From 08e9ef88ed867d05f18829126e8f69de49f4f578 Mon Sep 17 00:00:00 2001 From: Jezreel Ng Date: Mon, 4 Jul 2011 12:51:47 +0200 Subject: [PATCH] Bug 465186 - When detaching a tab, open the new window at the drop location. r=dao/smaug --HG-- extra : rebase_source : 8145e9a0fcc4bf96fc5f66c2fdbbad13ca25c90e --- browser/base/content/tabbrowser.xml | 57 +++++++++++++++++++++++++++-- dom/base/nsGlobalWindow.cpp | 3 +- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index ac2d018b6929..2a4d346b5c0b 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -2005,13 +2005,18 @@ in the current window, in which case this will do nothing. --> + @@ -3298,6 +3303,16 @@ let canvas = tabPreviews.capture(tab, false); dt.setDragImage(canvas, 0, 0); + + let bo = this.mTabstrip.boxObject; + let paddingStart = this.mTabstrip.scrollboxPaddingStart; + // _dragOffset[X|Y] give the coordinates that the mouse should be + // positioned relative to the corner of the new window created upon + // dragend such that the mouse appears to have the same position + // relative to the corner of the dragged tab. + tab._dragOffsetX = event.screenX - tab.boxObject.screenX + paddingStart + bo.screenX - window.screenX; + tab._dragOffsetY = event.screenY - tab.boxObject.screenY + bo.screenY - window.screenY; + event.stopPropagation(); ]]> @@ -3477,6 +3492,11 @@ } } } + + // these offsets are only used in dragend, but we need to free them here + // as well + delete draggedTab._dragOffsetX; + delete draggedTab._dragOffsetY; ]]> wX && eX < (wX + window.outerWidth)) { @@ -3498,13 +3519,43 @@ // also avoid detaching if the the tab was dropped too close to // the tabbar (half a tab) let endScreenY = bo.screenY + 1.5 * bo.height; - let eY = event.screenY; if (eY < endScreenY && eY > window.screenY) return; } var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0); - this.tabbrowser.replaceTabWithWindow(draggedTab); + // screen.availLeft et. al. only check the screen that this window is on, + // but we want to look at the screen the tab is being dropped onto. + var sm = Cc["@mozilla.org/gfx/screenmanager;1"]. + getService(Ci.nsIScreenManager); + var whichScreen = sm.screenForRect(eX, eY, 1, 1); + var sX = {}, sY = {}, sW = {}, sH = {}; + whichScreen.GetAvailRect(sX, sY, sW, sH); + // ensure new window entirely within screen + var winWidth = Math.min(window.outerWidth, sW.value); + var winHeight = Math.min(window.outerHeight, sH.value); + var aLeft = Math.min(Math.max(eX - draggedTab._dragOffsetX, sX.value), sX.value + sW.value - winWidth); + var aTop = Math.min(Math.max(eY - draggedTab._dragOffsetY, sY.value), sY.value + sH.value - winHeight); + + delete draggedTab._dragOffsetX; + delete draggedTab._dragOffsetY; + + if (this.tabbrowser.tabs.length == 1) { + // resize _before_ move to ensure the window fits the new screen. if + // the window is too large for its screen, the window manager may do + // automatic repositioning. + window.resizeTo(winWidth, winHeight); + window.moveTo(aLeft, aTop); + window.focus(); + } + else + this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: aLeft, + screenY: aTop, +#ifndef XP_WIN + outerWidth: winWidth, + outerHeight: winHeight +#endif + }); event.stopPropagation(); ]]> diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index d404812c0d1b..537efbb77667 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2579,7 +2579,8 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor) } else if (msg == NS_MOUSE_BUTTON_DOWN && NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) { gMouseDown = PR_TRUE; - } else if (msg == NS_MOUSE_BUTTON_UP && + } else if ((msg == NS_MOUSE_BUTTON_UP || + msg == NS_DRAGDROP_END) && NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) { gMouseDown = PR_FALSE; if (gDragServiceDisabled) {