diff options
Diffstat (limited to 'toolkit/modules/WindowDraggingUtils.jsm')
-rw-r--r-- | toolkit/modules/WindowDraggingUtils.jsm | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/toolkit/modules/WindowDraggingUtils.jsm b/toolkit/modules/WindowDraggingUtils.jsm new file mode 100644 index 000000000..0cc2e88e9 --- /dev/null +++ b/toolkit/modules/WindowDraggingUtils.jsm @@ -0,0 +1,99 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +Components.utils.import("resource://gre/modules/AppConstants.jsm"); + +const HAVE_CSS_WINDOW_DRAG_SUPPORT = ["win", "macosx"].includes(AppConstants.platform); + +this.EXPORTED_SYMBOLS = [ "WindowDraggingElement" ]; + +this.WindowDraggingElement = function WindowDraggingElement(elem) { + this._elem = elem; + this._window = elem.ownerDocument.defaultView; + if (HAVE_CSS_WINDOW_DRAG_SUPPORT && !this.isPanel()) { + return; + } + + this._elem.addEventListener("mousedown", this, false); +}; + +WindowDraggingElement.prototype = { + mouseDownCheck: function(e) { return true; }, + dragTags: ["box", "hbox", "vbox", "spacer", "label", "statusbarpanel", "stack", + "toolbaritem", "toolbarseparator", "toolbarspring", "toolbarspacer", + "radiogroup", "deck", "scrollbox", "arrowscrollbox", "tabs"], + shouldDrag: function(aEvent) { + if (aEvent.button != 0 || + this._window.fullScreen || + !this.mouseDownCheck.call(this._elem, aEvent) || + aEvent.defaultPrevented) + return false; + + let target = aEvent.originalTarget, parent = aEvent.originalTarget; + + // The target may be inside an embedded iframe or browser. (bug 615152) + if (target.ownerDocument.defaultView != this._window) + return false; + + while (parent != this._elem) { + let mousethrough = parent.getAttribute("mousethrough"); + if (mousethrough == "always") + target = parent.parentNode; + else if (mousethrough == "never") + break; + parent = parent.parentNode; + } + while (target != this._elem) { + if (this.dragTags.indexOf(target.localName) == -1) + return false; + target = target.parentNode; + } + return true; + }, + isPanel : function() { + return this._elem instanceof Components.interfaces.nsIDOMXULElement && + this._elem.localName == "panel"; + }, + handleEvent: function(aEvent) { + let isPanel = this.isPanel(); + switch (aEvent.type) { + case "mousedown": + if (!this.shouldDrag(aEvent)) + return; + + if (/^gtk/i.test(AppConstants.MOZ_WIDGET_TOOLKIT)) { + // On GTK, there is a toolkit-level function which handles + // window dragging, which must be used. + this._window.beginWindowMove(aEvent, isPanel ? this._elem : null); + break; + } + if (isPanel) { + let screenRect = this._elem.getOuterScreenRect(); + this._deltaX = aEvent.screenX - screenRect.left; + this._deltaY = aEvent.screenY - screenRect.top; + } + else { + this._deltaX = aEvent.screenX - this._window.screenX; + this._deltaY = aEvent.screenY - this._window.screenY; + } + this._draggingWindow = true; + this._window.addEventListener("mousemove", this, false); + this._window.addEventListener("mouseup", this, false); + break; + case "mousemove": + if (this._draggingWindow) { + let toDrag = this.isPanel() ? this._elem : this._window; + toDrag.moveTo(aEvent.screenX - this._deltaX, aEvent.screenY - this._deltaY); + } + break; + case "mouseup": + if (this._draggingWindow) { + this._draggingWindow = false; + this._window.removeEventListener("mousemove", this, false); + this._window.removeEventListener("mouseup", this, false); + } + break; + } + } +} |