From 6ecd66ed037fe66f6253ae3afb5091ab562a6307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 19 Jun 2024 07:47:36 +0000 Subject: [PATCH] Bug 1902315 - Remove other widget z-level fiction. r=win-reviewers,rkraesig,geckoview-reviewers,spohl,m_kato This comes back to bug 42557 and co. It only does something half-reasonable on Windows (on macOS we just lie and make z-order tracking be latest-active tracking), and given we don't use the special zorder flags elsewhere I'm pretty sure we should be able to just rip this off... On some DEs like Wayland we can't re-stack toplevel windows. Differential Revision: https://phabricator.services.mozilla.com/D213602 --- widget/android/nsWindow.cpp | 4 - widget/android/nsWindow.h | 75 ++-- widget/cocoa/nsCocoaWindow.h | 1 - widget/cocoa/nsCocoaWindow.mm | 12 - widget/gtk/nsWindow.cpp | 31 -- widget/gtk/nsWindow.h | 1 - widget/headless/HeadlessWidget.cpp | 7 - widget/nsBaseWidget.cpp | 45 --- widget/nsBaseWidget.h | 4 - widget/nsIWidget.h | 36 +- widget/nsIWidgetListener.cpp | 6 - widget/nsIWidgetListener.h | 11 - widget/windows/nsWindow.cpp | 68 +--- widget/windows/nsWindow.h | 2 - xpfe/appshell/AppWindow.cpp | 289 +--------------- xpfe/appshell/AppWindow.h | 37 +- xpfe/appshell/nsAppShellService.cpp | 38 --- xpfe/appshell/nsAppShellWindowEnumerator.cpp | 6 +- xpfe/appshell/nsAppShellWindowEnumerator.h | 1 - xpfe/appshell/nsContentTreeOwner.cpp | 3 +- xpfe/appshell/nsIAppWindow.idl | 8 - xpfe/appshell/nsIWindowMediator.idl | 70 ---- xpfe/appshell/nsWindowMediator.cpp | 338 ------------------- xpfe/appshell/nsWindowMediator.h | 3 - 24 files changed, 68 insertions(+), 1028 deletions(-) diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 762032bdb39a..195b70bcef40 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2441,10 +2441,6 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight, if (aRepaint && FindTopLevel() == nsWindow::TopWindow()) RedrawAll(); } -void nsWindow::SetZIndex(int32_t aZIndex) { - ALOG("nsWindow[%p]::SetZIndex %d ignored", (void*)this, aZIndex); -} - void nsWindow::SetSizeMode(nsSizeMode aMode) { if (aMode == mSizeMode) { return; diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 8cc41ba3ea3d..ce537b0f0386 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -141,57 +141,56 @@ class nsWindow final : public nsBaseWidget { // using nsBaseWidget::Create; // for Create signature not overridden here - [[nodiscard]] virtual nsresult Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - InitData* aInitData) override; - virtual void Destroy() override; - virtual void SetParent(nsIWidget* aNewParent) override; - virtual nsIWidget* GetParent(void) override; - virtual float GetDPI() override; - virtual double GetDefaultScaleInternal() override; - virtual void Show(bool aState) override; - virtual bool IsVisible() const override; - virtual void ConstrainPosition(DesktopIntPoint&) override; - virtual void Move(double aX, double aY) override; - virtual void Resize(double aWidth, double aHeight, bool aRepaint) override; - virtual void Resize(double aX, double aY, double aWidth, double aHeight, - bool aRepaint) override; - void SetZIndex(int32_t aZIndex) override; - virtual nsSizeMode SizeMode() override { return mSizeMode; } - virtual void SetSizeMode(nsSizeMode aMode) override; - virtual void Enable(bool aState) override; - virtual bool IsEnabled() const override; - virtual void Invalidate(const LayoutDeviceIntRect& aRect) override; - virtual void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; - virtual LayoutDeviceIntRect GetScreenBounds() override; - virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; - virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) override; + [[nodiscard]] nsresult Create(nsIWidget* aParent, + nsNativeWidget aNativeParent, + const LayoutDeviceIntRect& aRect, + InitData* aInitData) override; + void Destroy() override; + void SetParent(nsIWidget* aNewParent) override; + nsIWidget* GetParent(void) override; + float GetDPI() override; + double GetDefaultScaleInternal() override; + void Show(bool aState) override; + bool IsVisible() const override; + void ConstrainPosition(DesktopIntPoint&) override; + void Move(double aX, double aY) override; + void Resize(double aWidth, double aHeight, bool aRepaint) override; + void Resize(double aX, double aY, double aWidth, double aHeight, + bool aRepaint) override; + nsSizeMode SizeMode() override { return mSizeMode; } + void SetSizeMode(nsSizeMode aMode) override; + void Enable(bool aState) override; + bool IsEnabled() const override; + void Invalidate(const LayoutDeviceIntRect& aRect) override; + void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; + LayoutDeviceIntRect GetScreenBounds() override; + LayoutDeviceIntPoint WidgetToScreenOffset() override; + nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, + nsEventStatus& aStatus) override; nsEventStatus DispatchEvent(mozilla::WidgetGUIEvent* aEvent); - virtual nsresult MakeFullScreen(bool aFullScreen) override; + nsresult MakeFullScreen(bool aFullScreen) override; void SetCursor(const Cursor& aDefaultCursor) override; void* GetNativeData(uint32_t aDataType) override; - virtual nsresult SetTitle(const nsAString& aTitle) override { return NS_OK; } - [[nodiscard]] virtual nsresult GetAttention(int32_t aCycleCount) override { + nsresult SetTitle(const nsAString& aTitle) override { return NS_OK; } + [[nodiscard]] nsresult GetAttention(int32_t aCycleCount) override { return NS_ERROR_NOT_IMPLEMENTED; } TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override; - virtual void SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) override; - virtual InputContext GetInputContext() override; + void SetInputContext(const InputContext& aContext, + const InputContextAction& aAction) override; + InputContext GetInputContext() override; WindowRenderer* GetWindowRenderer() override; void NotifyCompositorSessionLost( mozilla::layers::CompositorSession* aSession) override; - virtual bool NeedsPaint() override; + bool NeedsPaint() override; - virtual bool WidgetPaintsBackground() override; + bool WidgetPaintsBackground() override; - virtual uint32_t GetMaxTouchPoints() const override; + uint32_t GetMaxTouchPoints() const override; void UpdateZoomConstraints( const uint32_t& aPresShellId, const ScrollableLayerGuid::ViewID& aViewId, @@ -213,7 +212,7 @@ class nsWindow final : public nsBaseWidget { void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override; - virtual void GetCompositorWidgetInitData( + void GetCompositorWidgetInitData( mozilla::widget::CompositorWidgetInitData* aInitData) override; mozilla::layers::CompositorBridgeChild* GetCompositorBridgeChild() const; @@ -241,7 +240,7 @@ class nsWindow final : public nsBaseWidget { void UpdateDynamicToolbarOffset(mozilla::ScreenIntCoord aOffset); - virtual mozilla::ScreenIntMargin GetSafeAreaInsets() const override; + mozilla::ScreenIntMargin GetSafeAreaInsets() const override; void UpdateSafeAreaInsets(const mozilla::ScreenIntMargin& aSafeAreaInsets); mozilla::jni::NativeWeakPtr diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index 3ec880392d22..70b56da83137 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -368,7 +368,6 @@ class nsCocoaWindow final : public nsBaseWidget { void DestroyNativeWindow(); void UpdateBounds(); int32_t GetWorkspaceID(); - void SendSetZLevelEvent(); void DoResize(double aX, double aY, double aWidth, double aHeight, bool aRepaint, bool aConstrainToCurrentScreen); diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 18fa75869a3c..9bb0311be2c3 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -799,7 +799,6 @@ void nsCocoaWindow::Show(bool aState) { [mWindow orderFront:nil]; } NS_OBJC_END_TRY_IGNORE_BLOCK; - SendSetZLevelEvent(); // If our popup window is a non-native context menu, tell the OS (and // other programs) that a menu has opened. This is how the OS knows to // close other programs' context menus when ours open. @@ -848,7 +847,6 @@ void nsCocoaWindow::Show(bool aState) { [mWindow makeKeyAndOrderFront:nil]; } NS_OBJC_END_TRY_IGNORE_BLOCK; - SendSetZLevelEvent(); } SetSupportsNativeFullscreen(savedValueForSupportsNativeFullscreen); } else { @@ -2056,15 +2054,6 @@ bool nsCocoaWindow::DragEvent(unsigned int aMessage, return false; } -void nsCocoaWindow::SendSetZLevelEvent() { - if (mWidgetListener) { - nsWindowZ placement = nsWindowZTop; - nsCOMPtr actualBelow; - mWidgetListener->ZLevelChanged(true, &placement, nullptr, - getter_AddRefs(actualBelow)); - } -} - // Invokes callback and ProcessEvent methods on Event Listener object nsresult nsCocoaWindow::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus) { @@ -2215,7 +2204,6 @@ void nsCocoaWindow::SetFocus(Raise aRaise, [mWindow deminiaturize:nil]; } [mWindow makeKeyAndOrderFront:nil]; - SendSetZLevelEvent(); } } diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index e21563da6fb1..c7981a5cf0f6 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -2725,37 +2725,6 @@ void nsWindow::WaylandPopupMoveImpl() { mPopupMoveToRectParams.mHints, offset.x, offset.y); } -void nsWindow::SetZIndex(int32_t aZIndex) { - nsIWidget* oldPrev = GetPrevSibling(); - - nsBaseWidget::SetZIndex(aZIndex); - - if (GetPrevSibling() == oldPrev) { - return; - } - - // We skip the nsWindows that don't have mGdkWindows. - // These are probably in the process of being destroyed. - if (!mGdkWindow) { - return; - } - - if (!GetNextSibling()) { - // We're to be on top. - if (mGdkWindow) { - gdk_window_raise(mGdkWindow); - } - } else { - // All the siblings before us need to be below our widget. - for (nsWindow* w = this; w; - w = static_cast(w->GetPrevSibling())) { - if (w->mGdkWindow) { - gdk_window_lower(w->mGdkWindow); - } - } - } -} - void nsWindow::SetSizeMode(nsSizeMode aMode) { LOG("nsWindow::SetSizeMode %d\n", aMode); diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 1dd1f1dce8f4..86bc66d1a12b 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -169,7 +169,6 @@ class nsWindow final : public nsBaseWidget { bool aRepaint) override; bool IsEnabled() const override; - void SetZIndex(int32_t aZIndex) override; nsSizeMode SizeMode() override { return mSizeMode; } void SetSizeMode(nsSizeMode aMode) override; void GetWorkspaceID(nsAString& workspaceID) override; diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp index 419b3bf94011..c6095751bc1e 100644 --- a/widget/headless/HeadlessWidget.cpp +++ b/widget/headless/HeadlessWidget.cpp @@ -170,13 +170,6 @@ void HeadlessWidget::RaiseWindow() { return; } - // Raise the window to the top of the stack. - nsWindowZ placement = nsWindowZTop; - nsCOMPtr actualBelow; - if (mWidgetListener) - mWidgetListener->ZLevelChanged(true, &placement, nullptr, - getter_AddRefs(actualBelow)); - // Deactivate the last active window. if (activeWindow && activeWindow->mWidgetListener) { activeWindow->mWidgetListener->WindowDeactivated(); diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index aff0651a0af3..a14ac32c5448 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -646,51 +646,6 @@ void nsBaseWidget::RemoveChild(nsIWidget* aChild) { aChild->SetPrevSibling(nullptr); } -//------------------------------------------------------------------------- -// -// Sets widget's position within its parent's child list. -// -//------------------------------------------------------------------------- -void nsBaseWidget::SetZIndex(int32_t aZIndex) { - // Hold a ref to ourselves just in case, since we're going to remove - // from our parent. - nsCOMPtr kungFuDeathGrip(this); - - mZIndex = aZIndex; - - // reorder this child in its parent's list. - auto* parent = static_cast(GetParent()); - if (parent) { - parent->RemoveChild(this); - // Scope sib outside the for loop so we can check it afterward - nsIWidget* sib = parent->GetFirstChild(); - for (; sib; sib = sib->GetNextSibling()) { - int32_t childZIndex = GetZIndex(); - if (aZIndex < childZIndex) { - // Insert ourselves before sib - nsIWidget* prev = sib->GetPrevSibling(); - mNextSibling = sib; - mPrevSibling = prev; - sib->SetPrevSibling(this); - if (prev) { - prev->SetNextSibling(this); - } else { - NS_ASSERTION(sib == parent->mFirstChild, "Broken child list"); - // We've taken ownership of sib, so it's safe to have parent let - // go of it - parent->mFirstChild = this; - } - PlaceBehind(eZPlacementBelow, sib, false); - break; - } - } - // were we added to the list? - if (!sib) { - parent->AddChild(this); - } - } -} - void nsBaseWidget::GetWorkspaceID(nsAString& workspaceID) { workspaceID.Truncate(); } diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 756f2ab7ebc7..da1b6919cb06 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -176,10 +176,6 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { void AddChild(nsIWidget* aChild) override; void RemoveChild(nsIWidget* aChild) override; - void SetZIndex(int32_t aZIndex) override; - void PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, nsIWidget* aWidget, - bool aActivate) override {} - void GetWorkspaceID(nsAString& workspaceID) override; void MoveToWorkspace(const nsAString& workspaceID) override; bool IsTiled() const override { return mIsTiled; } diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index bde13cea31f0..e7796b18f948 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -215,12 +215,6 @@ enum nsCursor { ///(normal cursor, usually rendered as an arrow) eCursorInvalid = eCursorCount + 1 }; -enum nsTopLevelWidgetZPlacement { // for PlaceBehind() - eZPlacementBottom = 0, // bottom of the window stack - eZPlacementBelow, // just below another widget - eZPlacementTop // top of the window stack -}; - /** * Before the OS goes to sleep, this topic is notified. */ @@ -408,10 +402,7 @@ class nsIWidget : public nsISupports { : mLastChild(nullptr), mPrevSibling(nullptr), mOnDestroyCalled(false), - mWindowType(WindowType::Child), - mZIndex(0) - - { + mWindowType(WindowType::Child) { ClearNativeTouchSequence(nullptr); } @@ -798,30 +789,6 @@ class nsIWidget : public nsISupports { */ virtual void ResizeClient(const DesktopRect& aRect, bool aRepaint) = 0; - /** - * Sets the widget's z-index. - */ - virtual void SetZIndex(int32_t aZIndex) = 0; - - /** - * Gets the widget's z-index. - */ - int32_t GetZIndex() { return mZIndex; } - - /** - * Position this widget just behind the given widget. (Used to - * control z-order for top-level widgets. Get/SetZIndex by contrast - * control z-order for child widgets of other widgets.) - * @param aPlacement top, bottom, or below a widget - * (if top or bottom, param aWidget is ignored) - * @param aWidget widget to place this widget behind - * (only if aPlacement is eZPlacementBelow). - * null is equivalent to aPlacement of eZPlacementTop - * @param aActivate true to activate the widget after placing it - */ - virtual void PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, - nsIWidget* aWidget, bool aActivate) = 0; - /** * Minimize, maximize or normalize the window size. * Takes a value from nsSizeMode (see nsIWidgetListener.h) @@ -2129,7 +2096,6 @@ class nsIWidget : public nsISupports { // When Destroy() is called, the sub class should set this true. bool mOnDestroyCalled; WindowType mWindowType; - int32_t mZIndex; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIWidget, NS_IWIDGET_IID) diff --git a/widget/nsIWidgetListener.cpp b/widget/nsIWidgetListener.cpp index 13eba4eeebf7..a554a6363660 100644 --- a/widget/nsIWidgetListener.cpp +++ b/widget/nsIWidgetListener.cpp @@ -45,12 +45,6 @@ void nsIWidgetListener::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) {} void nsIWidgetListener::MacFullscreenMenubarOverlapChanged( mozilla::DesktopCoord aOverlapAmount) {} -bool nsIWidgetListener::ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, - nsIWidget* aRequestBelow, - nsIWidget** aActualBelow) { - return false; -} - void nsIWidgetListener::OcclusionStateChanged(bool aIsFullyOccluded) {} void nsIWidgetListener::WindowActivated() {} diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h index 950d4b46224c..55a6987b0b52 100644 --- a/widget/nsIWidgetListener.h +++ b/widget/nsIWidgetListener.h @@ -86,17 +86,6 @@ class nsIWidgetListener { virtual void DynamicToolbarOffsetChanged(mozilla::ScreenIntCoord aOffset); #endif - /** - * Called when the z-order of the window is changed. Returns true if the - * notification was handled. aPlacement indicates the new z order. If - * placement is nsWindowZRelative, then aRequestBelow should be the - * window to place below. On return, aActualBelow will be set to the - * window actually behind. This generally only applies to Windows. - */ - virtual bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, - nsIWidget* aRequestBelow, - nsIWidget** aActualBelow); - /** * Called when the macOS titlebar is shown while in fullscreen. */ diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 661324be4412..b6fc3647819c 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -2103,40 +2103,14 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight, /************************************************************** * - * SECTION: Window Z-order and state. + * SECTION: Window state. * - * nsIWidget::PlaceBehind, nsIWidget::SetSizeMode, - * nsIWidget::ConstrainPosition + * nsIWidget::SetSizeMode, nsIWidget::ConstrainPosition * - * Z-order, positioning, restore, minimize, and maximize. + * Positioning, restore, minimize, and maximize. * **************************************************************/ -// Position the window behind the given window -void nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, - nsIWidget* aWidget, bool aActivate) { - HWND behind = HWND_TOP; - if (aPlacement == eZPlacementBottom) - behind = HWND_BOTTOM; - else if (aPlacement == eZPlacementBelow && aWidget) - behind = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW); - UINT flags = SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOSIZE; - if (!aActivate) flags |= SWP_NOACTIVATE; - - if (!CanTakeFocus() && behind == HWND_TOP) { - // Can't place the window to top so place it behind the foreground window - // (as long as it is not topmost) - HWND wndAfter = ::GetForegroundWindow(); - if (!wndAfter) - behind = HWND_BOTTOM; - else if (!(GetWindowLongPtrW(wndAfter, GWL_EXSTYLE) & WS_EX_TOPMOST)) - behind = wndAfter; - flags |= SWP_NOACTIVATE; - } - - ::SetWindowPos(mWnd, behind, 0, 0, 0, 0, flags); -} - static UINT GetCurrentShowCmd(HWND aWnd) { WINDOWPLACEMENT pl; pl.length = sizeof(pl); @@ -6695,40 +6669,10 @@ void nsWindow::OnWindowPosChanging(WINDOWPOS* info) { } } - // enforce local z-order rules - if (!(info->flags & SWP_NOZORDER)) { - HWND hwndAfter = info->hwndInsertAfter; - - nsWindow* aboveWindow = 0; - nsWindowZ placement; - - if (hwndAfter == HWND_BOTTOM) - placement = nsWindowZBottom; - else if (hwndAfter == HWND_TOP || hwndAfter == HWND_TOPMOST || - hwndAfter == HWND_NOTOPMOST) - placement = nsWindowZTop; - else { - placement = nsWindowZRelative; - aboveWindow = WinUtils::GetNSWindowPtr(hwndAfter); - } - - if (mWidgetListener) { - nsCOMPtr actualBelow = nullptr; - if (mWidgetListener->ZLevelChanged(false, &placement, aboveWindow, - getter_AddRefs(actualBelow))) { - if (placement == nsWindowZBottom) - info->hwndInsertAfter = HWND_BOTTOM; - else if (placement == nsWindowZTop) - info->hwndInsertAfter = HWND_TOP; - else { - info->hwndInsertAfter = - (HWND)actualBelow->GetNativeData(NS_NATIVE_WINDOW); - } - } - } - } // prevent rude external programs from making hidden window visible - if (mWindowType == WindowType::Invisible) info->flags &= ~SWP_SHOWWINDOW; + if (mWindowType == WindowType::Invisible) { + info->flags &= ~SWP_SHOWWINDOW; + } // When waking from sleep or switching out of tablet mode, Windows 10 // Version 1809 will reopen popup windows that should be hidden. Detect diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index e430eb7b09f6..76142f3a3e5d 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -175,8 +175,6 @@ class nsWindow final : public nsBaseWidget { void Resize(double aWidth, double aHeight, bool aRepaint) override; void Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override; - void PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, nsIWidget* aWidget, - bool aActivate) override; void SetSizeMode(nsSizeMode aMode) override; nsSizeMode SizeMode() override; void GetWorkspaceID(nsAString& workspaceID) override; diff --git a/xpfe/appshell/AppWindow.cpp b/xpfe/appshell/AppWindow.cpp index 7370fa95859e..c6b22c45c4e6 100644 --- a/xpfe/appshell/AppWindow.cpp +++ b/xpfe/appshell/AppWindow.cpp @@ -300,58 +300,6 @@ NS_IMETHODIMP AppWindow::GetDocShell(nsIDocShell** aDocShell) { return NS_OK; } -NS_IMETHODIMP AppWindow::GetZLevel(uint32_t* outLevel) { - nsCOMPtr mediator( - do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); - if (mediator) - mediator->GetZLevel(this, outLevel); - else - *outLevel = normalZ; - return NS_OK; -} - -NS_IMETHODIMP AppWindow::SetZLevel(uint32_t aLevel) { - nsCOMPtr mediator( - do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); - if (!mediator) return NS_ERROR_FAILURE; - - uint32_t zLevel; - mediator->GetZLevel(this, &zLevel); - if (zLevel == aLevel) return NS_OK; - - /* refuse to raise a maximized window above the normal browser level, - for fear it could hide newly opened browser windows */ - if (aLevel > nsIAppWindow::normalZ && mWindow) { - nsSizeMode sizeMode = mWindow->SizeMode(); - if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) { - return NS_ERROR_FAILURE; - } - } - - // do it - mediator->SetZLevel(this, aLevel); - PersistentAttributesDirty(PersistentAttribute::Misc, Sync); - - nsCOMPtr viewer; - mDocShell->GetDocViewer(getter_AddRefs(viewer)); - if (viewer) { - RefPtr doc = viewer->GetDocument(); - if (doc) { - ErrorResult rv; - RefPtr event = - doc->CreateEvent(u"Events"_ns, dom::CallerType::System, rv); - if (event) { - event->InitEvent(u"windowZLevel"_ns, true, false); - - event->SetTrusted(true); - - doc->DispatchEvent(*event); - } - } - } - return NS_OK; -} - NS_IMETHODIMP AppWindow::GetChromeFlags(uint32_t* aChromeFlags) { NS_ENSURE_ARG_POINTER(aChromeFlags); *aChromeFlags = mChromeFlags; @@ -592,40 +540,6 @@ NS_IMETHODIMP AppWindow::Destroy() { if (mWindow) mWindow->Show(false); #endif -#if defined(XP_WIN) - // We need to explicitly set the focus on Windows, but - // only if the parent is visible. - nsCOMPtr parent(do_QueryReferent(mParentWindow)); - if (parent) { - nsCOMPtr parentWidget; - parent->GetMainWidget(getter_AddRefs(parentWidget)); - - if (parentWidget && parentWidget->IsVisible()) { - bool isParentHiddenWindow = false; - - if (appShell) { - bool hasHiddenWindow = false; - appShell->GetHasHiddenWindow(&hasHiddenWindow); - if (hasHiddenWindow) { - nsCOMPtr baseHiddenWindow; - nsCOMPtr hiddenWindow; - appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow)); - if (hiddenWindow) { - baseHiddenWindow = do_GetInterface(hiddenWindow); - isParentHiddenWindow = (baseHiddenWindow == parent); - } - } - } - - // somebody screwed up somewhere. hiddenwindow shouldn't be anybody's - // parent. still, when it happens, skip activating it. - if (!isParentHiddenWindow) { - parentWidget->PlaceBehind(eZPlacementTop, 0, true); - } - } - } -#endif - RemoveTooltipSupport(); mDOMWindow = nullptr; @@ -1398,13 +1312,13 @@ void AppWindow::SetSpecifiedSize(int32_t aSpecWidth, int32_t aSpecHeight) { because it's important to load those before one of the misc attributes (sizemode) and they require extra processing. */ bool AppWindow::UpdateWindowStateFromMiscXULAttributes() { - bool gotState = false; - /* There are no misc attributes of interest to the hidden window. It's especially important not to try to validate that window's size or position, because some platforms (Mac OS X) need to make it visible and offscreen. */ - if (mIsHiddenWindow) return false; + if (mIsHiddenWindow) { + return false; + } nsCOMPtr windowElement = GetWindowDOMElement(); NS_ENSURE_TRUE(windowElement, false); @@ -1429,10 +1343,9 @@ bool AppWindow::UpdateWindowStateFromMiscXULAttributes() { if (mChromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) { mIntrinsicallySized = false; - if (stateString.Equals(SIZEMODE_MAXIMIZED)) - sizeMode = nsSizeMode_Maximized; - else - sizeMode = nsSizeMode_Fullscreen; + sizeMode = stateString.Equals(SIZEMODE_MAXIMIZED) + ? nsSizeMode_Maximized + : nsSizeMode_Fullscreen; } } } @@ -1451,18 +1364,7 @@ bool AppWindow::UpdateWindowStateFromMiscXULAttributes() { } mWindow->SetSizeMode(sizeMode); } - gotState = true; - - // zlevel - windowElement->GetAttr(nsGkAtoms::zlevel, stateString); - if (!stateString.IsEmpty()) { - nsresult errorCode; - int32_t zLevel = stateString.ToInteger(&errorCode); - if (NS_SUCCEEDED(errorCode) && zLevel >= lowestZ && zLevel <= highestZ) - SetZLevel(zLevel); - } - - return gotState; + return true; } /* Stagger windows of the same type so they don't appear on top of each other. @@ -2086,20 +1988,6 @@ void AppWindow::MaybeSavePersistentMiscAttributes( aRootElement.SetAttribute(u"gtktiledwindow"_ns, mWindow->IsTiled() ? u"true"_ns : u"false"_ns, IgnoreErrors()); - if (aPersistString.Find(u"zlevel") >= 0) { - uint32_t zLevel; - nsCOMPtr mediator( - do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); - if (mediator) { - mediator->GetZLevel(this, &zLevel); - sizeString.Truncate(); - sizeString.AppendInt(zLevel); - aRootElement.SetAttr(nsGkAtoms::zlevel, sizeString, IgnoreErrors()); - if (aShouldPersist) { - Unused << SetPersistentValue(nsGkAtoms::zlevel, sizeString); - } - } - } } void AppWindow::SavePersistentAttributes( @@ -2395,141 +2283,6 @@ void AppWindow::EnableParent(bool aEnable) { if (parentWidget) parentWidget->Enable(aEnable); } -// Constrain the window to its proper z-level -bool AppWindow::ConstrainToZLevel(bool aImmediate, nsWindowZ* aPlacement, - nsIWidget* aReqBelow, - nsIWidget** aActualBelow) { -#if 0 - /* Do we have a parent window? This means our z-order is already constrained, - since we're a dependent window. Our window list isn't hierarchical, - so we can't properly calculate placement for such a window. - Should we just abort? */ - nsCOMPtr parentWindow = do_QueryReferent(mParentWindow); - if (parentWindow) - return false; -#endif - - nsCOMPtr mediator( - do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); - if (!mediator) return false; - - bool altered; - uint32_t position, newPosition, zLevel; - nsIAppWindow* us = this; - - altered = false; - mediator->GetZLevel(this, &zLevel); - - // translate from WidgetGUIEvent to nsIWindowMediator constants - position = nsIWindowMediator::zLevelTop; - if (*aPlacement == nsWindowZBottom || zLevel == nsIAppWindow::lowestZ) - position = nsIWindowMediator::zLevelBottom; - else if (*aPlacement == nsWindowZRelative) - position = nsIWindowMediator::zLevelBelow; - - if (NS_SUCCEEDED(mediator->CalculateZPosition( - us, position, aReqBelow, &newPosition, aActualBelow, &altered))) { - /* If we were asked to move to the top but constrained to remain - below one of our other windows, first move all windows in that - window's layer and above to the top. This allows the user to - click a window which can't be topmost and still bring mozilla - to the foreground. */ - if (altered && - (position == nsIWindowMediator::zLevelTop || - (position == nsIWindowMediator::zLevelBelow && aReqBelow == 0))) - PlaceWindowLayersBehind(zLevel + 1, nsIAppWindow::highestZ, 0); - - if (*aPlacement != nsWindowZBottom && - position == nsIWindowMediator::zLevelBottom) - altered = true; - if (altered || aImmediate) { - if (newPosition == nsIWindowMediator::zLevelTop) - *aPlacement = nsWindowZTop; - else if (newPosition == nsIWindowMediator::zLevelBottom) - *aPlacement = nsWindowZBottom; - else - *aPlacement = nsWindowZRelative; - - if (aImmediate) { - nsCOMPtr ourBase = do_QueryObject(this); - if (ourBase) { - nsCOMPtr ourWidget; - ourBase->GetMainWidget(getter_AddRefs(ourWidget)); - ourWidget->PlaceBehind(*aPlacement == nsWindowZBottom - ? eZPlacementBottom - : eZPlacementBelow, - *aActualBelow, false); - } - } - } - - /* CalculateZPosition can tell us to be below nothing, because it tries - not to change something it doesn't recognize. A request to verify - being below an unrecognized window, then, is treated as a request - to come to the top (below null) */ - nsCOMPtr windowAbove; - if (newPosition == nsIWindowMediator::zLevelBelow && *aActualBelow) { - windowAbove = (*aActualBelow)->GetWidgetListener()->GetAppWindow(); - } - - mediator->SetZPosition(us, newPosition, windowAbove); - } - - return altered; -} - -/* Re-z-position all windows in the layers from aLowLevel to aHighLevel, - inclusive, to be behind aBehind. aBehind of null means on top. - Note this method actually does nothing to our relative window positions. - (And therefore there's no need to inform WindowMediator we're moving - things, because we aren't.) This method is useful for, say, moving - a range of layers of our own windows relative to windows belonging to - external applications. -*/ -void AppWindow::PlaceWindowLayersBehind(uint32_t aLowLevel, uint32_t aHighLevel, - nsIAppWindow* aBehind) { - // step through windows in z-order from top to bottommost window - - nsCOMPtr mediator( - do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); - if (!mediator) return; - - nsCOMPtr windowEnumerator; - mediator->GetZOrderAppWindowEnumerator(0, true, - getter_AddRefs(windowEnumerator)); - if (!windowEnumerator) return; - - // each window will be moved behind previousHighWidget, itself - // a moving target. initialize it. - nsCOMPtr previousHighWidget; - if (aBehind) { - nsCOMPtr highBase(do_QueryInterface(aBehind)); - if (highBase) highBase->GetMainWidget(getter_AddRefs(previousHighWidget)); - } - - // get next lower window - bool more; - while (NS_SUCCEEDED(windowEnumerator->HasMoreElements(&more)) && more) { - uint32_t nextZ; // z-level of nextWindow - nsCOMPtr nextWindow; - windowEnumerator->GetNext(getter_AddRefs(nextWindow)); - nsCOMPtr nextAppWindow(do_QueryInterface(nextWindow)); - nextAppWindow->GetZLevel(&nextZ); - if (nextZ < aLowLevel) - break; // we've processed all windows through aLowLevel - - // move it just below its next higher window - nsCOMPtr nextBase(do_QueryInterface(nextAppWindow)); - if (nextBase) { - nsCOMPtr nextWidget; - nextBase->GetMainWidget(getter_AddRefs(nextWidget)); - if (nextZ <= aHighLevel) - nextWidget->PlaceBehind(eZPlacementBelow, previousHighWidget, false); - previousHighWidget = nextWidget; - } - } -} - void AppWindow::SetContentScrollbarVisibility(bool aVisible) { nsCOMPtr contentWin( do_GetInterface(mPrimaryContentShell)); @@ -2927,18 +2680,6 @@ void AppWindow::SizeModeChanged(nsSizeMode aSizeMode) { FullscreenWillChange(mIsWidgetInFullscreen); } - // An alwaysRaised (or higher) window will hide any newly opened normal - // browser windows, so here we just drop a raised window to the normal - // zlevel if it's maximized. We make no provision for automatically - // re-raising it when restored. - if (aSizeMode == nsSizeMode_Maximized || aSizeMode == nsSizeMode_Fullscreen) { - uint32_t zLevel; - GetZLevel(&zLevel); - if (zLevel > nsIAppWindow::normalZ) { - SetZLevel(nsIAppWindow::normalZ); - } - } - RecomputeBrowsingContextVisibility(); PersistentAttributesDirty(PersistentAttribute::Misc, Sync); @@ -3086,14 +2827,6 @@ void AppWindow::OSToolbarButtonPressed() { wbc->SetChromeFlags(chromeFlags); } -bool AppWindow::ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, - nsIWidget* aRequestBelow, - nsIWidget** aActualBelow) { - if (aActualBelow) *aActualBelow = nullptr; - - return ConstrainToZLevel(aImmediate, aPlacement, aRequestBelow, aActualBelow); -} - void AppWindow::WindowActivated() { nsCOMPtr appWindow(this); @@ -3471,14 +3204,6 @@ void AppWindow::WidgetListenerDelegate::OSToolbarButtonPressed() { holder->OSToolbarButtonPressed(); } -bool AppWindow::WidgetListenerDelegate::ZLevelChanged( - bool aImmediate, nsWindowZ* aPlacement, nsIWidget* aRequestBelow, - nsIWidget** aActualBelow) { - RefPtr holder = mAppWindow; - return holder->ZLevelChanged(aImmediate, aPlacement, aRequestBelow, - aActualBelow); -} - void AppWindow::WidgetListenerDelegate::WindowActivated() { RefPtr holder = mAppWindow; holder->WindowActivated(); diff --git a/xpfe/appshell/AppWindow.h b/xpfe/appshell/AppWindow.h index d51c2c6aba2b..c9cfc3650617 100644 --- a/xpfe/appshell/AppWindow.h +++ b/xpfe/appshell/AppWindow.h @@ -78,40 +78,36 @@ class AppWindow final : public nsIBaseWindow, // The implementation of non-refcounted nsIWidgetListener, which would hold a // strong reference on stack before calling AppWindow's // MOZ_CAN_RUN_SCRIPT methods. - class WidgetListenerDelegate : public nsIWidgetListener { + class WidgetListenerDelegate final : public nsIWidgetListener { public: explicit WidgetListenerDelegate(AppWindow* aAppWindow) : mAppWindow(aAppWindow) {} MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual nsIAppWindow* GetAppWindow() override; + nsIAppWindow* GetAppWindow() override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual mozilla::PresShell* GetPresShell() override; + mozilla::PresShell* GetPresShell() override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y, - ByMoveToRect) override; + bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y, + ByMoveToRect) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, - int32_t aHeight) override; + bool WindowResized(nsIWidget* aWidget, int32_t aWidth, + int32_t aHeight) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual bool RequestWindowClose(nsIWidget* aWidget) override; + bool RequestWindowClose(nsIWidget* aWidget) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual void SizeModeChanged(nsSizeMode sizeMode) override; + void SizeModeChanged(nsSizeMode sizeMode) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual void MacFullscreenMenubarOverlapChanged( + void MacFullscreenMenubarOverlapChanged( mozilla::DesktopCoord aOverlapAmount) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual void OcclusionStateChanged(bool aIsFullyOccluded) override; + void OcclusionStateChanged(bool aIsFullyOccluded) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual void OSToolbarButtonPressed() override; + void OSToolbarButtonPressed() override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, - nsIWidget* aRequestBelow, - nsIWidget** aActualBelow) override; + void WindowActivated() override; MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual void WindowActivated() override; - MOZ_CAN_RUN_SCRIPT_BOUNDARY - virtual void WindowDeactivated() override; + void WindowDeactivated() override; private: // The lifetime of WidgetListenerDelegate is bound to AppWindow so @@ -163,9 +159,6 @@ class AppWindow final : public nsIBaseWindow, MOZ_CAN_RUN_SCRIPT void OcclusionStateChanged(bool aIsFullyOccluded); void RecomputeBrowsingContextVisibility(); MOZ_CAN_RUN_SCRIPT void OSToolbarButtonPressed(); - MOZ_CAN_RUN_SCRIPT - bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement, - nsIWidget* aRequestBelow, nsIWidget** aActualBelow); MOZ_CAN_RUN_SCRIPT void WindowActivated(); MOZ_CAN_RUN_SCRIPT void WindowDeactivated(); @@ -253,8 +246,6 @@ class AppWindow final : public nsIBaseWindow, NS_IMETHOD GetHasPrimaryContent(bool* aResult); void EnableParent(bool aEnable); - bool ConstrainToZLevel(bool aImmediate, nsWindowZ* aPlacement, - nsIWidget* aReqBelow, nsIWidget** aActualBelow); void PlaceWindowLayersBehind(uint32_t aLowLevel, uint32_t aHighLevel, nsIAppWindow* aBehind); void SetContentScrollbarVisibility(bool aVisible); diff --git a/xpfe/appshell/nsAppShellService.cpp b/xpfe/appshell/nsAppShellService.cpp index 06f2476c2508..3a69b85382c2 100644 --- a/xpfe/appshell/nsAppShellService.cpp +++ b/xpfe/appshell/nsAppShellService.cpp @@ -182,9 +182,6 @@ nsAppShellService::CreateTopLevelWindow(nsIAppWindow* aParent, nsIURI* aUrl, if (NS_SUCCEEDED(rv)) { // the addref resulting from this is the owning addref for this window RegisterTopLevelWindow(*aResult); - nsCOMPtr parent; - if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) parent = aParent; - (*aResult)->SetZLevel(CalculateWindowZLevel(parent, aChromeMask)); } return rv; @@ -468,41 +465,6 @@ nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, uint32_t aChromeMask, return NS_OK; } -uint32_t nsAppShellService::CalculateWindowZLevel(nsIAppWindow* aParent, - uint32_t aChromeMask) { - uint32_t zLevel; - - zLevel = nsIAppWindow::normalZ; - if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RAISED) - zLevel = nsIAppWindow::raisedZ; - else if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_LOWERED) - zLevel = nsIAppWindow::loweredZ; - -#ifdef XP_MACOSX - /* Platforms on which modal windows are always application-modal, not - window-modal (that's just the Mac, right?) want modal windows to - be stacked on top of everyone else. - - On Mac OS X, bind modality to parent window instead of app (ala Mac OS 9) - */ - uint32_t modalDepMask = - nsIWebBrowserChrome::CHROME_MODAL | nsIWebBrowserChrome::CHROME_DEPENDENT; - if (aParent && (aChromeMask & modalDepMask)) { - aParent->GetZLevel(&zLevel); - } -#else - /* Platforms with native support for dependent windows (that's everyone - but pre-Mac OS X, right?) know how to stack dependent windows. On these - platforms, give the dependent window the same level as its parent, - so we won't try to override the normal platform behaviour. */ - if ((aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) && aParent) { - aParent->GetZLevel(&zLevel); - } -#endif - - return zLevel; -} - /* * Just do the window-making part of CreateTopLevelWindow */ diff --git a/xpfe/appshell/nsAppShellWindowEnumerator.cpp b/xpfe/appshell/nsAppShellWindowEnumerator.cpp index d140f8a90f62..bf72d6762d38 100644 --- a/xpfe/appshell/nsAppShellWindowEnumerator.cpp +++ b/xpfe/appshell/nsAppShellWindowEnumerator.cpp @@ -62,13 +62,11 @@ void GetWindowType(nsIAppWindow* aWindow, nsString& outType) { // nsWindowInfo::nsWindowInfo(nsIAppWindow* inWindow, int32_t inTimeStamp) - : mWindow(inWindow), - mTimeStamp(inTimeStamp), - mZLevel(nsIAppWindow::normalZ) { + : mWindow(inWindow), mTimeStamp(inTimeStamp) { ReferenceSelf(true, true); } -nsWindowInfo::~nsWindowInfo() {} +nsWindowInfo::~nsWindowInfo() = default; // return true if the window described by this WindowInfo has a type // equal to the given type diff --git a/xpfe/appshell/nsAppShellWindowEnumerator.h b/xpfe/appshell/nsAppShellWindowEnumerator.h index b5dc828dcfc1..51ae19c88c9a 100644 --- a/xpfe/appshell/nsAppShellWindowEnumerator.h +++ b/xpfe/appshell/nsAppShellWindowEnumerator.h @@ -24,7 +24,6 @@ struct nsWindowInfo { nsCOMPtr mWindow; int32_t mTimeStamp; - uint32_t mZLevel; // each struct is in two, independent, circular, doubly-linked lists nsWindowInfo *mYounger, // next younger in sequence diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp index 72fa807bbace..37d5b45def67 100644 --- a/xpfe/appshell/nsContentTreeOwner.cpp +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -615,8 +615,7 @@ nsContentTreeOwner::Blur() { nsCOMPtr windowMediator( do_GetService(kWindowMediatorCID)); if (windowMediator) { - windowMediator->GetZOrderAppWindowEnumerator( - nullptr, true, getter_AddRefs(windowEnumerator)); + windowMediator->GetEnumerator(nullptr, getter_AddRefs(windowEnumerator)); } } diff --git a/xpfe/appshell/nsIAppWindow.idl b/xpfe/appshell/nsIAppWindow.idl index 0ef6425a2dde..a6e3880b1402 100644 --- a/xpfe/appshell/nsIAppWindow.idl +++ b/xpfe/appshell/nsIAppWindow.idl @@ -103,14 +103,6 @@ interface nsIAppWindow : nsISupports */ void lockAspectRatio(in boolean aShouldLock); - const unsigned long lowestZ = 0; - const unsigned long loweredZ = 4; /* "alwaysLowered" attribute */ - const unsigned long normalZ = 5; - const unsigned long raisedZ = 6; /* "alwaysRaised" attribute */ - const unsigned long highestZ = 9; - - attribute unsigned long zLevel; - attribute uint32_t chromeFlags; /** diff --git a/xpfe/appshell/nsIWindowMediator.idl b/xpfe/appshell/nsIWindowMediator.idl index ef891c053717..12f71a4763e1 100644 --- a/xpfe/appshell/nsIWindowMediator.idl +++ b/xpfe/appshell/nsIWindowMediator.idl @@ -110,76 +110,6 @@ interface nsIWindowMediator: nsISupports */ [noscript] void updateWindowTimeStamp(in nsIAppWindow aWindow); - /* z-ordering: */ - - const unsigned long zLevelTop = 1; - const unsigned long zLevelBottom = 2; - const unsigned long zLevelBelow = 3; // below some window - - /** A window wants to be moved in z-order. Calculate whether and how - * it should be constrained. Note this method is advisory only: - * it changes nothing either in WindowMediator's internal state - * or with the window. - * Note it compares the nsIAppWindow to nsIWidgets. A pure interface - * would use all nsIAppWindows. But we expect this to be called from - * callbacks originating in native window code. They are expected to - * hand us comparison values which are pulled from general storage - * in the native widget, and may not correspond to an nsIWidget at all. - * For that reason this interface requires only objects one step - * removed from the native window (nsIWidgets), and its implementation - * must be very understanding of what may be completely invalid - * pointers in those parameters. - * - * @param inWindow the window in question - * @param inPosition requested position - * values: zLevelTop: topmost window. zLevelBottom: bottom. - * zLevelBelow: below ioBelow. (the value of ioBelow will - * be ignored for zLevelTop and Bottom.) - * @param inBelow if inPosition==zLevelBelow, the window - * below which inWindow wants to be placed. Otherwise this - * variable is ignored. - * @param outPosition constrained position, values like inPosition. - * @param outBelow if outPosition==zLevelBelow, the window - * below which inWindow should be placed. Otherwise this - * this value will be null. - * @return PR_TRUE if the position returned is different from - * the position given. - */ - - [noscript] boolean calculateZPosition(in nsIAppWindow inWindow, - in unsigned long inPosition, - in nsIWidget inBelow, - out unsigned long outPosition, - out nsIWidget outBelow); - - /** A window has been positioned behind another. Inform WindowMediator - * @param inWindow the window in question - * @param inPosition new position. values: - * zLevelTop: topmost window. - * zLevelBottom: bottom. - * zLevelBelow: below inBelow. (inBelow is ignored - * for other values of inPosition.) - * @param inBelow the window inWindow is behind, if zLevelBelow - */ - [noscript] void setZPosition(in nsIAppWindow inWindow, - in unsigned long inPosition, - in nsIAppWindow inBelow); - - /** Return the window's Z level (as defined in nsIAppWindow). - * @param aWindow the window in question - * @return aWindow's z level - */ - [noscript] uint32_t getZLevel(in nsIAppWindow aWindow); - - /** Set the window's Z level (as defined in nsIAppWindow). The implementation - * will reposition the window as necessary to match its new Z level. - * The implementation will assume a window's Z level to be - * nsIAppWindow::normalZ until it has been informed of a different level. - * @param aWindow the window in question - * @param aZLevel the window's new Z level - */ - [noscript] void setZLevel(in nsIAppWindow aWindow, in uint32_t aZLevel); - /** Register a listener for window status changes. * keeps strong ref? (to be decided) * @param aListener the listener to register diff --git a/xpfe/appshell/nsWindowMediator.cpp b/xpfe/appshell/nsWindowMediator.cpp index 0e5f38898cdc..e44a5e7008f7 100644 --- a/xpfe/appshell/nsWindowMediator.cpp +++ b/xpfe/appshell/nsWindowMediator.cpp @@ -43,7 +43,6 @@ nsWindowMediator::nsWindowMediator() : mOldestWindow(nullptr), mTopmostWindow(nullptr), mTimeStamp(0), - mSortingZOrder(false), mReady(false) {} nsWindowMediator::~nsWindowMediator() { @@ -379,343 +378,6 @@ nsWindowMediator::UpdateWindowTimeStamp(nsIAppWindow* inWindow) { return NS_ERROR_FAILURE; } -/* This method's plan is to intervene only when absolutely necessary. - We will get requests to place our windows behind unknown windows. - For the most part, we need to leave those alone (turning them into - explicit requests to be on top breaks Windows.) So generally we - calculate a change as seldom as possible. -*/ -NS_IMETHODIMP -nsWindowMediator::CalculateZPosition(nsIAppWindow* inWindow, - uint32_t inPosition, nsIWidget* inBelow, - uint32_t* outPosition, - nsIWidget** outBelow, bool* outAltered) { - MOZ_RELEASE_ASSERT(NS_IsMainThread()); - NS_ENSURE_ARG_POINTER(outBelow); - MOZ_ASSERT(mReady); - NS_ENSURE_STATE(mReady); - - *outBelow = nullptr; - - if (!inWindow || !outPosition || !outAltered) return NS_ERROR_NULL_POINTER; - - if (inPosition != nsIWindowMediator::zLevelTop && - inPosition != nsIWindowMediator::zLevelBottom && - inPosition != nsIWindowMediator::zLevelBelow) - return NS_ERROR_INVALID_ARG; - - nsWindowInfo* info = mTopmostWindow; - nsIAppWindow* belowWindow = nullptr; - bool found = false; - nsresult result = NS_OK; - - *outPosition = inPosition; - *outAltered = false; - - if (mSortingZOrder) { // don't fight SortZOrder() - *outBelow = inBelow; - NS_IF_ADDREF(*outBelow); - return NS_OK; - } - - uint32_t inZ; - GetZLevel(inWindow, &inZ); - - if (inPosition == nsIWindowMediator::zLevelBelow) { - // locate inBelow. use topmost if it can't be found or isn't in the - // z-order list - info = GetInfoFor(inBelow); - if (!info || (info->mYounger != info && info->mLower == info)) - info = mTopmostWindow; - else - found = true; - - if (!found) { - /* Treat unknown windows as a request to be on top. - Not as it should be, but that's what Windows gives us. - Note we change inPosition, but not *outPosition. This forces - us to go through the "on top" calculation just below, without - necessarily changing the output parameters. */ - inPosition = nsIWindowMediator::zLevelTop; - } - } - - if (inPosition == nsIWindowMediator::zLevelTop) { - if (mTopmostWindow && mTopmostWindow->mZLevel > inZ) { - // asked for topmost, can't have it. locate highest allowed position. - do { - if (info->mZLevel <= inZ) break; - info = info->mLower; - } while (info != mTopmostWindow); - - *outPosition = nsIWindowMediator::zLevelBelow; - belowWindow = info->mHigher->mWindow; - *outAltered = true; - } - } else if (inPosition == nsIWindowMediator::zLevelBottom) { - if (mTopmostWindow && mTopmostWindow->mHigher->mZLevel < inZ) { - // asked for bottommost, can't have it. locate lowest allowed position. - do { - info = info->mHigher; - if (info->mZLevel >= inZ) break; - } while (info != mTopmostWindow); - - *outPosition = nsIWindowMediator::zLevelBelow; - belowWindow = info->mWindow; - *outAltered = true; - } - } else { - unsigned long relativeZ; - - // check that we're in the right z-plane - if (found) { - belowWindow = info->mWindow; - relativeZ = info->mZLevel; - if (relativeZ > inZ) { - // might be OK. is lower window, if any, lower? - if (info->mLower != info && info->mLower->mZLevel > inZ) { - do { - if (info->mZLevel <= inZ) break; - info = info->mLower; - } while (info != mTopmostWindow); - - belowWindow = info->mHigher->mWindow; - *outAltered = true; - } - } else if (relativeZ < inZ) { - // nope. look for a higher window to be behind. - do { - info = info->mHigher; - if (info->mZLevel >= inZ) break; - } while (info != mTopmostWindow); - - if (info->mZLevel >= inZ) - belowWindow = info->mWindow; - else - *outPosition = nsIWindowMediator::zLevelTop; - *outAltered = true; - } // else they're equal, so it's OK - } - } - - if (NS_SUCCEEDED(result) && belowWindow) { - nsCOMPtr base(do_QueryInterface(belowWindow)); - if (base) - base->GetMainWidget(outBelow); - else - result = NS_ERROR_NO_INTERFACE; - } - - return result; -} - -NS_IMETHODIMP -nsWindowMediator::SetZPosition(nsIAppWindow* inWindow, uint32_t inPosition, - nsIAppWindow* inBelow) { - MOZ_RELEASE_ASSERT(NS_IsMainThread()); - nsWindowInfo *inInfo, *belowInfo; - - if ((inPosition != nsIWindowMediator::zLevelTop && - inPosition != nsIWindowMediator::zLevelBottom && - inPosition != nsIWindowMediator::zLevelBelow) || - !inWindow) { - return NS_ERROR_INVALID_ARG; - } - - if (mSortingZOrder) // don't fight SortZOrder() - return NS_OK; - - MOZ_ASSERT(mReady); - NS_ENSURE_STATE(mReady); - - /* Locate inWindow and unlink it from the z-order list. - It's important we look for it in the age list, not the z-order list. - This is because the former is guaranteed complete, while - now may be this window's first exposure to the latter. */ - inInfo = GetInfoFor(inWindow); - if (!inInfo) return NS_ERROR_INVALID_ARG; - - // locate inBelow, place inWindow behind it - if (inPosition == nsIWindowMediator::zLevelBelow) { - belowInfo = GetInfoFor(inBelow); - // it had better also be in the z-order list - if (belowInfo && belowInfo->mYounger != belowInfo && - belowInfo->mLower == belowInfo) { - belowInfo = nullptr; - } - if (!belowInfo) { - if (inBelow) - return NS_ERROR_INVALID_ARG; - else - inPosition = nsIWindowMediator::zLevelTop; - } - } - if (inPosition == nsIWindowMediator::zLevelTop || - inPosition == nsIWindowMediator::zLevelBottom) - belowInfo = mTopmostWindow ? mTopmostWindow->mHigher : nullptr; - - if (inInfo != belowInfo) { - inInfo->Unlink(false, true); - inInfo->InsertAfter(nullptr, belowInfo); - } - if (inPosition == nsIWindowMediator::zLevelTop) mTopmostWindow = inInfo; - - return NS_OK; -} - -NS_IMETHODIMP -nsWindowMediator::GetZLevel(nsIAppWindow* aWindow, uint32_t* _retval) { - NS_ENSURE_ARG_POINTER(_retval); - *_retval = nsIAppWindow::normalZ; - // This can fail during window destruction. - nsWindowInfo* info = GetInfoFor(aWindow); - if (info) { - *_retval = info->mZLevel; - } - return NS_OK; -} - -NS_IMETHODIMP -nsWindowMediator::SetZLevel(nsIAppWindow* aWindow, uint32_t aZLevel) { - MOZ_RELEASE_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mReady); - NS_ENSURE_STATE(mReady); - - nsWindowInfo* info = GetInfoFor(aWindow); - NS_ASSERTION(info, "setting z level of unregistered window"); - if (!info) return NS_ERROR_FAILURE; - - if (info->mZLevel != aZLevel) { - bool lowered = info->mZLevel > aZLevel; - info->mZLevel = aZLevel; - if (lowered) - SortZOrderFrontToBack(); - else - SortZOrderBackToFront(); - } - return NS_OK; -} - -/* Fix potentially out-of-order windows by performing an insertion sort - on the z-order list. The method will work no matter how broken the - list, but its assumed usage is immediately after one window's z level - has been changed, so one window is potentially out of place. Such a sort - is most efficiently done in a particular direction. Use this one - if a window's z level has just been reduced, so the sort is most efficiently - done front to back. - Note it's hardly worth going to all the trouble to write two versions - of this method except that if we choose the inefficient sorting direction, - on slow systems windows could visibly bubble around the window that - was moved. -*/ -void nsWindowMediator::SortZOrderFrontToBack() { - nsWindowInfo *scan, // scans list looking for problems - *search, // searches for correct placement for scan window - *prev, // previous search element - *lowest; // bottom-most window in list - bool finished; - - if (!mTopmostWindow) // early during program execution there's no z list yet - return; // there's also only one window, so this is not dangerous - - mSortingZOrder = true; - - /* Step through the list from top to bottom. If we find a window which - should be moved down in the list, move it to its highest legal position. */ - do { - finished = true; - lowest = mTopmostWindow->mHigher; - scan = mTopmostWindow; - while (scan != lowest) { - uint32_t scanZ = scan->mZLevel; - if (scanZ < scan->mLower->mZLevel) { // out of order - search = scan->mLower; - do { - prev = search; - search = search->mLower; - } while (prev != lowest && scanZ < search->mZLevel); - - // reposition |scan| within the list - if (scan == mTopmostWindow) mTopmostWindow = scan->mLower; - scan->Unlink(false, true); - scan->InsertAfter(nullptr, prev); - - // fix actual window order - nsCOMPtr base; - nsCOMPtr scanWidget; - nsCOMPtr prevWidget; - base = do_QueryInterface(scan->mWindow); - if (base) base->GetMainWidget(getter_AddRefs(scanWidget)); - base = do_QueryInterface(prev->mWindow); - if (base) base->GetMainWidget(getter_AddRefs(prevWidget)); - if (scanWidget) - scanWidget->PlaceBehind(eZPlacementBelow, prevWidget, false); - - finished = false; - break; - } - scan = scan->mLower; - } - } while (!finished); - - mSortingZOrder = false; -} - -// see comment for SortZOrderFrontToBack -void nsWindowMediator::SortZOrderBackToFront() { - nsWindowInfo *scan, // scans list looking for problems - *search, // searches for correct placement for scan window - *lowest; // bottom-most window in list - bool finished; - - if (!mTopmostWindow) // early during program execution there's no z list yet - return; // there's also only one window, so this is not dangerous - - mSortingZOrder = true; - - /* Step through the list from bottom to top. If we find a window which - should be moved up in the list, move it to its lowest legal position. */ - do { - finished = true; - lowest = mTopmostWindow->mHigher; - scan = lowest; - while (scan != mTopmostWindow) { - uint32_t scanZ = scan->mZLevel; - if (scanZ > scan->mHigher->mZLevel) { // out of order - search = scan; - do { - search = search->mHigher; - } while (search != lowest && scanZ > search->mZLevel); - - // reposition |scan| within the list - if (scan != search && scan != search->mLower) { - scan->Unlink(false, true); - scan->InsertAfter(nullptr, search); - } - if (search == lowest) mTopmostWindow = scan; - - // fix actual window order - nsCOMPtr base; - nsCOMPtr scanWidget; - nsCOMPtr searchWidget; - base = do_QueryInterface(scan->mWindow); - if (base) base->GetMainWidget(getter_AddRefs(scanWidget)); - if (mTopmostWindow != scan) { - base = do_QueryInterface(search->mWindow); - if (base) base->GetMainWidget(getter_AddRefs(searchWidget)); - } - if (scanWidget) - scanWidget->PlaceBehind(eZPlacementBelow, searchWidget, false); - finished = false; - break; - } - scan = scan->mHigher; - } - } while (!finished); - - mSortingZOrder = false; -} - NS_IMPL_ISUPPORTS(nsWindowMediator, nsIWindowMediator, nsIObserver, nsISupportsWeakReference) diff --git a/xpfe/appshell/nsWindowMediator.h b/xpfe/appshell/nsWindowMediator.h index 578f901ea72a..9c23e8711037 100644 --- a/xpfe/appshell/nsWindowMediator.h +++ b/xpfe/appshell/nsWindowMediator.h @@ -56,14 +56,11 @@ class nsWindowMediator : public nsIWindowMediator, nsresult UnregisterWindow(nsWindowInfo* inInfo); nsWindowInfo* GetInfoFor(nsIAppWindow* aWindow); nsWindowInfo* GetInfoFor(nsIWidget* aWindow); - void SortZOrderFrontToBack(); - void SortZOrderBackToFront(); nsTArray mEnumeratorList; nsWindowInfo* mOldestWindow; nsWindowInfo* mTopmostWindow; int32_t mTimeStamp; - bool mSortingZOrder; bool mReady; typedef nsTObserverArray> ListenerArray;