--- a/layout/build/nsLayoutCID.h
+++ b/layout/build/nsLayoutCID.h
@@ -213,9 +213,13 @@
// {8b449142-1eab-4bfa-9830-fab6ebb09774}
#define NS_DOMSTORAGE_CID \
{ 0x8b449142, 0x1eab, 0x4bfa, { 0x98, 0x30, 0xfa, 0xb6, 0xeb, 0xb0, 0x97, 0x74 } }
// {b88a4712-eb52-4c10-9b85-bf5894b510f0}
#define NS_DOMSTORAGEMANAGER_CID \
{ 0xb88a4712, 0xeb52, 0x4c10, { 0x9b, 0x85, 0xbf, 0x58, 0x94, 0xb5, 0x10, 0xf0 } }
+// {14632191-AC21-4BDF-83E7-2363AD17E838}
+#define NS_XULPOPUPMANAGER_CID \
+{ 0x14632191, 0xac21, 0x4bdf, { 0x83, 0xe7, 0x23, 0x63, 0xad, 0x17, 0xe8, 0x38 } }
+
#endif /* nsLayoutCID_h__ */
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -94,16 +94,17 @@
#include "nsContentAreaDragDrop.h"
#include "nsContentList.h"
#include "nsSyncLoadService.h"
#include "nsBox.h"
#include "nsIFrameTraversal.h"
#include "nsLayoutCID.h"
#include "nsILanguageAtomService.h"
#include "nsStyleSheetService.h"
+#include "nsXULPopupManager.h"
// Transformiix stuff
#include "nsXPathEvaluator.h"
#include "txMozillaXSLTProcessor.h"
#include "txNodeSetAdaptor.h"
#include "nsXPath1Scheme.h"
#include "nsDOMParser.h"
@@ -501,16 +502,17 @@ MAKE_CTOR(CreateContentPolicy,
MAKE_CTOR(CreateComputedDOMStyle, nsIComputedDOMStyle, NS_NewComputedDOMStyle)
#ifdef MOZ_XUL
MAKE_CTOR(CreateXULSortService, nsIXULSortService, NS_NewXULSortService)
// NS_NewXULContentBuilder
// NS_NewXULTreeBuilder
MAKE_CTOR(CreateXULDocument, nsIXULDocument, NS_NewXULDocument)
// NS_NewXULControllers
// NS_NewXULPrototypeCache
+MAKE_CTOR(CreateXULPopupManager, nsISupports, NS_NewXULPopupManager)
#endif
#ifdef MOZ_XTF
MAKE_CTOR(CreateXTFService, nsIXTFService, NS_NewXTFService)
MAKE_CTOR(CreateXMLContentBuilder, nsIXMLContentBuilder, NS_NewXMLContentBuilder)
#endif
MAKE_CTOR(CreateContentDLF, nsIDocumentLoaderFactory, NS_NewContentDocumentLoaderFactory)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCSSOMFactory)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsInspectorCSSUtils)
@@ -1171,16 +1173,21 @@ static const nsModuleComponentInfo gComp
"@mozilla.org/xul/xul-template-builder;1",
NS_NewXULContentBuilder },
{ "XUL Tree Builder",
NS_XULTREEBUILDER_CID,
"@mozilla.org/xul/xul-tree-builder;1",
NS_NewXULTreeBuilder },
+ { "XUL Popup Manager",
+ NS_XULPOPUPMANAGER_CID,
+ "@mozilla.org/xul/xul-popup-manager;1",
+ CreateXULPopupManager },
+
{ "XUL Document",
NS_XULDOCUMENT_CID,
"@mozilla.org/xul/xul-document;1",
CreateXULDocument },
{ "XUL Prototype Cache",
NS_XULPROTOTYPECACHE_CID,
"@mozilla.org/xul/xul-prototype-cache;1",
--- a/layout/xul/base/public/nsXULPopupManager.h
+++ b/layout/xul/base/public/nsXULPopupManager.h
@@ -732,9 +732,12 @@ protected:
// timer used for HidePopupAfterDelay
nsCOMPtr<nsITimer> mCloseTimer;
// a popup that is waiting on the timer
nsMenuPopupFrame* mTimerMenu;
};
+nsresult
+NS_NewXULPopupManager(nsISupports** aResult);
+
#endif
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -75,16 +75,18 @@
#include "nsUnicharUtils.h"
#include "nsLayoutUtils.h"
#include "nsCSSFrameConstructor.h"
#include "nsIEventStateManager.h"
#include "nsIBoxLayout.h"
#include "nsIPopupBoxObject.h"
#include "nsIReflowCallback.h"
#include "nsBindingManager.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIBaseWindow.h"
#ifdef XP_WIN
#include "nsISound.h"
#endif
const PRInt32 kMaxZ = 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32
// NS_NewMenuPopupFrame
//
@@ -169,16 +171,27 @@ nsMenuPopupFrame::Init(nsIContent*
// the popup opens.
if (!IsLeaf() && !ourView->HasWidget()) {
CreateWidgetForView(ourView);
}
return rv;
}
+PRBool
+nsMenuPopupFrame::IsNoAutoHide()
+{
+ // Panels with noautohide="true" don't hide when the mouse is clicked
+ // outside of them, or when another application is made active. Non-autohide
+ // panels cannot be used in content windows.
+ return (!mInContentShell && mPopupType == ePopupTypePanel &&
+ mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautohide,
+ nsGkAtoms::_true, eIgnoreCase));
+}
+
void
nsMenuPopupFrame::EnsureWidget()
{
nsIView* ourView = GetView();
if (!ourView->HasWidget()) {
NS_ASSERTION(!mGeneratedChildren && !GetFirstChild(nsnull),
"Creating widget for MenuPopupFrame with children");
CreateWidgetForView(ourView);
@@ -196,24 +209,44 @@ nsMenuPopupFrame::CreateWidgetForView(ns
PRBool viewHasTransparentContent = !mInContentShell &&
nsLayoutUtils::FrameHasTransparency(this);
nsIContent* parentContent = GetContent()->GetParent();
nsIAtom *tag = nsnull;
if (parentContent)
tag = parentContent->Tag();
widgetData.mDropShadow = !(viewHasTransparentContent || tag == nsGkAtoms::menulist);
-
+
+ // panels which don't auto-hide need a parent widget. This allows them
+ // to always appear in front of the parent window but behind other windows
+ // that should be in front of it.
+ nsCOMPtr<nsIWidget> parentWidget;
+ if (IsNoAutoHide()) {
+ nsCOMPtr<nsISupports> cont = PresContext()->GetContainer();
+ nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(cont);
+ if (!dsti)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
+ dsti->GetTreeOwner(getter_AddRefs(treeOwner));
+ if (!treeOwner) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(treeOwner));
+ if (baseWindow)
+ baseWindow->GetMainWidget(getter_AddRefs(parentWidget));
+ }
+
#if defined(XP_MACOSX) || defined(XP_BEOS)
static NS_DEFINE_IID(kCPopupCID, NS_POPUP_CID);
aView->CreateWidget(kCPopupCID, &widgetData, nsnull, PR_TRUE, PR_TRUE,
- eContentTypeUI);
+ eContentTypeUI, parentWidget);
#else
static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID);
- aView->CreateWidget(kCChildCID, &widgetData, nsnull, PR_TRUE, PR_TRUE);
+ aView->CreateWidget(kCChildCID, &widgetData, nsnull, PR_TRUE, PR_TRUE,
+ eContentTypeInherit, parentWidget);
#endif
aView->GetWidget()->SetWindowTranslucency(viewHasTransparentContent);
return NS_OK;
}
// this class is used for dispatching popupshowing events asynchronously.
class nsXULPopupShownEvent : public nsRunnable
{
@@ -1633,20 +1666,20 @@ nsMenuPopupFrame::MoveToInternal(PRInt32
// Move the widget. The widget will be null if it hasn't been created yet,
// but that's OK as the popup won't be open in this case.
// XXXbz don't we want screenPos to be the parent _widget_'s position, then?
nsIWidget* widget = view->GetWidget();
if (widget)
widget->Move(aLeft - screenPos.x, aTop - screenPos.y);
}
-void
-nsMenuPopupFrame::GetAutoPosition(PRBool* aShouldAutoPosition)
+PRBool
+nsMenuPopupFrame::GetAutoPosition()
{
- *aShouldAutoPosition = mShouldAutoPosition;
+ return mShouldAutoPosition;
}
void
nsMenuPopupFrame::SetAutoPosition(PRBool aShouldAutoPosition)
{
mShouldAutoPosition = aShouldAutoPosition;
}
--- a/layout/xul/base/src/nsMenuPopupFrame.h
+++ b/layout/xul/base/src/nsMenuPopupFrame.h
@@ -173,16 +173,20 @@ public:
PRInt32 aModType);
virtual void Destroy();
virtual void InvalidateInternal(const nsRect& aDamageRect,
nscoord aX, nscoord aY, nsIFrame* aForChild,
PRBool aImmediate);
+ // returns true if the popup is a panel with the noautohide attribute set to
+ // true. These panels do not roll up automatically.
+ PRBool IsNoAutoHide();
+
void EnsureWidget();
virtual nsresult CreateWidgetForView(nsIView* aView);
NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
nsIFrame* aChildList);
virtual PRBool IsLeaf() const;
@@ -259,17 +263,17 @@ public:
#endif
void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);
// This sets 'left' and 'top' attributes.
// May kill the frame.
void MoveTo(PRInt32 aLeft, PRInt32 aTop);
- void GetAutoPosition(PRBool* aShouldAutoPosition);
+ PRBool GetAutoPosition();
void SetAutoPosition(PRBool aShouldAutoPosition);
void SetConsumeRollupEvent(PRUint32 aConsumeMode);
nsIScrollableView* GetScrollableView(nsIFrame* aStart);
protected:
// Move without updating attributes.
void MoveToInternal(PRInt32 aLeft, PRInt32 aTop);
--- a/layout/xul/base/src/nsPopupBoxObject.cpp
+++ b/layout/xul/base/src/nsPopupBoxObject.cpp
@@ -170,17 +170,17 @@ nsPopupBoxObject::SizeTo(PRInt32 aWidth,
return NS_OK;
}
NS_IMETHODIMP
nsPopupBoxObject::GetAutoPosition(PRBool* aShouldAutoPosition)
{
nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
if (menuPopupFrame) {
- menuPopupFrame->GetAutoPosition(aShouldAutoPosition);
+ *aShouldAutoPosition = menuPopupFrame->GetAutoPosition();
}
return NS_OK;
}
NS_IMETHODIMP
nsPopupBoxObject::SetAutoPosition(PRBool aShouldAutoPosition)
{
--- a/layout/xul/base/src/nsXULPopupManager.cpp
+++ b/layout/xul/base/src/nsXULPopupManager.cpp
@@ -206,16 +206,33 @@ nsXULPopupManager::GetSubmenuWidgetChain
item->IsContextMenu() != parent->IsContextMenu())
break;
item = parent;
}
return NS_OK;
}
+NS_IMETHODIMP
+nsXULPopupManager::AdjustPopupsOnWindowChange()
+{
+ // Panels are moved and kept aligned with the anchor when the parent window
+ // moves. We only look through the panels list, as menus are expected to
+ // roll up when a window is moved, so menus don't need to be moved.
+ nsMenuChainItem* item = mPanels;
+ while (item) {
+ // if the auto positioning has been disabled, don't move the popup
+ if (item->Frame()->GetAutoPosition())
+ item->Frame()->SetPopupPosition(nsnull);
+ item = item->GetParent();
+ }
+
+ return NS_OK;
+}
+
nsIFrame*
nsXULPopupManager::GetFrameOfTypeForContent(nsIContent* aContent,
nsIAtom* aFrameType,
PRBool aShouldFlush)
{
nsIDocument *document = aContent->GetCurrentDoc();
if (document) {
nsCOMPtr<nsIPresShell> presShell = document->GetPrimaryShell();
@@ -463,20 +480,17 @@ nsXULPopupManager::ShowPopupCallback(nsI
nsWeakFrame weakFrame(aPopupFrame);
PRBool hasChildren = aPopupFrame->ShowPopup(aIsContextMenu, aSelectFirstItem);
ENSURE_TRUE(weakFrame.IsAlive());
// popups normally hide when an outside click occurs. Panels may use
// the noautohide attribute to disable this behaviour. It is expected
// that the application will hide these popups manually. The tooltip
// listener will handle closing the tooltip also.
- if (popupType == ePopupTypeTooltip ||
- (popupType == ePopupTypePanel &&
- aPopup->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautohide,
- nsGkAtoms::_true, eIgnoreCase))) {
+ if (aPopupFrame->IsNoAutoHide() || popupType == ePopupTypeTooltip) {
item->SetParent(mPanels);
mPanels = item;
}
else {
nsIContent* oldmenu = nsnull;
if (mCurrentMenu)
oldmenu = mCurrentMenu->Content();
item->SetParent(mCurrentMenu);
@@ -1937,8 +1951,17 @@ nsXULMenuCommandEvent::Run()
shell->HandleDOMEventWithTarget(mMenu, &commandEvent, &status);
}
if (popup && mCloseMenuMode != CloseMenuMode_None)
pm->HidePopup(popup, mCloseMenuMode == CloseMenuMode_Auto, PR_TRUE, PR_FALSE);
return NS_OK;
}
+
+nsresult
+NS_NewXULPopupManager(nsISupports** aResult)
+{
+ nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+ NS_IF_ADDREF(pm);
+ *aResult = static_cast<nsIMenuRollup *>(pm);
+ return NS_OK;
+}
--- a/view/public/nsIView.h
+++ b/view/public/nsIView.h
@@ -54,20 +54,20 @@ class nsWeakView;
// show - the layer is shown irrespective of the visibility of
// the layer's parent.
enum nsViewVisibility {
nsViewVisibility_kHide = 0,
nsViewVisibility_kShow = 1
};
// IID for the nsIView interface
-// 1b0215f7-f5d1-4574-9ab9-abdcceddb82e
+// 1377A30E-99E6-42FA-9A2E-EEEC6B31B7B6
#define NS_IVIEW_IID \
-{ 0x1b0215f7, 0xf5d1, 0x4574, \
- { 0x9a, 0xb9, 0xab, 0xdc, 0xce, 0xdd, 0xb8, 0x2e } }
+{ 0x1377ae0e, 0x99e6, 0x42fa, \
+{ 0x9a, 0x2e, 0xee, 0xec, 0x6b, 0x31, 0xb7, 0xb6 } }
// Public view flags are defined in this file
#define NS_VIEW_FLAGS_PUBLIC 0x00FF
// Private view flags are private to the view module,
// and are defined in nsView.h
#define NS_VIEW_FLAGS_PRIVATE 0xFF00
// Public view flags
@@ -276,24 +276,27 @@ public:
* @param aWidgetInitData data used to initialize this view's widget before
* its create is called.
* @param aNative native window that will be used as parent of
* aWindowIID. if nsnull, then parent will be derived from
* parent view and it's ancestors
* @param aWindowType is either content, UI or inherit from parent window.
* This is used to expose what type of window this is to
* assistive technology like screen readers.
+ * @param aParentWidget alternative parent to aNative used for popups. Must
+ * be null for non-popups.
* @return error status
*/
nsresult CreateWidget(const nsIID &aWindowIID,
nsWidgetInitData *aWidgetInitData = nsnull,
nsNativeWidget aNative = nsnull,
PRBool aEnableDragDrop = PR_TRUE,
PRBool aResetVisibility = PR_TRUE,
- nsContentType aWindowType = eContentTypeInherit);
+ nsContentType aWindowType = eContentTypeInherit,
+ nsIWidget* aParentWidget = nsnull);
/**
* In 4.0, the "cutout" nature of a view is queryable.
* If we believe that all cutout view have a native widget, this
* could be a replacement.
* @param aWidget out parameter for widget that this view contains,
* or nsnull if there is none.
*/
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -601,17 +601,18 @@ static PRInt32 FindNonAutoZIndex(nsView*
return 0;
}
nsresult nsIView::CreateWidget(const nsIID &aWindowIID,
nsWidgetInitData *aWidgetInitData,
nsNativeWidget aNative,
PRBool aEnableDragDrop,
PRBool aResetVisibility,
- nsContentType aContentType)
+ nsContentType aContentType,
+ nsIWidget* aParentWidget)
{
if (NS_UNLIKELY(mWindow)) {
NS_ERROR("We already have a window for this view? BAD");
ViewWrapper* wrapper = GetWrapperFor(mWindow);
NS_IF_RELEASE(wrapper);
mWindow->SetClientData(nsnull);
NS_RELEASE(mWindow);
}
@@ -638,35 +639,43 @@ nsresult nsIView::CreateWidget(const nsI
// Create initData to pass in params
initDataPassedIn = PR_FALSE;
initData.clipChildren = PR_TRUE; // Clip child window's children
initData.clipSiblings = PR_TRUE; // Clip child window's siblings
aWidgetInitData = &initData;
}
aWidgetInitData->mContentType = aContentType;
- if (aNative)
+ if (aNative && aWidgetInitData->mWindowType != eWindowType_popup)
mWindow->Create(aNative, trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
else
{
if (!initDataPassedIn && GetParent() &&
GetParent()->GetViewManager() != mViewManager)
initData.mListenForResizes = PR_TRUE;
- nsIWidget* parentWidget = GetParent() ? GetParent()->GetNearestWidget(nsnull)
- : nsnull;
- if (aWidgetInitData->mWindowType == eWindowType_popup) {
- // Without a parent, we can't make a popup. This can happen
- // when printing
- if (!parentWidget)
- return NS_ERROR_FAILURE;
- mWindow->Create(parentWidget->GetNativeData(NS_NATIVE_WIDGET), trect,
+ if (aParentWidget) {
+ NS_ASSERTION(aWidgetInitData->mWindowType == eWindowType_popup,
+ "popup widget type expected");
+ mWindow->Create(aParentWidget, trect,
::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
- } else {
- mWindow->Create(parentWidget, trect,
- ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
+ }
+ else {
+ nsIWidget* parentWidget = GetParent() ? GetParent()->GetNearestWidget(nsnull)
+ : nsnull;
+ if (aWidgetInitData->mWindowType == eWindowType_popup) {
+ // Without a parent, we can't make a popup. This can happen
+ // when printing
+ if (!parentWidget)
+ return NS_ERROR_FAILURE;
+ mWindow->Create(parentWidget->GetNativeData(NS_NATIVE_WIDGET), trect,
+ ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
+ } else {
+ mWindow->Create(parentWidget, trect,
+ ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
+ }
}
}
if (aEnableDragDrop) {
mWindow->EnableDragDrop(PR_TRUE);
}
// propagate the z-index to the widget.
UpdateNativeWidgetZIndexes(v, FindNonAutoZIndex(v));
--- a/widget/public/nsIMenuRollup.idl
+++ b/widget/public/nsIMenuRollup.idl
@@ -36,17 +36,20 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsISupportsArray.idl"
-[uuid(05c48880-0fcf-11d4-bb6f-d9f289fe803c)]
+[uuid(10C69225-2C5A-4948-8690-0BC589D145B4)]
interface nsIMenuRollup : nsISupports
{
// Walks up the menu parent chain of a submenu pulling out the widgets and
// places them into a list. Useful for determining if a click is in a
// parent menu.
nsISupportsArray GetSubmenuWidgetChain ( ) ;
-
+
+ // adjust the position of any open popups when the position or size of a
+ // window has been changed.
+ void AdjustPopupsOnWindowChange ( );
};
--- a/widget/src/cocoa/nsCocoaWindow.mm
+++ b/widget/src/cocoa/nsCocoaWindow.mm
@@ -542,16 +542,24 @@ NS_IMETHODIMP nsCocoaWindow::Show(PRBool
// other programs) that a menu has opened. This is how the OS knows to
// close other programs' context menus when ours open.
if ([mWindow isKindOfClass:[PopupWindow class]] &&
[(PopupWindow*) mWindow isContextMenu]) {
[[NSDistributedNotificationCenter defaultCenter]
postNotificationName:@"com.apple.HIToolbox.beginMenuTrackingNotification"
object:@"org.mozilla.gecko.PopupWindow"];
}
+
+ // if a parent was supplied, set its child window. This will cause the
+ // child window to appear above the parent and move when the parent
+ // does. Setting this needs to happen after the _setWindowNumber calls
+ // above, otherwise the window doesn't focus properly.
+ if (nativeParentWindow)
+ [nativeParentWindow addChildWindow:mWindow
+ ordered:NSWindowAbove];
}
else {
mVisible = PR_TRUE;
[mWindow setAcceptsMouseMovedEvents:YES];
[mWindow makeKeyAndOrderFront:nil];
SendSetZLevelEvent();
}
}
@@ -619,18 +627,25 @@ NS_IMETHODIMP nsCocoaWindow::Show(PRBool
// window will keep receiving mouse-moved events even after it's been
// "ordered out" (instead of the browser window that was underneath it,
// until you click on that window). This is bmo bug 378645, but it's
// surely an Apple bug. The "window cache" is an undocumented subsystem,
// all of whose methods are included in the NSWindowCache category of
// the NSApplication class (in header files generated using class-dump).
// This workaround was "borrowed" from the Java Embedding Plugin (which
// uses it for a different purpose).
- if (mWindowType == eWindowType_popup)
+ if (mWindowType == eWindowType_popup) {
+ // remove the window as a child of its parent again. This will just
+ // do nothing if the popup was never added as a child.
+ if (nativeParentWindow)
+ [nativeParentWindow removeChildWindow:mWindow];
+
[NSApp _removeWindowFromCache:mWindow];
+ }
+
// it's very important to turn off mouse moved events when hiding a window, otherwise
// the windows' tracking rects will interfere with each other. (bug 356528)
[mWindow setAcceptsMouseMovedEvents:NO];
mVisible = PR_FALSE;
// If our popup window is a non-native context menu, tell the OS (and
// other programs) that a menu has closed.
if ([mWindow isKindOfClass:[PopupWindow class]] &&
[(PopupWindow*) mWindow isContextMenu]) {
@@ -691,27 +706,16 @@ NS_IMETHODIMP nsCocoaWindow::ConstrainPo
}
NS_IMETHODIMP nsCocoaWindow::Move(PRInt32 aX, PRInt32 aY)
{
if (!mWindow || (mBounds.x == aX && mBounds.y == aY))
return NS_OK;
- // if we're a popup, we have to convert from our parent widget's coord
- // system to the global coord system first because the (x,y) we're given
- // is in its coordinate system.
- if (mParent && mWindowType == eWindowType_popup) {
- nsRect globalRect;
- nsRect localRect(aX, aY, 0, 0);
- mParent->WidgetToScreen(localRect, globalRect);
- aX = globalRect.x;
- aY = globalRect.y;
- }
-
// The point we have is in Gecko coordinates (origin top-left). Convert
// it to Cocoa ones (origin bottom-left).
NSPoint coord = {aX, FlippedScreenY(aY)};
[mWindow setFrameTopLeftPoint:coord];
return NS_OK;
}
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -608,26 +608,17 @@ nsWindow::Move(PRInt32 aX, PRInt32 aY)
mBounds.x = aX;
mBounds.y = aY;
if (!mCreated)
return NS_OK;
if (mIsTopLevel) {
- if (mParent && mWindowType == eWindowType_popup) {
- nsRect oldrect, newrect;
- oldrect.x = aX;
- oldrect.y = aY;
- mParent->WidgetToScreen(oldrect, newrect);
- gtk_window_move(GTK_WINDOW(mShell), newrect.x, newrect.y);
- }
- else {
- gtk_window_move(GTK_WINDOW(mShell), aX, aY);
- }
+ gtk_window_move(GTK_WINDOW(mShell), aX, aY);
}
else if (mDrawingarea) {
moz_drawingarea_move(mDrawingarea, aX, aY);
}
return NS_OK;
}
@@ -2837,18 +2828,16 @@ nsWindow::NativeCreate(nsIWidget
// only set the base parent if we're going to be a dialog or a
// toplevel
nsIWidget *baseParent = aInitData &&
(aInitData->mWindowType == eWindowType_dialog ||
aInitData->mWindowType == eWindowType_toplevel ||
aInitData->mWindowType == eWindowType_invisible) ?
nsnull : aParent;
- NS_ASSERTION(aInitData->mWindowType != eWindowType_popup ||
- !aParent, "Popups should not be hooked into nsIWidget hierarchy");
NS_ASSERTION(!mWindowGroup, "already have window group (leaking it)");
// initialize all the common bits of this class
BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
aAppShell, aToolkit, aInitData);
// Do we need to listen for resizes?
PRBool listenForResizes = PR_FALSE;;
@@ -2977,18 +2966,26 @@ nsWindow::NativeCreate(nsIWidget
mWindowGroup = parentnsWindow->mWindowGroup;
g_object_ref(G_OBJECT(mWindowGroup));
LOG(("adding window %p to group %p\n",
(void *)mShell, (void *)mWindowGroup));
}
}
}
else if (mWindowType == eWindowType_popup) {
- mShell = gtk_window_new(GTK_WINDOW_POPUP);
- gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get());
+ // treat popups with a parent as top level windows
+ if (mParent) {
+ mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel", cBrand.get());
+ gtk_window_set_decorated(GTK_WINDOW(mShell), FALSE);
+ }
+ else {
+ mShell = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get());
+ }
if (topLevelParent) {
gtk_window_set_transient_for(GTK_WINDOW(mShell),
topLevelParent);
mTransientParent = topLevelParent;
if (topLevelParent->group) {
gtk_window_group_add_window(topLevelParent->group,
@@ -3292,36 +3289,25 @@ nsWindow::NativeResize(PRInt32 aX, PRInt
mNeedsMove = PR_FALSE;
LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
aX, aY, aWidth, aHeight));
ResizeTransparencyBitmap(aWidth, aHeight);
if (mIsTopLevel) {
- if (mParent && mWindowType == eWindowType_popup) {
- nsRect oldrect, newrect;
- oldrect.x = aX;
- oldrect.y = aY;
- mParent->WidgetToScreen(oldrect, newrect);
- moz_drawingarea_resize(mDrawingarea, aWidth, aHeight);
- gtk_window_move(GTK_WINDOW(mShell), newrect.x, newrect.y);
- gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
- }
- else {
- // We only move the toplevel window if someone has
- // actually placed the window somewhere. If no placement
- // has taken place, we just let the window manager Do The
- // Right Thing.
- if (mPlaced)
- gtk_window_move(GTK_WINDOW(mShell), aX, aY);
-
- gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
- moz_drawingarea_resize(mDrawingarea, aWidth, aHeight);
- }
+ // We only move the toplevel window if someone has
+ // actually placed the window somewhere. If no placement
+ // has taken place, we just let the window manager Do The
+ // Right Thing.
+ if (mPlaced)
+ gtk_window_move(GTK_WINDOW(mShell), aX, aY);
+
+ gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
+ moz_drawingarea_resize(mDrawingarea, aWidth, aHeight);
}
else if (mContainer) {
GtkAllocation allocation;
allocation.x = 0;
allocation.y = 0;
allocation.width = aWidth;
allocation.height = aHeight;
gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -1361,19 +1361,20 @@ nsWindow::StandardWindowCreate(nsIWidget
}
mContentType = aInitData ? aInitData->mContentType : eContentTypeInherit;
DWORD style = WindowStyle();
DWORD extendedStyle = WindowExStyle();
if (mWindowType == eWindowType_popup) {
- NS_ASSERTION(!aParent, "Popups should not be hooked into the nsIWidget hierarchy");
- // Don't set the parent of a popup window.
- parent = NULL;
+ // if a parent was specified, don't use WS_EX_TOPMOST so that the popup
+ // only appears above the parent, instead of all windows
+ if (aParent)
+ extendedStyle = WS_EX_TOOLWINDOW;
} else if (nsnull != aInitData) {
// See if the caller wants to explictly set clip children and clip siblings
if (aInitData->clipChildren) {
style |= WS_CLIPCHILDREN;
} else {
style &= ~WS_CLIPCHILDREN;
}
if (aInitData->clipSiblings) {
@@ -1745,17 +1746,18 @@ NS_METHOD nsWindow::Show(PRBool bState)
#ifndef WINCE
// ensure popups are the topmost of the TOPMOST
// layer. Remember not to set the SWP_NOZORDER
// flag as that might allow the taskbar to overlap
// the popup. However on windows ce, we need to
// activate the popup or clicks will not be sent.
flags |= SWP_NOACTIVATE;
#endif
- ::SetWindowPos(mWnd, HWND_TOPMOST, 0, 0, 0, 0, flags);
+ HWND owner = ::GetWindow(mWnd, GW_OWNER);
+ ::SetWindowPos(mWnd, owner ? 0 : HWND_TOPMOST, 0, 0, 0, 0, flags);
} else {
::SetWindowPos(mWnd, HWND_TOP, 0, 0, 0, 0, flags);
}
}
} else {
if (mWindowType != eWindowType_dialog) {
if (!sIsInEndSession)
::ShowWindow(mWnd, SW_HIDE);
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -70,16 +70,17 @@
#include "nsIAppShell.h"
#include "nsIAppShellService.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMNodeList.h"
#include "nsITimer.h"
+#include "nsXULPopupManager.h"
#include "prmem.h"
#include "prlock.h"
#include "nsIDOMXULDocument.h"
#include "nsIFocusController.h"
@@ -301,22 +302,40 @@ nsWebShellWindow::HandleEvent(nsGUIEvent
if (docShell) {
switch(aEvent->message) {
/*
* For size events, the DocShell must be resized to fill the entire
* client area of the window...
*/
case NS_MOVE: {
+#ifndef XP_MACOSX
+ // Move any popups that are attached to their parents. That is, the
+ // popup moves along with the parent window when it moves. This
+ // doesn't need to happen on Mac, as Cocoa provides a nice API
+ // which does this for us.
+ nsCOMPtr<nsIMenuRollup> pm =
+ do_GetService("@mozilla.org/xul/xul-popup-manager;1");
+ if (pm)
+ pm->AdjustPopupsOnWindowChange();
+#endif
+
// persist position, but not immediately, in case this OS is firing
// repeated move events as the user drags the window
eventWindow->SetPersistenceTimer(PAD_POSITION);
break;
}
case NS_SIZE: {
+#ifndef XP_MACOSX
+ nsCOMPtr<nsIMenuRollup> pm =
+ do_GetService("@mozilla.org/xul/xul-popup-manager;1");
+ if (pm)
+ pm->AdjustPopupsOnWindowChange();
+#endif
+
nsSizeEvent* sizeEvent = (nsSizeEvent*)aEvent;
nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(docShell));
shellAsWin->SetPositionAndSize(0, 0, sizeEvent->windowSize->width,
sizeEvent->windowSize->height, PR_FALSE);
// persist size, but not immediately, in case this OS is firing
// repeated size events as the user drags the sizing handle
if (!eventWindow->IsLocked())
eventWindow->SetPersistenceTimer(PAD_SIZE | PAD_MISC);