browser/components/places/content/menu.xml

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 <?xml version="1.0"?>
     3 # This Source Code Form is subject to the terms of the Mozilla Public
     4 # License, v. 2.0. If a copy of the MPL was not distributed with this
     5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     7 <bindings id="placesMenuBindings"
     8           xmlns="http://www.mozilla.org/xbl"
     9           xmlns:xbl="http://www.mozilla.org/xbl"
    10           xmlns:html="http://www.w3.org/1999/xhtml"
    11           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    13   <binding id="places-popup-base"
    14            extends="chrome://global/content/bindings/popup.xml#popup">
    15     <content>
    16       <xul:hbox flex="1">
    17         <xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
    18           <xul:image class="menupopup-drop-indicator" mousethrough="always"/>
    19         </xul:vbox>
    20         <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
    21                             smoothscroll="false">
    22           <children/>
    23         </xul:arrowscrollbox>
    24       </xul:hbox>
    25     </content>
    27     <implementation>
    29       <field name="_indicatorBar">
    30         document.getAnonymousElementByAttribute(this, "class",
    31                                                 "menupopup-drop-indicator-bar");
    32       </field>
    34       <field name="_scrollBox">
    35         document.getAnonymousElementByAttribute(this, "class",
    36                                                 "popup-internal-box");
    37       </field>
    39       <!-- This is the view that manage the popup -->
    40       <field name="_rootView">PlacesUIUtils.getViewForNode(this);</field>
    42       <!-- Check if we should hide the drop indicator for the target -->
    43       <method name="_hideDropIndicator">
    44         <parameter name="aEvent"/>
    45         <body><![CDATA[
    46           let target = aEvent.target;
    48           // Don't draw the drop indicator outside of markers.
    49           // The markers are hidden, since otherwise sometimes popups acquire
    50           // scrollboxes on OS X, so we can't use them directly.
    51           let firstChildTop = this._startMarker.nextSibling.boxObject.y;
    52           let lastChildBottom = this._endMarker.previousSibling.boxObject.y +
    53                                 this._endMarker.previousSibling.boxObject.height;
    54           let betweenMarkers = target.boxObject.y >= firstChildTop ||
    55                                target.boxObject.y <= lastChildBottom;
    57           // Hide the dropmarker if current node is not a Places node.
    58           return !(target && target._placesNode && betweenMarkers);
    59         ]]></body>
    60       </method>
    62       <!-- This function returns information about where to drop when
    63            dragging over this popup insertion point -->
    64       <method name="_getDropPoint">
    65         <parameter name="aEvent"/>
    66           <body><![CDATA[
    67             // Can't drop if the menu isn't a folder
    68             let resultNode = this._placesNode;
    70             if (!PlacesUtils.nodeIsFolder(resultNode) ||
    71                 PlacesControllerDragHelper.disallowInsertion(resultNode)) {
    72               return null;
    73             }
    75             var dropPoint = { ip: null, folderElt: null };
    77             // The element we are dragging over
    78             let elt = aEvent.target;
    79             if (elt.localName == "menupopup")
    80               elt = elt.parentNode;
    82             // Calculate positions taking care of arrowscrollbox
    83             let scrollbox = this._scrollBox;
    84             let eventY = aEvent.layerY + (scrollbox.boxObject.y - this.boxObject.y);
    85             let scrollboxOffset = scrollbox.scrollBoxObject.y -
    86                                   (scrollbox.boxObject.y - this.boxObject.y);
    87             let eltY = elt.boxObject.y - scrollboxOffset;
    88             let eltHeight = elt.boxObject.height;
    90             if (!elt._placesNode) {
    91               // If we are dragging over a non places node drop at the end.
    92               dropPoint.ip = new InsertionPoint(
    93                                   PlacesUtils.getConcreteItemId(resultNode),
    94                                   -1,
    95                                   Ci.nsITreeView.DROP_ON);
    96               // We can set folderElt if we are dropping over a static menu that
    97               // has an internal placespopup.
    98               let isMenu = elt.localName == "menu" ||
    99                  (elt.localName == "toolbarbutton" &&
   100                   elt.getAttribute("type") == "menu");
   101               if (isMenu && elt.lastChild &&
   102                   elt.lastChild.hasAttribute("placespopup"))
   103                 dropPoint.folderElt = elt;
   104               return dropPoint;
   105             }
   106             else if ((PlacesUtils.nodeIsFolder(elt._placesNode) ||
   107                       PlacesUtils.nodeIsTagQuery(elt._placesNode)) &&
   108                      !PlacesUtils.nodeIsReadOnly(elt._placesNode)) {
   109               // This is a folder or a tag container.
   110               if (eventY - eltY < eltHeight * 0.20) {
   111                 // If mouse is in the top part of the element, drop above folder.
   112                 dropPoint.ip = new InsertionPoint(
   113                                     PlacesUtils.getConcreteItemId(resultNode),
   114                                     -1,
   115                                     Ci.nsITreeView.DROP_BEFORE,
   116                                     PlacesUtils.nodeIsTagQuery(elt._placesNode),
   117                                     elt._placesNode.itemId);
   118                 return dropPoint;
   119               }
   120               else if (eventY - eltY < eltHeight * 0.80) {
   121                 // If mouse is in the middle of the element, drop inside folder.
   122                 dropPoint.ip = new InsertionPoint(
   123                                     PlacesUtils.getConcreteItemId(elt._placesNode),
   124                                     -1,
   125                                     Ci.nsITreeView.DROP_ON,
   126                                     PlacesUtils.nodeIsTagQuery(elt._placesNode));
   127                 dropPoint.folderElt = elt;
   128                 return dropPoint;
   129               }
   130             }
   131             else if (eventY - eltY <= eltHeight / 2) {
   132               // This is a non-folder node or a readonly folder.
   133               // If the mouse is above the middle, drop above this item.
   134               dropPoint.ip = new InsertionPoint(
   135                                   PlacesUtils.getConcreteItemId(resultNode),
   136                                   -1,
   137                                   Ci.nsITreeView.DROP_BEFORE,
   138                                   PlacesUtils.nodeIsTagQuery(elt._placesNode),
   139                                   elt._placesNode.itemId);
   140               return dropPoint;
   141             }
   143             // Drop below the item.
   144             dropPoint.ip = new InsertionPoint(
   145                                 PlacesUtils.getConcreteItemId(resultNode),
   146                                 -1,
   147                                 Ci.nsITreeView.DROP_AFTER,
   148                                 PlacesUtils.nodeIsTagQuery(elt._placesNode),
   149                                 elt._placesNode.itemId);
   150             return dropPoint;
   151         ]]></body>
   152       </method>
   154       <!-- Sub-menus should be opened when the mouse drags over them, and closed
   155            when the mouse drags off.  The overFolder object manages opening and
   156            closing of folders when the mouse hovers. -->
   157       <field name="_overFolder"><![CDATA[({
   158         _self: this,
   159         _folder: {elt: null,
   160                   openTimer: null,
   161                   hoverTime: 350,
   162                   closeTimer: null},
   163         _closeMenuTimer: null,
   165         get elt() {
   166           return this._folder.elt;
   167         },
   168         set elt(val) {
   169           return this._folder.elt = val;
   170         },
   172         get openTimer() {
   173           return this._folder.openTimer;
   174         },
   175         set openTimer(val) {
   176           return this._folder.openTimer = val;
   177         },
   179         get hoverTime() {
   180           return this._folder.hoverTime;
   181         },
   182         set hoverTime(val) {
   183           return this._folder.hoverTime = val;
   184         },
   186         get closeTimer() {
   187           return this._folder.closeTimer;
   188         },
   189         set closeTimer(val) {
   190           return this._folder.closeTimer = val;
   191         },
   193         get closeMenuTimer() {
   194           return this._closeMenuTimer;
   195         },
   196         set closeMenuTimer(val) {
   197           return this._closeMenuTimer = val;
   198         },
   200         setTimer: function OF__setTimer(aTime) {
   201           var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   202           timer.initWithCallback(this, aTime, timer.TYPE_ONE_SHOT);
   203           return timer;
   204         },
   206         notify: function OF__notify(aTimer) {
   207           // Function to process all timer notifications.
   209           if (aTimer == this._folder.openTimer) {
   210             // Timer to open a submenu that's being dragged over.
   211             this._folder.elt.lastChild.setAttribute("autoopened", "true");
   212             this._folder.elt.lastChild.showPopup(this._folder.elt);
   213             this._folder.openTimer = null;
   214           }
   216           else if (aTimer == this._folder.closeTimer) {
   217             // Timer to close a submenu that's been dragged off of.
   218             // Only close the submenu if the mouse isn't being dragged over any
   219             // of its child menus.
   220             var draggingOverChild = PlacesControllerDragHelper
   221                                     .draggingOverChildNode(this._folder.elt);
   222             if (draggingOverChild)
   223               this._folder.elt = null;
   224             this.clear();
   226             // Close any parent folders which aren't being dragged over.
   227             // (This is necessary because of the above code that keeps a folder
   228             // open while its children are being dragged over.)
   229             if (!draggingOverChild)
   230               this.closeParentMenus();
   231           }
   233           else if (aTimer == this.closeMenuTimer) {
   234             // Timer to close this menu after the drag exit.
   235             var popup = this._self;
   236             // if we are no more dragging we can leave the menu open to allow
   237             // for better D&D bookmark organization
   238             if (PlacesControllerDragHelper.getSession() &&
   239                 !PlacesControllerDragHelper.draggingOverChildNode(popup.parentNode)) {
   240               popup.hidePopup();
   241               // Close any parent menus that aren't being dragged over;
   242               // otherwise they'll stay open because they couldn't close
   243               // while this menu was being dragged over.
   244               this.closeParentMenus();
   245             }
   246             this._closeMenuTimer = null;
   247           }
   248         },
   250         //  Helper function to close all parent menus of this menu,
   251         //  as long as none of the parent's children are currently being
   252         //  dragged over.
   253         closeParentMenus: function OF__closeParentMenus() {
   254           var popup = this._self;
   255           var parent = popup.parentNode;
   256           while (parent) {
   257             if (parent.localName == "menupopup" && parent._placesNode) {
   258               if (PlacesControllerDragHelper.draggingOverChildNode(parent.parentNode))
   259                 break;
   260               parent.hidePopup();
   261             }
   262             parent = parent.parentNode;
   263           }
   264         },
   266         //  The mouse is no longer dragging over the stored menubutton.
   267         //  Close the menubutton, clear out drag styles, and clear all
   268         //  timers for opening/closing it.
   269         clear: function OF__clear() {
   270           if (this._folder.elt && this._folder.elt.lastChild) {
   271             if (!this._folder.elt.lastChild.hasAttribute("dragover"))
   272               this._folder.elt.lastChild.hidePopup();
   273             // remove menuactive style
   274             this._folder.elt.removeAttribute("_moz-menuactive");
   275             this._folder.elt = null;
   276           }
   277           if (this._folder.openTimer) {
   278             this._folder.openTimer.cancel();
   279             this._folder.openTimer = null;
   280           }
   281           if (this._folder.closeTimer) {
   282             this._folder.closeTimer.cancel();
   283             this._folder.closeTimer = null;
   284           }
   285         }
   286       })]]></field>
   288       <method name="_cleanupDragDetails">
   289         <body><![CDATA[
   290           // Called on dragend and drop.
   291           PlacesControllerDragHelper.currentDropTarget = null;
   292           this._rootView._draggedElt = null;
   293           this.removeAttribute("dragover");
   294           this.removeAttribute("dragstart");
   295           this._indicatorBar.hidden = true;
   296         ]]></body>
   297       </method>
   299     </implementation>
   301     <handlers>
   302       <handler event="DOMMenuItemActive"><![CDATA[
   303         let elt = event.target;
   304         if (elt.parentNode != this)
   305           return;
   307 #ifdef XP_MACOSX
   308         // XXX: The following check is a temporary hack until bug 420033 is
   309         // resolved.
   310         let parentElt = elt.parent;
   311         while (parentElt) {
   312           if (parentElt.id == "bookmarksMenuPopup" ||
   313               parentElt.id == "goPopup")
   314             return;
   316           parentElt = parentElt.parentNode;
   317         }
   318 #endif
   320         if (window.XULBrowserWindow) {
   321           let elt = event.target;
   322           let placesNode = elt._placesNode;
   324           var linkURI;
   325           if (placesNode && PlacesUtils.nodeIsURI(placesNode))
   326             linkURI = placesNode.uri;
   327           else if (elt.hasAttribute("targetURI"))
   328             linkURI = elt.getAttribute("targetURI");
   330           if (linkURI)
   331             window.XULBrowserWindow.setOverLink(linkURI, null);
   332         }
   333       ]]></handler>
   335       <handler event="DOMMenuItemInactive"><![CDATA[
   336         let elt = event.target;
   337         if (elt.parentNode != this)
   338           return;
   340         if (window.XULBrowserWindow)
   341           window.XULBrowserWindow.setOverLink("", null);
   342       ]]></handler>
   344       <handler event="dragstart"><![CDATA[
   345         if (!event.target._placesNode)
   346           return;
   348         let draggedElt = event.target._placesNode;
   350         // Force a copy action if parent node is a query or we are dragging a
   351         // not-removable node.
   352         if (!PlacesControllerDragHelper.canMoveNode(draggedElt))
   353           event.dataTransfer.effectAllowed = "copyLink";
   355         // Activate the view and cache the dragged element.
   356         this._rootView._draggedElt = draggedElt;
   357         this._rootView.controller.setDataTransfer(event);
   358         this.setAttribute("dragstart", "true");
   359         event.stopPropagation();
   360       ]]></handler>
   362       <handler event="drop"><![CDATA[
   363         PlacesControllerDragHelper.currentDropTarget = event.target;
   365         let dropPoint = this._getDropPoint(event);
   366         if (dropPoint && dropPoint.ip) {
   367           PlacesControllerDragHelper.onDrop(dropPoint.ip, event.dataTransfer);
   368           event.preventDefault();
   369         }
   371         this._cleanupDragDetails();
   372         event.stopPropagation();
   373       ]]></handler>
   375       <handler event="dragover"><![CDATA[
   376         PlacesControllerDragHelper.currentDropTarget = event.target;
   377         let dt = event.dataTransfer;
   379         let dropPoint = this._getDropPoint(event);
   380         if (!dropPoint || !dropPoint.ip ||
   381             !PlacesControllerDragHelper.canDrop(dropPoint.ip, dt)) {
   382           this._indicatorBar.hidden = true;
   383           event.stopPropagation();
   384           return;
   385         }
   387         // Mark this popup as being dragged over.
   388         this.setAttribute("dragover", "true");
   390         if (dropPoint.folderElt) {
   391           // We are dragging over a folder.
   392           // _overFolder should take the care of opening it on a timer.
   393           if (this._overFolder.elt &&
   394               this._overFolder.elt != dropPoint.folderElt) {
   395             // We are dragging over a new folder, let's clear old values
   396             this._overFolder.clear();
   397           }
   398           if (!this._overFolder.elt) {
   399             this._overFolder.elt = dropPoint.folderElt;
   400             // Create the timer to open this folder.
   401             this._overFolder.openTimer = this._overFolder
   402                                              .setTimer(this._overFolder.hoverTime);
   403           }
   404           // Since we are dropping into a folder set the corresponding style.
   405           dropPoint.folderElt.setAttribute("_moz-menuactive", true);
   406         }
   407         else {
   408           // We are not dragging over a folder.
   409           // Clear out old _overFolder information.
   410           this._overFolder.clear();
   411         }
   413         // Autoscroll the popup strip if we drag over the scroll buttons.
   414         let anonid = event.originalTarget.getAttribute('anonid');
   415         let scrollDir = anonid == "scrollbutton-up" ? -1 :
   416                         anonid == "scrollbutton-down" ? 1 : 0;
   417         if (scrollDir != 0) {
   418           this._scrollBox.scrollByIndex(scrollDir, false);
   419         }
   421         // Check if we should hide the drop indicator for this target.
   422         if (dropPoint.folderElt || this._hideDropIndicator(event)) {
   423           this._indicatorBar.hidden = true;
   424           event.preventDefault();
   425           event.stopPropagation();
   426           return;
   427         }
   429         // We should display the drop indicator relative to the arrowscrollbox.
   430         let sbo = this._scrollBox.scrollBoxObject;
   431         let newMarginTop = 0;
   432         if (scrollDir == 0) {
   433           let elt = this.firstChild;
   434           while (elt && event.screenY > elt.boxObject.screenY +
   435                                         elt.boxObject.height / 2)
   436             elt = elt.nextSibling;
   437           newMarginTop = elt ? elt.boxObject.screenY - sbo.screenY :
   438                                sbo.height;
   439         }
   440         else if (scrollDir == 1)
   441           newMarginTop = sbo.height;
   443         // Set the new marginTop based on arrowscrollbox.
   444         newMarginTop += sbo.y - this._scrollBox.boxObject.y;
   445         this._indicatorBar.firstChild.style.marginTop = newMarginTop + "px";
   446         this._indicatorBar.hidden = false;
   448         event.preventDefault();
   449         event.stopPropagation();
   450       ]]></handler>
   452       <handler event="dragexit"><![CDATA[
   453         PlacesControllerDragHelper.currentDropTarget = null;
   454         this.removeAttribute("dragover");
   456         // If we have not moved to a valid new target clear the drop indicator
   457         // this happens when moving out of the popup.
   458         let target = event.relatedTarget;
   459         if (!target || !this.contains(target))
   460           this._indicatorBar.hidden = true;
   462         // Close any folder being hovered over
   463         if (this._overFolder.elt) {
   464           this._overFolder.closeTimer = this._overFolder
   465                                             .setTimer(this._overFolder.hoverTime);
   466         }
   468         // The autoopened attribute is set when this folder was automatically
   469         // opened after the user dragged over it.  If this attribute is set,
   470         // auto-close the folder on drag exit.
   471         // We should also try to close this popup if the drag has started
   472         // from here, the timer will check if we are dragging over a child.
   473         if (this.hasAttribute("autoopened") ||
   474             this.hasAttribute("dragstart")) {
   475           this._overFolder.closeMenuTimer = this._overFolder
   476                                                 .setTimer(this._overFolder.hoverTime);
   477         }
   479         event.stopPropagation();
   480       ]]></handler>
   482       <handler event="dragend"><![CDATA[
   483         this._cleanupDragDetails();
   484       ]]></handler>
   486     </handlers>
   487   </binding>
   489   <!-- Most of this is copied from the arrowpanel binding in popup.xml -->
   490   <binding id="places-popup-arrow"
   491            extends="chrome://browser/content/places/menu.xml#places-popup-base">
   492     <content flip="both" side="top" position="bottomcenter topright">
   493       <xul:vbox anonid="container" class="panel-arrowcontainer" flex="1"
   494                xbl:inherits="side,panelopen">
   495         <xul:box anonid="arrowbox" class="panel-arrowbox">
   496           <xul:image anonid="arrow" class="panel-arrow" xbl:inherits="side"/>
   497         </xul:box>
   498         <xul:box class="panel-arrowcontent" xbl:inherits="side,align,dir,orient,pack" flex="1">
   499           <xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
   500             <xul:image class="menupopup-drop-indicator" mousethrough="always"/>
   501           </xul:vbox>
   502           <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
   503                               smoothscroll="false">
   504             <children/>
   505           </xul:arrowscrollbox>
   506         </xul:box>
   507       </xul:vbox>
   508     </content>
   510     <implementation>
   511       <constructor><![CDATA[
   512         this.style.pointerEvents = 'none';
   513       ]]></constructor>
   514       <method name="adjustArrowPosition">
   515         <body><![CDATA[
   516           var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
   518           var anchor = this.anchorNode;
   519           if (!anchor) {
   520             arrow.hidden = true;
   521             return;
   522           }
   524           var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
   525           var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
   527           var position = this.alignmentPosition;
   528           var offset = this.alignmentOffset;
   530           // if this panel has a "sliding" arrow, we may have previously set margins...
   531           arrowbox.style.removeProperty("transform");
   532           if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
   533             container.orient = "horizontal";
   534             arrowbox.orient = "vertical";
   535             if (position.indexOf("_after") > 0) {
   536               arrowbox.pack = "end";
   537             } else {
   538               arrowbox.pack = "start";
   539             }
   540             arrowbox.style.transform = "translate(0, " + -offset + "px)";
   542             // The assigned side stays the same regardless of direction.
   543             var isRTL = (window.getComputedStyle(this).direction == "rtl");
   545             if (position.indexOf("start_") == 0) {
   546               container.dir = "reverse";
   547               this.setAttribute("side", isRTL ? "left" : "right");
   548             }
   549             else {
   550               container.dir = "";
   551               this.setAttribute("side", isRTL ? "right" : "left");
   552             }
   553           }
   554           else if (position.indexOf("before_") == 0 || position.indexOf("after_") == 0) {
   555             container.orient = "";
   556             arrowbox.orient = "";
   557             if (position.indexOf("_end") > 0) {
   558               arrowbox.pack = "end";
   559             } else {
   560               arrowbox.pack = "start";
   561             }
   562             arrowbox.style.transform = "translate(" + -offset + "px, 0)";
   564             if (position.indexOf("before_") == 0) {
   565               container.dir = "reverse";
   566               this.setAttribute("side", "bottom");
   567             }
   568             else {
   569               container.dir = "";
   570               this.setAttribute("side", "top");
   571             }
   572           }
   574           arrow.hidden = false;
   575         ]]></body>
   576       </method>
   577     </implementation>
   579     <handlers>
   580       <handler event="popupshowing" phase="target"><![CDATA[
   581         this.adjustArrowPosition();
   582       ]]></handler>
   583       <handler event="popupshown" phase="target"><![CDATA[
   584         this.setAttribute("panelopen", "true");
   585         let disablePointerEvents;
   586         if (!this.hasAttribute("disablepointereventsfortransition")) {
   587           let container = document.getAnonymousElementByAttribute(this, "anonid", "container");
   588           let cs = getComputedStyle(container);
   589           let transitionProp = cs.transitionProperty;
   590           let transitionTime = parseFloat(cs.transitionDuration);
   591           disablePointerEvents = (transitionProp.contains("transform") ||
   592                                   transitionProp == "all") &&
   593                                  transitionTime > 0;
   594           this.setAttribute("disablepointereventsfortransition", disablePointerEvents);
   595         } else {
   596           disablePointerEvents = this.getAttribute("disablepointereventsfortransition") == "true";
   597         }
   598         if (!disablePointerEvents) {
   599           this.style.removeProperty("pointer-events");
   600         }
   601       ]]></handler>
   602       <handler event="transitionend"><![CDATA[
   603         if (event.originalTarget.getAttribute("anonid") == "container" &&
   604             event.propertyName == "transform") {
   605           this.style.removeProperty("pointer-events");
   606         }
   607       ]]></handler>
   608       <handler event="popuphidden" phase="target"><![CDATA[
   609         this.removeAttribute("panelopen");
   610         if (this.getAttribute("disablepointereventsfortransition") == "true") {
   611           this.style.pointerEvents = 'none';
   612         }
   613       ]]></handler>
   614     </handlers>
   615   </binding>
   616 </bindings>

mercurial