toolkit/content/widgets/tabbox.xml

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 <?xml version="1.0"?>
     2 <!-- This Source Code Form is subject to the terms of the Mozilla Public
     3    - License, v. 2.0. If a copy of the MPL was not distributed with this
     4    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
     7 <bindings id="tabBindings"
     8           xmlns="http://www.mozilla.org/xbl"
     9           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    10           xmlns:xbl="http://www.mozilla.org/xbl">
    12   <binding id="tab-base">
    13     <resources>
    14       <stylesheet src="chrome://global/skin/tabbox.css"/>
    15     </resources>
    16   </binding>
    18   <binding id="tabbox"
    19            extends="chrome://global/content/bindings/tabbox.xml#tab-base">
    20     <implementation implements="nsIDOMEventListener">
    21       <property name="handleCtrlTab">
    22         <setter>
    23         <![CDATA[
    24           this.setAttribute("handleCtrlTab", val);
    25           return val;
    26         ]]>
    27         </setter>
    28         <getter>
    29         <![CDATA[
    30           return (this.getAttribute("handleCtrlTab") != "false");
    31         ]]>
    32         </getter>
    33       </property>
    35       <property name="handleCtrlPageUpDown">
    36         <setter>
    37         <![CDATA[
    38           this.setAttribute("handleCtrlPageUpDown", val);
    39           return val;
    40         ]]>
    41         </setter>
    42         <getter>
    43         <![CDATA[
    44           return (this.getAttribute("handleCtrlPageUpDown") != "false");
    45         ]]>
    46         </getter>
    47       </property>
    49       <field name="_handleMetaAltArrows" readonly="true">
    50 #ifdef XP_MACOSX
    51         true
    52 #else
    53         false
    54 #endif
    55       </field>
    57       <!-- _tabs and _tabpanels are deprecated, they exist only for
    58            backwards compatibility. -->
    59       <property name="_tabs" readonly="true" onget="return this.tabs;"/>
    60       <property name="_tabpanels" readonly="true" onget="return this.tabpanels;"/>
    62       <property name="tabs" readonly="true">
    63         <getter>
    64         <![CDATA[
    65           return this.getElementsByTagNameNS(
    66               "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
    67               "tabs").item(0);
    68         ]]>
    69         </getter>
    70       </property>
    72       <property name="tabpanels" readonly="true">
    73         <getter>
    74         <![CDATA[
    75           return this.getElementsByTagNameNS(
    76               "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
    77               "tabpanels").item(0);
    78         ]]>
    79         </getter>
    80       </property>
    82       <property name="selectedIndex">
    83         <getter>
    84         <![CDATA[
    85           var tabs = this.tabs;
    86           return tabs ? tabs.selectedIndex : -1;
    87         ]]>
    88         </getter>
    90         <setter>
    91         <![CDATA[
    92           var tabs = this.tabs;
    93           if (tabs)
    94             tabs.selectedIndex = val;
    95           this.setAttribute("selectedIndex", val);
    96           return val;
    97         ]]>
    98         </setter>
    99       </property>
   101       <property name="selectedTab">
   102         <getter>
   103         <![CDATA[
   104           var tabs = this.tabs;
   105           return tabs && tabs.selectedItem;
   106         ]]>
   107         </getter>
   109         <setter>
   110         <![CDATA[
   111           if (val) {
   112             var tabs = this.tabs;
   113             if (tabs)
   114               tabs.selectedItem = val;
   115           }
   116           return val;
   117         ]]>
   118         </setter>
   119       </property>
   121       <property name="selectedPanel">
   122         <getter>
   123         <![CDATA[
   124           var tabpanels = this.tabpanels;
   125           return tabpanels && tabpanels.selectedPanel;
   126         ]]>
   127         </getter>
   129         <setter>
   130         <![CDATA[
   131           if (val) {
   132             var tabpanels = this.tabpanels;
   133             if (tabpanels)
   134               tabpanels.selectedPanel = val;
   135           }
   136           return val;
   137         ]]>
   138         </setter>
   139       </property>
   141       <method name="handleEvent">
   142         <parameter name="event"/>
   143         <body>
   144         <![CDATA[
   145           if (!event.isTrusted) {
   146             // Don't let untrusted events mess with tabs.
   147             return;
   148           }
   150           switch (event.keyCode) {
   151             case event.DOM_VK_TAB:
   152               if (event.ctrlKey && !event.altKey && !event.metaKey)
   153                 if (this.tabs && this.handleCtrlTab) {
   154                   this.tabs.advanceSelectedTab(event.shiftKey ? -1 : 1, true);
   155                   event.stopPropagation();
   156                   event.preventDefault();
   157                 }
   158               break;
   159             case event.DOM_VK_PAGE_UP:
   160               if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey)
   161                 if (this.tabs && this.handleCtrlPageUpDown) {
   162                   this.tabs.advanceSelectedTab(-1, true);
   163                   event.stopPropagation();
   164                   event.preventDefault();
   165                 }
   166               break;
   167             case event.DOM_VK_PAGE_DOWN:
   168               if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey)
   169                 if (this.tabs && this.handleCtrlPageUpDown) {
   170                   this.tabs.advanceSelectedTab(1, true);
   171                   event.stopPropagation();
   172                   event.preventDefault();
   173                 }
   174               break;
   175             case event.DOM_VK_LEFT:
   176               if (event.metaKey && event.altKey && !event.shiftKey && !event.ctrlKey)
   177                 if (this.tabs && this._handleMetaAltArrows) {
   178                   var offset = window.getComputedStyle(this, "")
   179                                      .direction == "ltr" ? -1 : 1;
   180                   this.tabs.advanceSelectedTab(offset, true);
   181                   event.stopPropagation();
   182                   event.preventDefault();
   183                 }
   184               break;
   185             case event.DOM_VK_RIGHT:
   186               if (event.metaKey && event.altKey && !event.shiftKey && !event.ctrlKey)
   187                 if (this.tabs && this._handleMetaAltArrows) {
   188                   var offset = window.getComputedStyle(this, "")
   189                                      .direction == "ltr" ? 1 : -1;
   190                   this.tabs.advanceSelectedTab(offset, true);
   191                   event.stopPropagation();
   192                   event.preventDefault();
   193                 }
   194               break;
   195           }
   196         ]]>
   197         </body>
   198       </method>
   200       <field name="_eventNode">this</field>
   202       <property name="eventNode" onget="return this._eventNode;">
   203         <setter>
   204           <![CDATA[
   205             if (val != this._eventNode) {
   206               val.addEventListener("keypress", this, false);
   207               this._eventNode.removeEventListener("keypress", this, false);
   208               this._eventNode = val;
   209             }
   210             return val;
   211           ]]>
   212         </setter>
   213       </property>
   215       <constructor>
   216         switch (this.getAttribute("eventnode")) {
   217           case "parent": this._eventNode = this.parentNode; break;
   218           case "window": this._eventNode = window; break;
   219           case "document": this._eventNode = document; break;
   220         }
   221         this._eventNode.addEventListener("keypress", this, false);
   222       </constructor>
   224       <destructor>
   225         this._eventNode.removeEventListener("keypress", this, false);
   226       </destructor>
   227     </implementation>
   228   </binding>
   230   <binding id="tabs" role="xul:tabs"
   231            extends="chrome://global/content/bindings/general.xml#basecontrol">
   232     <resources>
   233       <stylesheet src="chrome://global/skin/tabbox.css"/>
   234     </resources>
   236     <content>
   237       <xul:spacer class="tabs-left"/>
   238       <children/>
   239       <xul:spacer class="tabs-right" flex="1"/>
   240     </content>
   242     <implementation implements="nsIDOMXULSelectControlElement, nsIDOMXULRelatedElement">
   243       <constructor>
   244       <![CDATA[
   245         // first and last tabs need to be able to have unique styles
   246         // and also need to select first tab on startup.
   247         if (this.firstChild)
   248           this.firstChild.setAttribute("first-tab", "true");
   249         if (this.lastChild)
   250           this.lastChild.setAttribute("last-tab", "true");
   252         if (!this.hasAttribute("orient"))
   253           this.setAttribute("orient", "horizontal");
   255         if (this.tabbox && this.tabbox.hasAttribute("selectedIndex")) {
   256           let selectedIndex = parseInt(this.tabbox.getAttribute("selectedIndex"));
   257           this.selectedIndex = selectedIndex > 0 ? selectedIndex : 0;
   258           return;
   259         }
   261         var children = this.childNodes;
   262         var length = children.length;
   263         for (var i = 0; i < length; i++) {
   264           if (children[i].getAttribute("selected") == "true") {
   265             this.selectedIndex = i;
   266             return;
   267           }
   268         }
   270         var value = this.value;
   271         if (value)
   272           this.value = value;
   273         else
   274           this.selectedIndex = 0;
   275       ]]>
   276       </constructor>
   278       <!-- nsIDOMXULRelatedElement -->
   279       <method name="getRelatedElement">
   280         <parameter name="aTabElm"/>
   281         <body>
   282         <![CDATA[
   283           if (!aTabElm)
   284             return null;
   286           let tabboxElm = this.tabbox;
   287           if (!tabboxElm)
   288             return null;
   290           let tabpanelsElm = tabboxElm.tabpanels;
   291           if (!tabpanelsElm)
   292             return null;
   294           // Get linked tab panel by 'linkedpanel' attribute on the given tab
   295           // element.
   296           let linkedPanelElm = null;
   298           let linkedPanelId = aTabElm.linkedPanel;
   299           if (linkedPanelId) {
   300             let ownerDoc = this.ownerDocument;
   302             // XXX bug 565858: if XUL tab element is anonymous element then
   303             // suppose linked tab panel is hosted within the same XBL binding
   304             // and search it by ID attribute inside an anonymous content of
   305             // the binding. This is not robust assumption since tab elements may
   306             // live outside a tabbox element so that for example tab elements
   307             // can be explicit content but tab panels can be anonymous.
   309             let bindingParent = ownerDoc.getBindingParent(aTabElm);
   310             if (bindingParent)
   311               return ownerDoc.getAnonymousElementByAttribute(bindingParent,
   312                                                              "id",
   313                                                              linkedPanelId);
   315             return ownerDoc.getElementById(linkedPanelId);
   316           }
   318           // otherwise linked tabpanel element has the same index as the given
   319           // tab element.
   320           let tabElmIdx = this.getIndexOfItem(aTabElm);
   321           return tabpanelsElm.childNodes[tabElmIdx];
   322         ]]>
   323         </body>
   324       </method>
   326       <!-- nsIDOMXULSelectControlElement -->
   327       <property name="itemCount" readonly="true"
   328                 onget="return this.childNodes.length"/>
   330       <property name="value" onget="return this.getAttribute('value');">
   331         <setter>
   332           <![CDATA[
   333             this.setAttribute("value", val);
   334             var children = this.childNodes;
   335             for (var c = children.length - 1; c >= 0; c--) {
   336               if (children[c].value == val) {
   337                 this.selectedIndex = c;
   338                 break;
   339               }
   340             }
   341             return val;
   342           ]]>
   343         </setter>
   344       </property>
   346       <field name="tabbox" readonly="true"><![CDATA[
   347         var parent = this.parentNode;
   348         while (parent) {
   349           if (parent.localName == "tabbox")
   350             break;
   351           parent = parent.parentNode;
   352         }
   353         parent;
   354       ]]></field>
   356       <!-- _tabbox is deprecated, it exists only for backwards compatibility. -->
   357       <field name="_tabbox" readonly="true"><![CDATA[
   358         this.tabbox;
   359       ]]></field>
   361       <property name="selectedIndex">
   362         <getter>
   363         <![CDATA[
   364           const tabs = this.childNodes;
   365           for (var i = 0; i < tabs.length; i++) {
   366             if (tabs[i].selected)
   367               return i;
   368           }
   369           return -1;
   370         ]]>
   371         </getter>
   373         <setter>
   374         <![CDATA[
   375           var tab = this.getItemAtIndex(val);
   376           if (tab) {
   377             var alreadySelected = tab.selected;
   379             Array.forEach(this.childNodes, function (aTab) {
   380               if (aTab.selected && aTab != tab)
   381                 aTab._selected = false;
   382             });
   383             tab._selected = true;
   385             this.setAttribute("value", tab.value);
   387             let linkedPanel = this.getRelatedElement(tab);
   388             if (linkedPanel) {
   389               this.tabbox.setAttribute("selectedIndex", val);
   391               // This will cause an onselect event to fire for the tabpanel
   392               // element.
   393               this.tabbox.tabpanels.selectedPanel = linkedPanel;
   394             }
   396             if (!alreadySelected) {
   397               // Fire an onselect event for the tabs element.
   398               var event = document.createEvent('Events');
   399               event.initEvent('select', true, true);
   400               this.dispatchEvent(event);
   401             }
   402           }
   403           return val;
   404         ]]>
   405         </setter>
   406       </property>
   408       <property name="selectedItem">
   409         <getter>
   410         <![CDATA[
   411           const tabs = this.childNodes;
   412           for (var i = 0; i < tabs.length; i++) {
   413             if (tabs[i].selected)
   414               return tabs[i];
   415           }
   416           return null;
   417         ]]>
   418         </getter>
   420         <setter>
   421         <![CDATA[
   422           if (val && !val.selected)
   423             // The selectedIndex setter ignores invalid values
   424             // such as -1 if |val| isn't one of our child nodes.
   425             this.selectedIndex = this.getIndexOfItem(val);
   426           return val;
   427         ]]>
   428         </setter>
   429       </property>
   431       <method name="getIndexOfItem">
   432         <parameter name="item"/>
   433         <body>
   434         <![CDATA[
   435           return Array.indexOf(this.childNodes, item);
   436         ]]>
   437         </body>
   438       </method>
   440       <method name="getItemAtIndex">
   441         <parameter name="index"/>
   442         <body>
   443         <![CDATA[
   444           return this.childNodes.item(index);
   445         ]]>
   446         </body>
   447       </method>
   449       <method name="_selectNewTab">
   450         <parameter name="aNewTab"/>
   451         <parameter name="aFallbackDir"/>
   452         <parameter name="aWrap"/>
   453         <body>
   454         <![CDATA[
   455           var requestedTab = aNewTab;
   456           while (aNewTab.hidden || aNewTab.disabled || !this._canAdvanceToTab(aNewTab)) {
   457             aNewTab = aFallbackDir == -1 ? aNewTab.previousSibling : aNewTab.nextSibling;
   458             if (!aNewTab && aWrap)
   459               aNewTab = aFallbackDir == -1 ? this.childNodes[this.childNodes.length - 1] :
   460                                              this.childNodes[0];
   461             if (!aNewTab || aNewTab == requestedTab)
   462               return;
   463           }
   465           var isTabFocused = false;
   466           try {
   467             isTabFocused =
   468               (document.commandDispatcher.focusedElement == this.selectedItem);
   469           } catch (e) {}
   470           this.selectedItem = aNewTab;
   471           if (isTabFocused) {
   472             aNewTab.focus();
   473           }
   474           else if (this.getAttribute("setfocus") != "false") {
   475             let selectedPanel = this.tabbox.selectedPanel;
   476             document.commandDispatcher.advanceFocusIntoSubtree(selectedPanel);
   478             // Make sure that the focus doesn't move outside the tabbox
   479             if (this.tabbox) {
   480               try {
   481                 let el = document.commandDispatcher.focusedElement;
   482                 while (el && el != this.tabbox.tabpanels) {
   483                   if (el == this.tabbox || el == selectedPanel)
   484                     return;
   485                   el = el.parentNode;
   486                 }
   487                 aNewTab.focus();
   488               } catch(e) {
   489               }
   490             }
   491           }
   492         ]]>
   493         </body>
   494       </method>
   496       <method name="_canAdvanceToTab">
   497         <parameter name="aTab"/>
   498         <body>
   499         <![CDATA[
   500           return true;
   501         ]]>
   502         </body>
   503       </method>
   505       <method name="advanceSelectedTab">
   506         <parameter name="aDir"/>
   507         <parameter name="aWrap"/>
   508         <body>
   509         <![CDATA[
   510           var startTab = this.selectedItem;
   511           var next = startTab[aDir == -1 ? "previousSibling" : "nextSibling"];
   512           if (!next && aWrap) {
   513             next = aDir == -1 ? this.childNodes[this.childNodes.length - 1] :
   514                                 this.childNodes[0];
   515           }
   516           if (next && next != startTab) {
   517             this._selectNewTab(next, aDir, aWrap);
   518           }
   519         ]]>
   520         </body>
   521       </method>
   523       <method name="appendItem">
   524         <parameter name="label"/>
   525         <parameter name="value"/>
   526         <body>
   527         <![CDATA[
   528           var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
   529           var tab = document.createElementNS(XULNS, "tab");
   530           tab.setAttribute("label", label);
   531           tab.setAttribute("value", value);
   532           this.appendChild(tab);
   533           return tab;
   534         ]]>
   535         </body>
   536       </method>
   538       <method name="insertItemAt">
   539         <parameter name="index"/>
   540         <parameter name="label"/>
   541         <parameter name="value"/>
   542         <body>
   543         <![CDATA[
   544           var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
   545           var tab = document.createElementNS(XULNS, "tab");
   546           tab.setAttribute("label", label);
   547           tab.setAttribute("value", value);
   548           var before = this.getItemAtIndex(index);
   549           if (before)
   550             this.insertBefore(tab, before);
   551           else
   552             this.appendChild(tab);
   553           return tab;
   554         ]]>
   555         </body>
   556       </method>
   558       <method name="removeItemAt">
   559         <parameter name="index"/>
   560         <body>
   561         <![CDATA[
   562           var remove = this.getItemAtIndex(index);
   563           if (remove)
   564             this.removeChild(remove);
   565           return remove;
   566         ]]>
   567         </body>
   568       </method>
   569     </implementation>
   571 #ifdef MOZ_WIDGET_GTK
   572     <handlers>
   573       <handler event="DOMMouseScroll">
   574       <![CDATA[
   575         if (event.detail > 0)
   576           this.advanceSelectedTab(1, false);
   577         else
   578           this.advanceSelectedTab(-1, false);
   580         event.stopPropagation();
   581       ]]>
   582       </handler>
   583     </handlers>
   584 #endif
   585   </binding>
   587   <binding id="tabpanels" role="xul:tabpanels"
   588            extends="chrome://global/content/bindings/tabbox.xml#tab-base">
   589     <implementation implements="nsIDOMXULRelatedElement">
   590       <!-- nsIDOMXULRelatedElement -->
   591       <method name="getRelatedElement">
   592         <parameter name="aTabPanelElm"/>
   593         <body>
   594         <![CDATA[
   595           if (!aTabPanelElm)
   596             return null;
   598           let tabboxElm = this.tabbox;
   599           if (!tabboxElm)
   600             return null;
   602           let tabsElm = tabboxElm.tabs;
   603           if (!tabsElm)
   604             return null;
   606           // Return tab element having 'linkedpanel' attribute equal to the id
   607           // of the tab panel or the same index as the tab panel element.
   608           let tabpanelIdx = Array.indexOf(this.childNodes, aTabPanelElm);
   609           if (tabpanelIdx == -1)
   610             return null;
   612           let tabElms = tabsElm.childNodes;
   613           let tabElmFromIndex = tabElms[tabpanelIdx];
   615           let tabpanelId = aTabPanelElm.id;
   616           if (tabpanelId) {
   617             for (let idx = 0; idx < tabElms.length; idx++) {
   618               var tabElm = tabElms[idx];
   619               if (tabElm.linkedPanel == tabpanelId)
   620                 return tabElm;
   621             }
   622           }
   624           return tabElmFromIndex;
   625         ]]>
   626         </body>
   627       </method>
   629       <!-- public -->
   630       <field name="tabbox" readonly="true"><![CDATA[
   631         var parent = this.parentNode;
   632         while (parent) {
   633           if (parent.localName == "tabbox")
   634             break;
   635           parent = parent.parentNode;
   636         }
   637         parent;
   638       ]]></field>
   640       <field name="_selectedPanel">this.childNodes.item(this.selectedIndex)</field>
   642       <property name="selectedIndex">
   643         <getter>
   644         <![CDATA[
   645           var indexStr = this.getAttribute("selectedIndex");
   646           return indexStr ? parseInt(indexStr) : -1;
   647         ]]>
   648         </getter>
   650         <setter>
   651         <![CDATA[
   652           if (val < 0 || val >= this.childNodes.length)
   653             return val;
   654           var panel = this._selectedPanel;
   655           this._selectedPanel = this.childNodes[val];
   656           this.setAttribute("selectedIndex", val);
   657           if (this._selectedPanel != panel) {
   658             var event = document.createEvent("Events");
   659             event.initEvent("select", true, true);
   660             this.dispatchEvent(event);
   661           }
   662           return val;
   663         ]]>
   664         </setter>
   665       </property>
   667       <property name="selectedPanel">
   668         <getter>
   669           <![CDATA[
   670             return this._selectedPanel;
   671           ]]>
   672         </getter>
   674         <setter>
   675           <![CDATA[
   676             var selectedIndex = -1;
   677             for (var panel = val; panel != null; panel = panel.previousSibling)
   678               ++selectedIndex;
   679             this.selectedIndex = selectedIndex;
   680             return val;
   681           ]]>
   682         </setter>
   683       </property>
   684     </implementation>
   685   </binding>
   687   <binding id="tab" display="xul:button" role="xul:tab"
   688            extends="chrome://global/content/bindings/general.xml#control-item">
   689     <resources>
   690       <stylesheet src="chrome://global/skin/tabbox.css"/>
   691     </resources>
   693     <content>
   694       <xul:hbox class="tab-middle box-inherit" xbl:inherits="align,dir,pack,orient,selected" flex="1">
   695         <xul:image class="tab-icon"
   696                    xbl:inherits="validate,src=image"
   697                    role="presentation"/>
   698         <xul:label class="tab-text"
   699                    xbl:inherits="value=label,accesskey,crop,disabled"
   700                    flex="1"
   701                    role="presentation"/>
   702       </xul:hbox>
   703     </content>
   705     <implementation implements="nsIDOMXULSelectControlItemElement">
   706       <property name="control" readonly="true">
   707         <getter>
   708           <![CDATA[
   709             var parent = this.parentNode;
   710             if (parent instanceof Components.interfaces.nsIDOMXULSelectControlElement)
   711               return parent;
   712             return null;
   713           ]]>
   714         </getter>
   715       </property>
   717       <property name="selected" readonly="true"
   718                 onget="return this.getAttribute('selected') == 'true';"/>
   720       <property name="_selected">
   721         <setter>
   722           <![CDATA[
   723           if (val)
   724             this.setAttribute("selected", "true");
   725           else
   726             this.removeAttribute("selected");
   728           if (this.previousSibling && this.previousSibling.localName == "tab") {
   729             if (val)
   730               this.previousSibling.setAttribute("beforeselected", "true");
   731             else
   732               this.previousSibling.removeAttribute("beforeselected");
   733             this.removeAttribute("first-tab");
   734           }
   735           else
   736             this.setAttribute("first-tab", "true");
   738           if (this.nextSibling && this.nextSibling.localName == "tab") {
   739             if (val)
   740               this.nextSibling.setAttribute("afterselected", "true");
   741             else
   742               this.nextSibling.removeAttribute("afterselected");
   743             this.removeAttribute("last-tab");
   744           }
   745           else
   746             this.setAttribute("last-tab", "true");
   747           return val;
   748         ]]>
   749         </setter>
   750       </property>
   752       <property name="linkedPanel" onget="return this.getAttribute('linkedpanel')"
   753                                    onset="this.setAttribute('linkedpanel', val); return val;"/>
   755       <field name="arrowKeysShouldWrap" readonly="true">
   756 #ifdef XP_MACOSX
   757         true
   758 #else
   759         false
   760 #endif
   761       </field>
   762       <field name="TelemetryStopwatch" readonly="true">
   763         let tmp = {};
   764         Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", tmp);
   765         tmp.TelemetryStopwatch;
   766       </field>
   767     </implementation>
   769     <handlers>
   770       <handler event="mousedown" button="0">
   771       <![CDATA[
   772         if (this.disabled)
   773           return;
   775         if (this != this.parentNode.selectedItem) { // Not selected yet
   776           let stopwatchid = this.parentNode.getAttribute("stopwatchid");
   777           if (stopwatchid) {
   778             this.TelemetryStopwatch.start(stopwatchid);
   779           }
   781           // Call this before setting the 'ignorefocus' attribute because this
   782           // will pass on focus if the formerly selected tab was focused as well.
   783           this.parentNode._selectNewTab(this);
   785           var isTabFocused = false;
   786           try {
   787             isTabFocused = (document.commandDispatcher.focusedElement == this);
   788           } catch (e) {}
   790           // Set '-moz-user-focus' to 'ignore' so that PostHandleEvent() can't
   791           // focus the tab; we only want tabs to be focusable by the mouse if
   792           // they are already focused. After a short timeout we'll reset
   793           // '-moz-user-focus' so that tabs can be focused by keyboard again.
   794           if (!isTabFocused) {
   795             this.setAttribute("ignorefocus", "true");
   796             setTimeout(function (tab) tab.removeAttribute("ignorefocus"), 0, this);
   797           }
   799           if (stopwatchid) {
   800             this.TelemetryStopwatch.finish(stopwatchid);
   801           }
   802         }
   803         // Otherwise this tab is already selected and we will fall
   804         // through to mousedown behavior which sets focus on the current tab,
   805         // Only a click on an already selected tab should focus the tab itself.
   806       ]]>
   807       </handler>
   809       <handler event="keypress" keycode="VK_LEFT">
   810       <![CDATA[
   811         var direction = window.getComputedStyle(this.parentNode, null).direction;
   812         this.parentNode.advanceSelectedTab(direction == 'ltr' ? -1 : 1, this.arrowKeysShouldWrap);
   813       ]]>
   814       </handler>
   816       <handler event="keypress" keycode="VK_RIGHT">
   817       <![CDATA[
   818         var direction = window.getComputedStyle(this.parentNode, null).direction;
   819         this.parentNode.advanceSelectedTab(direction == 'ltr' ? 1 : -1, this.arrowKeysShouldWrap);
   820       ]]>
   821       </handler>
   823       <handler event="keypress" keycode="VK_UP">
   824       <![CDATA[
   825         this.parentNode.advanceSelectedTab(-1, this.arrowKeysShouldWrap);
   826       ]]>
   827       </handler>
   829       <handler event="keypress" keycode="VK_DOWN">
   830       <![CDATA[
   831         this.parentNode.advanceSelectedTab(1, this.arrowKeysShouldWrap);
   832       ]]>
   833       </handler>
   835       <handler event="keypress" keycode="VK_HOME">
   836       <![CDATA[
   837         this.parentNode._selectNewTab(this.parentNode.childNodes[0]);
   838       ]]>
   839       </handler>
   841       <handler event="keypress" keycode="VK_END">
   842       <![CDATA[
   843         var tabs = this.parentNode.childNodes;
   844         this.parentNode._selectNewTab(tabs[tabs.length - 1], -1);
   845       ]]>
   846       </handler>
   847     </handlers>
   848   </binding>
   850 </bindings>

mercurial