browser/components/places/content/menu.xml

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/components/places/content/menu.xml	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,616 @@
     1.4 +<?xml version="1.0"?>
     1.5 +
     1.6 +# This Source Code Form is subject to the terms of the Mozilla Public
     1.7 +# License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.9 +
    1.10 +<bindings id="placesMenuBindings"
    1.11 +          xmlns="http://www.mozilla.org/xbl"
    1.12 +          xmlns:xbl="http://www.mozilla.org/xbl"
    1.13 +          xmlns:html="http://www.w3.org/1999/xhtml"
    1.14 +          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    1.15 +
    1.16 +  <binding id="places-popup-base"
    1.17 +           extends="chrome://global/content/bindings/popup.xml#popup">
    1.18 +    <content>
    1.19 +      <xul:hbox flex="1">
    1.20 +        <xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
    1.21 +          <xul:image class="menupopup-drop-indicator" mousethrough="always"/>
    1.22 +        </xul:vbox>
    1.23 +        <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
    1.24 +                            smoothscroll="false">
    1.25 +          <children/>
    1.26 +        </xul:arrowscrollbox>
    1.27 +      </xul:hbox>
    1.28 +    </content>
    1.29 +
    1.30 +    <implementation>
    1.31 +
    1.32 +      <field name="_indicatorBar">
    1.33 +        document.getAnonymousElementByAttribute(this, "class",
    1.34 +                                                "menupopup-drop-indicator-bar");
    1.35 +      </field>
    1.36 +
    1.37 +      <field name="_scrollBox">
    1.38 +        document.getAnonymousElementByAttribute(this, "class",
    1.39 +                                                "popup-internal-box");
    1.40 +      </field>
    1.41 +
    1.42 +      <!-- This is the view that manage the popup -->
    1.43 +      <field name="_rootView">PlacesUIUtils.getViewForNode(this);</field>
    1.44 +
    1.45 +      <!-- Check if we should hide the drop indicator for the target -->
    1.46 +      <method name="_hideDropIndicator">
    1.47 +        <parameter name="aEvent"/>
    1.48 +        <body><![CDATA[
    1.49 +          let target = aEvent.target;
    1.50 +
    1.51 +          // Don't draw the drop indicator outside of markers.
    1.52 +          // The markers are hidden, since otherwise sometimes popups acquire
    1.53 +          // scrollboxes on OS X, so we can't use them directly.
    1.54 +          let firstChildTop = this._startMarker.nextSibling.boxObject.y;
    1.55 +          let lastChildBottom = this._endMarker.previousSibling.boxObject.y +
    1.56 +                                this._endMarker.previousSibling.boxObject.height;
    1.57 +          let betweenMarkers = target.boxObject.y >= firstChildTop ||
    1.58 +                               target.boxObject.y <= lastChildBottom;
    1.59 +
    1.60 +          // Hide the dropmarker if current node is not a Places node.
    1.61 +          return !(target && target._placesNode && betweenMarkers);
    1.62 +        ]]></body>
    1.63 +      </method>
    1.64 +
    1.65 +      <!-- This function returns information about where to drop when
    1.66 +           dragging over this popup insertion point -->
    1.67 +      <method name="_getDropPoint">
    1.68 +        <parameter name="aEvent"/>
    1.69 +          <body><![CDATA[
    1.70 +            // Can't drop if the menu isn't a folder
    1.71 +            let resultNode = this._placesNode;
    1.72 +
    1.73 +            if (!PlacesUtils.nodeIsFolder(resultNode) ||
    1.74 +                PlacesControllerDragHelper.disallowInsertion(resultNode)) {
    1.75 +              return null;
    1.76 +            }
    1.77 +
    1.78 +            var dropPoint = { ip: null, folderElt: null };
    1.79 +
    1.80 +            // The element we are dragging over
    1.81 +            let elt = aEvent.target;
    1.82 +            if (elt.localName == "menupopup")
    1.83 +              elt = elt.parentNode;
    1.84 +
    1.85 +            // Calculate positions taking care of arrowscrollbox
    1.86 +            let scrollbox = this._scrollBox;
    1.87 +            let eventY = aEvent.layerY + (scrollbox.boxObject.y - this.boxObject.y);
    1.88 +            let scrollboxOffset = scrollbox.scrollBoxObject.y -
    1.89 +                                  (scrollbox.boxObject.y - this.boxObject.y);
    1.90 +            let eltY = elt.boxObject.y - scrollboxOffset;
    1.91 +            let eltHeight = elt.boxObject.height;
    1.92 +
    1.93 +            if (!elt._placesNode) {
    1.94 +              // If we are dragging over a non places node drop at the end.
    1.95 +              dropPoint.ip = new InsertionPoint(
    1.96 +                                  PlacesUtils.getConcreteItemId(resultNode),
    1.97 +                                  -1,
    1.98 +                                  Ci.nsITreeView.DROP_ON);
    1.99 +              // We can set folderElt if we are dropping over a static menu that
   1.100 +              // has an internal placespopup.
   1.101 +              let isMenu = elt.localName == "menu" ||
   1.102 +                 (elt.localName == "toolbarbutton" &&
   1.103 +                  elt.getAttribute("type") == "menu");
   1.104 +              if (isMenu && elt.lastChild &&
   1.105 +                  elt.lastChild.hasAttribute("placespopup"))
   1.106 +                dropPoint.folderElt = elt;
   1.107 +              return dropPoint;
   1.108 +            }
   1.109 +            else if ((PlacesUtils.nodeIsFolder(elt._placesNode) ||
   1.110 +                      PlacesUtils.nodeIsTagQuery(elt._placesNode)) &&
   1.111 +                     !PlacesUtils.nodeIsReadOnly(elt._placesNode)) {
   1.112 +              // This is a folder or a tag container.
   1.113 +              if (eventY - eltY < eltHeight * 0.20) {
   1.114 +                // If mouse is in the top part of the element, drop above folder.
   1.115 +                dropPoint.ip = new InsertionPoint(
   1.116 +                                    PlacesUtils.getConcreteItemId(resultNode),
   1.117 +                                    -1,
   1.118 +                                    Ci.nsITreeView.DROP_BEFORE,
   1.119 +                                    PlacesUtils.nodeIsTagQuery(elt._placesNode),
   1.120 +                                    elt._placesNode.itemId);
   1.121 +                return dropPoint;
   1.122 +              }
   1.123 +              else if (eventY - eltY < eltHeight * 0.80) {
   1.124 +                // If mouse is in the middle of the element, drop inside folder.
   1.125 +                dropPoint.ip = new InsertionPoint(
   1.126 +                                    PlacesUtils.getConcreteItemId(elt._placesNode),
   1.127 +                                    -1,
   1.128 +                                    Ci.nsITreeView.DROP_ON,
   1.129 +                                    PlacesUtils.nodeIsTagQuery(elt._placesNode));
   1.130 +                dropPoint.folderElt = elt;
   1.131 +                return dropPoint;
   1.132 +              }
   1.133 +            }
   1.134 +            else if (eventY - eltY <= eltHeight / 2) {
   1.135 +              // This is a non-folder node or a readonly folder.
   1.136 +              // If the mouse is above the middle, drop above this item.
   1.137 +              dropPoint.ip = new InsertionPoint(
   1.138 +                                  PlacesUtils.getConcreteItemId(resultNode),
   1.139 +                                  -1,
   1.140 +                                  Ci.nsITreeView.DROP_BEFORE,
   1.141 +                                  PlacesUtils.nodeIsTagQuery(elt._placesNode),
   1.142 +                                  elt._placesNode.itemId);
   1.143 +              return dropPoint;
   1.144 +            }
   1.145 +
   1.146 +            // Drop below the item.
   1.147 +            dropPoint.ip = new InsertionPoint(
   1.148 +                                PlacesUtils.getConcreteItemId(resultNode),
   1.149 +                                -1,
   1.150 +                                Ci.nsITreeView.DROP_AFTER,
   1.151 +                                PlacesUtils.nodeIsTagQuery(elt._placesNode),
   1.152 +                                elt._placesNode.itemId);
   1.153 +            return dropPoint;
   1.154 +        ]]></body>
   1.155 +      </method>
   1.156 +
   1.157 +      <!-- Sub-menus should be opened when the mouse drags over them, and closed
   1.158 +           when the mouse drags off.  The overFolder object manages opening and
   1.159 +           closing of folders when the mouse hovers. -->
   1.160 +      <field name="_overFolder"><![CDATA[({
   1.161 +        _self: this,
   1.162 +        _folder: {elt: null,
   1.163 +                  openTimer: null,
   1.164 +                  hoverTime: 350,
   1.165 +                  closeTimer: null},
   1.166 +        _closeMenuTimer: null,
   1.167 +
   1.168 +        get elt() {
   1.169 +          return this._folder.elt;
   1.170 +        },
   1.171 +        set elt(val) {
   1.172 +          return this._folder.elt = val;
   1.173 +        },
   1.174 +
   1.175 +        get openTimer() {
   1.176 +          return this._folder.openTimer;
   1.177 +        },
   1.178 +        set openTimer(val) {
   1.179 +          return this._folder.openTimer = val;
   1.180 +        },
   1.181 +
   1.182 +        get hoverTime() {
   1.183 +          return this._folder.hoverTime;
   1.184 +        },
   1.185 +        set hoverTime(val) {
   1.186 +          return this._folder.hoverTime = val;
   1.187 +        },
   1.188 +
   1.189 +        get closeTimer() {
   1.190 +          return this._folder.closeTimer;
   1.191 +        },
   1.192 +        set closeTimer(val) {
   1.193 +          return this._folder.closeTimer = val;
   1.194 +        },
   1.195 +
   1.196 +        get closeMenuTimer() {
   1.197 +          return this._closeMenuTimer;
   1.198 +        },
   1.199 +        set closeMenuTimer(val) {
   1.200 +          return this._closeMenuTimer = val;
   1.201 +        },
   1.202 +
   1.203 +        setTimer: function OF__setTimer(aTime) {
   1.204 +          var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   1.205 +          timer.initWithCallback(this, aTime, timer.TYPE_ONE_SHOT);
   1.206 +          return timer;
   1.207 +        },
   1.208 +
   1.209 +        notify: function OF__notify(aTimer) {
   1.210 +          // Function to process all timer notifications.
   1.211 +
   1.212 +          if (aTimer == this._folder.openTimer) {
   1.213 +            // Timer to open a submenu that's being dragged over.
   1.214 +            this._folder.elt.lastChild.setAttribute("autoopened", "true");
   1.215 +            this._folder.elt.lastChild.showPopup(this._folder.elt);
   1.216 +            this._folder.openTimer = null;
   1.217 +          }
   1.218 +
   1.219 +          else if (aTimer == this._folder.closeTimer) {
   1.220 +            // Timer to close a submenu that's been dragged off of.
   1.221 +            // Only close the submenu if the mouse isn't being dragged over any
   1.222 +            // of its child menus.
   1.223 +            var draggingOverChild = PlacesControllerDragHelper
   1.224 +                                    .draggingOverChildNode(this._folder.elt);
   1.225 +            if (draggingOverChild)
   1.226 +              this._folder.elt = null;
   1.227 +            this.clear();
   1.228 +
   1.229 +            // Close any parent folders which aren't being dragged over.
   1.230 +            // (This is necessary because of the above code that keeps a folder
   1.231 +            // open while its children are being dragged over.)
   1.232 +            if (!draggingOverChild)
   1.233 +              this.closeParentMenus();
   1.234 +          }
   1.235 +
   1.236 +          else if (aTimer == this.closeMenuTimer) {
   1.237 +            // Timer to close this menu after the drag exit.
   1.238 +            var popup = this._self;
   1.239 +            // if we are no more dragging we can leave the menu open to allow
   1.240 +            // for better D&D bookmark organization
   1.241 +            if (PlacesControllerDragHelper.getSession() &&
   1.242 +                !PlacesControllerDragHelper.draggingOverChildNode(popup.parentNode)) {
   1.243 +              popup.hidePopup();
   1.244 +              // Close any parent menus that aren't being dragged over;
   1.245 +              // otherwise they'll stay open because they couldn't close
   1.246 +              // while this menu was being dragged over.
   1.247 +              this.closeParentMenus();
   1.248 +            }
   1.249 +            this._closeMenuTimer = null;
   1.250 +          }
   1.251 +        },
   1.252 +
   1.253 +        //  Helper function to close all parent menus of this menu,
   1.254 +        //  as long as none of the parent's children are currently being
   1.255 +        //  dragged over.
   1.256 +        closeParentMenus: function OF__closeParentMenus() {
   1.257 +          var popup = this._self;
   1.258 +          var parent = popup.parentNode;
   1.259 +          while (parent) {
   1.260 +            if (parent.localName == "menupopup" && parent._placesNode) {
   1.261 +              if (PlacesControllerDragHelper.draggingOverChildNode(parent.parentNode))
   1.262 +                break;
   1.263 +              parent.hidePopup();
   1.264 +            }
   1.265 +            parent = parent.parentNode;
   1.266 +          }
   1.267 +        },
   1.268 +
   1.269 +        //  The mouse is no longer dragging over the stored menubutton.
   1.270 +        //  Close the menubutton, clear out drag styles, and clear all
   1.271 +        //  timers for opening/closing it.
   1.272 +        clear: function OF__clear() {
   1.273 +          if (this._folder.elt && this._folder.elt.lastChild) {
   1.274 +            if (!this._folder.elt.lastChild.hasAttribute("dragover"))
   1.275 +              this._folder.elt.lastChild.hidePopup();
   1.276 +            // remove menuactive style
   1.277 +            this._folder.elt.removeAttribute("_moz-menuactive");
   1.278 +            this._folder.elt = null;
   1.279 +          }
   1.280 +          if (this._folder.openTimer) {
   1.281 +            this._folder.openTimer.cancel();
   1.282 +            this._folder.openTimer = null;
   1.283 +          }
   1.284 +          if (this._folder.closeTimer) {
   1.285 +            this._folder.closeTimer.cancel();
   1.286 +            this._folder.closeTimer = null;
   1.287 +          }
   1.288 +        }
   1.289 +      })]]></field>
   1.290 +
   1.291 +      <method name="_cleanupDragDetails">
   1.292 +        <body><![CDATA[
   1.293 +          // Called on dragend and drop.
   1.294 +          PlacesControllerDragHelper.currentDropTarget = null;
   1.295 +          this._rootView._draggedElt = null;
   1.296 +          this.removeAttribute("dragover");
   1.297 +          this.removeAttribute("dragstart");
   1.298 +          this._indicatorBar.hidden = true;
   1.299 +        ]]></body>
   1.300 +      </method>
   1.301 +
   1.302 +    </implementation>
   1.303 +
   1.304 +    <handlers>
   1.305 +      <handler event="DOMMenuItemActive"><![CDATA[
   1.306 +        let elt = event.target;
   1.307 +        if (elt.parentNode != this)
   1.308 +          return;
   1.309 +
   1.310 +#ifdef XP_MACOSX
   1.311 +        // XXX: The following check is a temporary hack until bug 420033 is
   1.312 +        // resolved.
   1.313 +        let parentElt = elt.parent;
   1.314 +        while (parentElt) {
   1.315 +          if (parentElt.id == "bookmarksMenuPopup" ||
   1.316 +              parentElt.id == "goPopup")
   1.317 +            return;
   1.318 +
   1.319 +          parentElt = parentElt.parentNode;
   1.320 +        }
   1.321 +#endif
   1.322 +
   1.323 +        if (window.XULBrowserWindow) {
   1.324 +          let elt = event.target;
   1.325 +          let placesNode = elt._placesNode;
   1.326 +
   1.327 +          var linkURI;
   1.328 +          if (placesNode && PlacesUtils.nodeIsURI(placesNode))
   1.329 +            linkURI = placesNode.uri;
   1.330 +          else if (elt.hasAttribute("targetURI"))
   1.331 +            linkURI = elt.getAttribute("targetURI");
   1.332 +
   1.333 +          if (linkURI)
   1.334 +            window.XULBrowserWindow.setOverLink(linkURI, null);
   1.335 +        }
   1.336 +      ]]></handler>
   1.337 +
   1.338 +      <handler event="DOMMenuItemInactive"><![CDATA[
   1.339 +        let elt = event.target;
   1.340 +        if (elt.parentNode != this)
   1.341 +          return;
   1.342 +
   1.343 +        if (window.XULBrowserWindow)
   1.344 +          window.XULBrowserWindow.setOverLink("", null);
   1.345 +      ]]></handler>
   1.346 +
   1.347 +      <handler event="dragstart"><![CDATA[
   1.348 +        if (!event.target._placesNode)
   1.349 +          return;
   1.350 +
   1.351 +        let draggedElt = event.target._placesNode;
   1.352 +
   1.353 +        // Force a copy action if parent node is a query or we are dragging a
   1.354 +        // not-removable node.
   1.355 +        if (!PlacesControllerDragHelper.canMoveNode(draggedElt))
   1.356 +          event.dataTransfer.effectAllowed = "copyLink";
   1.357 +
   1.358 +        // Activate the view and cache the dragged element.
   1.359 +        this._rootView._draggedElt = draggedElt;
   1.360 +        this._rootView.controller.setDataTransfer(event);
   1.361 +        this.setAttribute("dragstart", "true");
   1.362 +        event.stopPropagation();
   1.363 +      ]]></handler>
   1.364 +
   1.365 +      <handler event="drop"><![CDATA[
   1.366 +        PlacesControllerDragHelper.currentDropTarget = event.target;
   1.367 +
   1.368 +        let dropPoint = this._getDropPoint(event);
   1.369 +        if (dropPoint && dropPoint.ip) {
   1.370 +          PlacesControllerDragHelper.onDrop(dropPoint.ip, event.dataTransfer);
   1.371 +          event.preventDefault();
   1.372 +        }
   1.373 +
   1.374 +        this._cleanupDragDetails();
   1.375 +        event.stopPropagation();
   1.376 +      ]]></handler>
   1.377 +
   1.378 +      <handler event="dragover"><![CDATA[
   1.379 +        PlacesControllerDragHelper.currentDropTarget = event.target;
   1.380 +        let dt = event.dataTransfer;
   1.381 +
   1.382 +        let dropPoint = this._getDropPoint(event);
   1.383 +        if (!dropPoint || !dropPoint.ip ||
   1.384 +            !PlacesControllerDragHelper.canDrop(dropPoint.ip, dt)) {
   1.385 +          this._indicatorBar.hidden = true;
   1.386 +          event.stopPropagation();
   1.387 +          return;
   1.388 +        }
   1.389 +
   1.390 +        // Mark this popup as being dragged over.
   1.391 +        this.setAttribute("dragover", "true");
   1.392 +
   1.393 +        if (dropPoint.folderElt) {
   1.394 +          // We are dragging over a folder.
   1.395 +          // _overFolder should take the care of opening it on a timer.
   1.396 +          if (this._overFolder.elt &&
   1.397 +              this._overFolder.elt != dropPoint.folderElt) {
   1.398 +            // We are dragging over a new folder, let's clear old values
   1.399 +            this._overFolder.clear();
   1.400 +          }
   1.401 +          if (!this._overFolder.elt) {
   1.402 +            this._overFolder.elt = dropPoint.folderElt;
   1.403 +            // Create the timer to open this folder.
   1.404 +            this._overFolder.openTimer = this._overFolder
   1.405 +                                             .setTimer(this._overFolder.hoverTime);
   1.406 +          }
   1.407 +          // Since we are dropping into a folder set the corresponding style.
   1.408 +          dropPoint.folderElt.setAttribute("_moz-menuactive", true);
   1.409 +        }
   1.410 +        else {
   1.411 +          // We are not dragging over a folder.
   1.412 +          // Clear out old _overFolder information.
   1.413 +          this._overFolder.clear();
   1.414 +        }
   1.415 +
   1.416 +        // Autoscroll the popup strip if we drag over the scroll buttons.
   1.417 +        let anonid = event.originalTarget.getAttribute('anonid');
   1.418 +        let scrollDir = anonid == "scrollbutton-up" ? -1 :
   1.419 +                        anonid == "scrollbutton-down" ? 1 : 0;
   1.420 +        if (scrollDir != 0) {
   1.421 +          this._scrollBox.scrollByIndex(scrollDir, false);
   1.422 +        }
   1.423 +
   1.424 +        // Check if we should hide the drop indicator for this target.
   1.425 +        if (dropPoint.folderElt || this._hideDropIndicator(event)) {
   1.426 +          this._indicatorBar.hidden = true;
   1.427 +          event.preventDefault();
   1.428 +          event.stopPropagation();
   1.429 +          return;
   1.430 +        }
   1.431 +
   1.432 +        // We should display the drop indicator relative to the arrowscrollbox.
   1.433 +        let sbo = this._scrollBox.scrollBoxObject;
   1.434 +        let newMarginTop = 0;
   1.435 +        if (scrollDir == 0) {
   1.436 +          let elt = this.firstChild;
   1.437 +          while (elt && event.screenY > elt.boxObject.screenY +
   1.438 +                                        elt.boxObject.height / 2)
   1.439 +            elt = elt.nextSibling;
   1.440 +          newMarginTop = elt ? elt.boxObject.screenY - sbo.screenY :
   1.441 +                               sbo.height;
   1.442 +        }
   1.443 +        else if (scrollDir == 1)
   1.444 +          newMarginTop = sbo.height;
   1.445 +
   1.446 +        // Set the new marginTop based on arrowscrollbox.
   1.447 +        newMarginTop += sbo.y - this._scrollBox.boxObject.y;
   1.448 +        this._indicatorBar.firstChild.style.marginTop = newMarginTop + "px";
   1.449 +        this._indicatorBar.hidden = false;
   1.450 +
   1.451 +        event.preventDefault();
   1.452 +        event.stopPropagation();
   1.453 +      ]]></handler>
   1.454 +
   1.455 +      <handler event="dragexit"><![CDATA[
   1.456 +        PlacesControllerDragHelper.currentDropTarget = null;
   1.457 +        this.removeAttribute("dragover");
   1.458 +
   1.459 +        // If we have not moved to a valid new target clear the drop indicator
   1.460 +        // this happens when moving out of the popup.
   1.461 +        let target = event.relatedTarget;
   1.462 +        if (!target || !this.contains(target))
   1.463 +          this._indicatorBar.hidden = true;
   1.464 +
   1.465 +        // Close any folder being hovered over
   1.466 +        if (this._overFolder.elt) {
   1.467 +          this._overFolder.closeTimer = this._overFolder
   1.468 +                                            .setTimer(this._overFolder.hoverTime);
   1.469 +        }
   1.470 +
   1.471 +        // The autoopened attribute is set when this folder was automatically
   1.472 +        // opened after the user dragged over it.  If this attribute is set,
   1.473 +        // auto-close the folder on drag exit.
   1.474 +        // We should also try to close this popup if the drag has started
   1.475 +        // from here, the timer will check if we are dragging over a child.
   1.476 +        if (this.hasAttribute("autoopened") ||
   1.477 +            this.hasAttribute("dragstart")) {
   1.478 +          this._overFolder.closeMenuTimer = this._overFolder
   1.479 +                                                .setTimer(this._overFolder.hoverTime);
   1.480 +        }
   1.481 +
   1.482 +        event.stopPropagation();
   1.483 +      ]]></handler>
   1.484 +
   1.485 +      <handler event="dragend"><![CDATA[
   1.486 +        this._cleanupDragDetails();
   1.487 +      ]]></handler>
   1.488 +
   1.489 +    </handlers>
   1.490 +  </binding>
   1.491 +
   1.492 +  <!-- Most of this is copied from the arrowpanel binding in popup.xml -->
   1.493 +  <binding id="places-popup-arrow"
   1.494 +           extends="chrome://browser/content/places/menu.xml#places-popup-base">
   1.495 +    <content flip="both" side="top" position="bottomcenter topright">
   1.496 +      <xul:vbox anonid="container" class="panel-arrowcontainer" flex="1"
   1.497 +               xbl:inherits="side,panelopen">
   1.498 +        <xul:box anonid="arrowbox" class="panel-arrowbox">
   1.499 +          <xul:image anonid="arrow" class="panel-arrow" xbl:inherits="side"/>
   1.500 +        </xul:box>
   1.501 +        <xul:box class="panel-arrowcontent" xbl:inherits="side,align,dir,orient,pack" flex="1">
   1.502 +          <xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
   1.503 +            <xul:image class="menupopup-drop-indicator" mousethrough="always"/>
   1.504 +          </xul:vbox>
   1.505 +          <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
   1.506 +                              smoothscroll="false">
   1.507 +            <children/>
   1.508 +          </xul:arrowscrollbox>
   1.509 +        </xul:box>
   1.510 +      </xul:vbox>
   1.511 +    </content>
   1.512 +
   1.513 +    <implementation>
   1.514 +      <constructor><![CDATA[
   1.515 +        this.style.pointerEvents = 'none';
   1.516 +      ]]></constructor>
   1.517 +      <method name="adjustArrowPosition">
   1.518 +        <body><![CDATA[
   1.519 +          var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
   1.520 +
   1.521 +          var anchor = this.anchorNode;
   1.522 +          if (!anchor) {
   1.523 +            arrow.hidden = true;
   1.524 +            return;
   1.525 +          }
   1.526 +
   1.527 +          var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
   1.528 +          var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
   1.529 +
   1.530 +          var position = this.alignmentPosition;
   1.531 +          var offset = this.alignmentOffset;
   1.532 +
   1.533 +          // if this panel has a "sliding" arrow, we may have previously set margins...
   1.534 +          arrowbox.style.removeProperty("transform");
   1.535 +          if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
   1.536 +            container.orient = "horizontal";
   1.537 +            arrowbox.orient = "vertical";
   1.538 +            if (position.indexOf("_after") > 0) {
   1.539 +              arrowbox.pack = "end";
   1.540 +            } else {
   1.541 +              arrowbox.pack = "start";
   1.542 +            }
   1.543 +            arrowbox.style.transform = "translate(0, " + -offset + "px)";
   1.544 +
   1.545 +            // The assigned side stays the same regardless of direction.
   1.546 +            var isRTL = (window.getComputedStyle(this).direction == "rtl");
   1.547 +
   1.548 +            if (position.indexOf("start_") == 0) {
   1.549 +              container.dir = "reverse";
   1.550 +              this.setAttribute("side", isRTL ? "left" : "right");
   1.551 +            }
   1.552 +            else {
   1.553 +              container.dir = "";
   1.554 +              this.setAttribute("side", isRTL ? "right" : "left");
   1.555 +            }
   1.556 +          }
   1.557 +          else if (position.indexOf("before_") == 0 || position.indexOf("after_") == 0) {
   1.558 +            container.orient = "";
   1.559 +            arrowbox.orient = "";
   1.560 +            if (position.indexOf("_end") > 0) {
   1.561 +              arrowbox.pack = "end";
   1.562 +            } else {
   1.563 +              arrowbox.pack = "start";
   1.564 +            }
   1.565 +            arrowbox.style.transform = "translate(" + -offset + "px, 0)";
   1.566 +
   1.567 +            if (position.indexOf("before_") == 0) {
   1.568 +              container.dir = "reverse";
   1.569 +              this.setAttribute("side", "bottom");
   1.570 +            }
   1.571 +            else {
   1.572 +              container.dir = "";
   1.573 +              this.setAttribute("side", "top");
   1.574 +            }
   1.575 +          }
   1.576 +
   1.577 +          arrow.hidden = false;
   1.578 +        ]]></body>
   1.579 +      </method>
   1.580 +    </implementation>
   1.581 +
   1.582 +    <handlers>
   1.583 +      <handler event="popupshowing" phase="target"><![CDATA[
   1.584 +        this.adjustArrowPosition();
   1.585 +      ]]></handler>
   1.586 +      <handler event="popupshown" phase="target"><![CDATA[
   1.587 +        this.setAttribute("panelopen", "true");
   1.588 +        let disablePointerEvents;
   1.589 +        if (!this.hasAttribute("disablepointereventsfortransition")) {
   1.590 +          let container = document.getAnonymousElementByAttribute(this, "anonid", "container");
   1.591 +          let cs = getComputedStyle(container);
   1.592 +          let transitionProp = cs.transitionProperty;
   1.593 +          let transitionTime = parseFloat(cs.transitionDuration);
   1.594 +          disablePointerEvents = (transitionProp.contains("transform") ||
   1.595 +                                  transitionProp == "all") &&
   1.596 +                                 transitionTime > 0;
   1.597 +          this.setAttribute("disablepointereventsfortransition", disablePointerEvents);
   1.598 +        } else {
   1.599 +          disablePointerEvents = this.getAttribute("disablepointereventsfortransition") == "true";
   1.600 +        }
   1.601 +        if (!disablePointerEvents) {
   1.602 +          this.style.removeProperty("pointer-events");
   1.603 +        }
   1.604 +      ]]></handler>
   1.605 +      <handler event="transitionend"><![CDATA[
   1.606 +        if (event.originalTarget.getAttribute("anonid") == "container" &&
   1.607 +            event.propertyName == "transform") {
   1.608 +          this.style.removeProperty("pointer-events");
   1.609 +        }
   1.610 +      ]]></handler>
   1.611 +      <handler event="popuphidden" phase="target"><![CDATA[
   1.612 +        this.removeAttribute("panelopen");
   1.613 +        if (this.getAttribute("disablepointereventsfortransition") == "true") {
   1.614 +          this.style.pointerEvents = 'none';
   1.615 +        }
   1.616 +      ]]></handler>
   1.617 +    </handlers>
   1.618 +  </binding>
   1.619 +</bindings>

mercurial