From 83072836713f230e2445b5c83b92ba0269d0015b Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Fri, 3 Jun 2011 15:38:24 -0400 Subject: [PATCH] Bug 554919, support panels which can dragged via their backgrounds, r=dao,smaug --- dom/base/nsGlobalWindow.cpp | 25 +++++++++-- dom/interfaces/base/nsIDOMChromeWindow.idl | 6 ++- toolkit/content/WindowDraggingUtils.jsm | 42 +++++++++++++------ toolkit/content/tests/chrome/window_panel.xul | 25 +++++++++++ toolkit/content/widgets/popup.xml | 14 +++++++ 5 files changed, 95 insertions(+), 17 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 5f5b8fb189ca..facd16ec403c 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -190,7 +190,7 @@ #ifdef MOZ_XUL #include "nsXULPopupManager.h" #include "nsIDOMXULControlElement.h" -#include "nsIFrame.h" +#include "nsMenuPopupFrame.h" #endif #include "xpcprivate.h" @@ -10214,9 +10214,28 @@ nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount) } NS_IMETHODIMP -nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent) +nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElement* aPanel) { - nsCOMPtr widget = GetMainWidget(); + nsCOMPtr widget; + + // if a panel was supplied, use its widget instead. +#ifdef MOZ_XUL + if (aPanel) { + nsCOMPtr panel = do_QueryInterface(aPanel); + NS_ENSURE_TRUE(panel, NS_ERROR_FAILURE); + + nsIFrame* frame = panel->GetPrimaryFrame(); + NS_ENSURE_TRUE(frame && frame->GetType() == nsGkAtoms::menuPopupFrame, NS_OK); + + (static_cast(frame))->GetWidget(getter_AddRefs(widget)); + } + else { +#endif + widget = GetMainWidget(); +#ifdef MOZ_XUL + } +#endif + if (!widget) { return NS_OK; } diff --git a/dom/interfaces/base/nsIDOMChromeWindow.idl b/dom/interfaces/base/nsIDOMChromeWindow.idl index 7b755aad68eb..682a28d03483 100644 --- a/dom/interfaces/base/nsIDOMChromeWindow.idl +++ b/dom/interfaces/base/nsIDOMChromeWindow.idl @@ -43,7 +43,7 @@ interface nsIDOMElement; interface nsIDOMEvent; interface nsIChromeFrameMessageManager; -[scriptable, uuid(ec38cbaf-372f-4874-bc7a-dbf1f0b3d755)] +[scriptable, uuid(7cfbc355-cbf9-4408-8e4c-a3c603ff1428)] interface nsIDOMChromeWindow : nsISupports { const unsigned short STATE_MAXIMIZED = 1; @@ -84,8 +84,10 @@ interface nsIDOMChromeWindow : nsISupports * start dragging the window. This function will fail unless called * while the left mouse button is held down, callers must check this. * + * The optional panel argument should be set when moving a panel. + * * Returns NS_ERROR_NOT_IMPLEMENTED (and thus throws in JS) if the OS * doesn't support this. */ - void beginWindowMove(in nsIDOMEvent mouseDownEvent); + void beginWindowMove(in nsIDOMEvent mouseDownEvent, [optional] in nsIDOMElement panel); }; diff --git a/toolkit/content/WindowDraggingUtils.jsm b/toolkit/content/WindowDraggingUtils.jsm index fe008618de31..22016b251ce6 100644 --- a/toolkit/content/WindowDraggingUtils.jsm +++ b/toolkit/content/WindowDraggingUtils.jsm @@ -40,10 +40,11 @@ function WindowDraggingElement(elem, window) { this._elem = elem; this._window = window; #ifdef XP_WIN - this._elem.addEventListener("MozMouseHittest", this, false); -#else - this._elem.addEventListener("mousedown", this, false); + if (!this.isPanel()) + this._elem.addEventListener("MozMouseHittest", this, false); + else #endif + this._elem.addEventListener("mousedown", this, false); } WindowDraggingElement.prototype = { @@ -79,11 +80,20 @@ WindowDraggingElement.prototype = { } return true; }, + isPanel : function() { + return this._elem instanceof Components.interfaces.nsIDOMXULElement && + this._elem.localName == "panel"; + }, handleEvent: function(aEvent) { + let isPanel = this.isPanel(); #ifdef XP_WIN - if (this.shouldDrag(aEvent)) - aEvent.preventDefault(); -#else + if (!isPanel) { + if (this.shouldDrag(aEvent)) + aEvent.preventDefault(); + return; + } +#endif + switch (aEvent.type) { case "mousedown": if (!this.shouldDrag(aEvent)) @@ -92,18 +102,27 @@ WindowDraggingElement.prototype = { #ifdef MOZ_WIDGET_GTK2 // On GTK, there is a toolkit-level function which handles // window dragging, which must be used. - this._window.beginWindowMove(aEvent); + this._window.beginWindowMove(aEvent, isPanel ? this._elem : null); #else - this._deltaX = aEvent.screenX - this._window.screenX; - this._deltaY = aEvent.screenY - this._window.screenY; + 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); #endif break; case "mousemove": - if (this._draggingWindow) - this._window.moveTo(aEvent.screenX - this._deltaX, aEvent.screenY - this._deltaY); + 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) { @@ -113,6 +132,5 @@ WindowDraggingElement.prototype = { } break; } -#endif } } diff --git a/toolkit/content/tests/chrome/window_panel.xul b/toolkit/content/tests/chrome/window_panel.xul index 80b347063838..d715bd6716af 100644 --- a/toolkit/content/tests/chrome/window_panel.xul +++ b/toolkit/content/tests/chrome/window_panel.xul @@ -227,6 +227,31 @@ var tests = [ panel.appendChild(tree); checkTreeCoords(); } + }, + { + testname: "noautohide panel with backdrag", + attrs: { noautohide: true, backdrag: "true" }, + test: function(panel) { + var label = document.createElement("label"); + label.id = "backdragspot"; + label.setAttribute("value", "Hello There"); + panel.appendChild(label); + panel.openPopupAtScreen(200, 230); + }, + result: function(testname, panel) { + var oldrect = panel.getOuterScreenRect(); + + // Linux uses native window moving + if (navigator.platform.indexOf("Linux") == -1) { + var backdragspot = document.getElementById("backdragspot"); + synthesizeMouse(backdragspot, 5, 5, { type: "mousedown" }); + synthesizeMouse(backdragspot, 15, 20, { type: "mousemove" }); + synthesizeMouse(backdragspot, 15, 20, { type: "mouseup" }); + + is(panel.getOuterScreenRect().left, 210, testname + "left"); + is(panel.getOuterScreenRect().top, 245, testname + "top"); + } + } } ]; diff --git a/toolkit/content/widgets/popup.xml b/toolkit/content/widgets/popup.xml index 9605f67b6734..f9cc0a79c049 100644 --- a/toolkit/content/widgets/popup.xml +++ b/toolkit/content/widgets/popup.xml @@ -229,6 +229,20 @@ ]]> 0 + true + + +