michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifdef XP_WIN michael@0: #define USE_HITTEST michael@0: #elifdef MOZ_WIDGET_COCOA michael@0: #define USE_HITTEST michael@0: #endif michael@0: michael@0: this.EXPORTED_SYMBOLS = [ "WindowDraggingElement" ]; michael@0: michael@0: this.WindowDraggingElement = function WindowDraggingElement(elem) { michael@0: this._elem = elem; michael@0: this._window = elem.ownerDocument.defaultView; michael@0: #ifdef USE_HITTEST michael@0: if (!this.isPanel()) michael@0: this._elem.addEventListener("MozMouseHittest", this, false); michael@0: else michael@0: #endif michael@0: this._elem.addEventListener("mousedown", this, false); michael@0: }; michael@0: michael@0: WindowDraggingElement.prototype = { michael@0: mouseDownCheck: function(e) { return true; }, michael@0: dragTags: ["box", "hbox", "vbox", "spacer", "label", "statusbarpanel", "stack", michael@0: "toolbaritem", "toolbarseparator", "toolbarspring", "toolbarspacer", michael@0: "radiogroup", "deck", "scrollbox", "arrowscrollbox", "tabs"], michael@0: shouldDrag: function(aEvent) { michael@0: if (aEvent.button != 0 || michael@0: this._window.fullScreen || michael@0: !this.mouseDownCheck.call(this._elem, aEvent) || michael@0: aEvent.defaultPrevented) michael@0: return false; michael@0: michael@0: let target = aEvent.originalTarget, parent = aEvent.originalTarget; michael@0: michael@0: // The target may be inside an embedded iframe or browser. (bug 615152) michael@0: if (target.ownerDocument.defaultView != this._window) michael@0: return false; michael@0: michael@0: while (parent != this._elem) { michael@0: let mousethrough = parent.getAttribute("mousethrough"); michael@0: if (mousethrough == "always") michael@0: target = parent.parentNode; michael@0: else if (mousethrough == "never") michael@0: break; michael@0: parent = parent.parentNode; michael@0: } michael@0: while (target != this._elem) { michael@0: if (this.dragTags.indexOf(target.localName) == -1) michael@0: return false; michael@0: target = target.parentNode; michael@0: } michael@0: return true; michael@0: }, michael@0: isPanel : function() { michael@0: return this._elem instanceof Components.interfaces.nsIDOMXULElement && michael@0: this._elem.localName == "panel"; michael@0: }, michael@0: handleEvent: function(aEvent) { michael@0: let isPanel = this.isPanel(); michael@0: #ifdef USE_HITTEST michael@0: if (!isPanel) { michael@0: if (this.shouldDrag(aEvent)) michael@0: aEvent.preventDefault(); michael@0: return; michael@0: } michael@0: #endif michael@0: michael@0: switch (aEvent.type) { michael@0: case "mousedown": michael@0: if (!this.shouldDrag(aEvent)) michael@0: return; michael@0: michael@0: #ifdef MOZ_WIDGET_GTK michael@0: // On GTK, there is a toolkit-level function which handles michael@0: // window dragging, which must be used. michael@0: this._window.beginWindowMove(aEvent, isPanel ? this._elem : null); michael@0: #else michael@0: if (isPanel) { michael@0: let screenRect = this._elem.getOuterScreenRect(); michael@0: this._deltaX = aEvent.screenX - screenRect.left; michael@0: this._deltaY = aEvent.screenY - screenRect.top; michael@0: } michael@0: else { michael@0: this._deltaX = aEvent.screenX - this._window.screenX; michael@0: this._deltaY = aEvent.screenY - this._window.screenY; michael@0: } michael@0: this._draggingWindow = true; michael@0: this._window.addEventListener("mousemove", this, false); michael@0: this._window.addEventListener("mouseup", this, false); michael@0: #endif michael@0: break; michael@0: case "mousemove": michael@0: if (this._draggingWindow) { michael@0: let toDrag = this.isPanel() ? this._elem : this._window; michael@0: toDrag.moveTo(aEvent.screenX - this._deltaX, aEvent.screenY - this._deltaY); michael@0: } michael@0: break; michael@0: case "mouseup": michael@0: if (this._draggingWindow) { michael@0: this._draggingWindow = false; michael@0: this._window.removeEventListener("mousemove", this, false); michael@0: this._window.removeEventListener("mouseup", this, false); michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: }