From d02835660f6e033fa7e492ba5854448a16bb8945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 14 Nov 2008 13:37:27 +0000 Subject: [PATCH] * Added a method Desktop::_LastFocusSubsetWindow() which returns the last window being the focus window that is a subset of the specified window. * This is now used to bring the window to front belonging to a floating or modal window (if on another workspace), ie. Desktop::ActivateWindow() should now work with modal and floating windows. * Fixed typo (in Window.cpp). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28649 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 69 ++++++++++++++++++++++++------------- src/servers/app/Desktop.h | 1 + src/servers/app/Window.cpp | 2 +- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index c69263c0ea..3de855f34d 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -1532,8 +1532,26 @@ Desktop::_BringWindowsToFront(WindowList& windows, int32 list, } -/*! - \brief Tries to move the specified window to the front of the screen, +/*! Returns the last focussed non-hidden subset window belonging to the + specified \a window. +*/ +Window* +Desktop::_LastFocusSubsetWindow(Window* window) +{ + if (window == NULL) + return NULL; + + for (Window* front = fFocusList.LastWindow(); front != NULL; + front = front->PreviousWindow(kFocusList)) { + if (front != window && !front->IsHidden() && window->HasInSubset(front)) + return front; + } + + return NULL; +} + + +/*! \brief Tries to move the specified window to the front of the screen, and make it the focus window. If there are any modal windows on this screen, it might not actually @@ -1550,13 +1568,11 @@ Desktop::ActivateWindow(Window* window) fFront = NULL; return; } - if (window->Workspaces() == 0) + if (window->Workspaces() == 0 + && !window->IsFloating() && !window->IsModal()) return; - // TODO: take care about floating windows - - if (!LockAllWindows()) - return; + AutoWriteLocker _(fWindowLock); bool windowOnOtherWorkspace = !window->InWorkspace(fCurrentWorkspace); if (windowOnOtherWorkspace @@ -1573,17 +1589,26 @@ Desktop::ActivateWindow(Window* window) break; } } - } else { - UnlockAllWindows(); + } else return; - } } if (windowOnOtherWorkspace) { - // Bring the window to the current workspace - // TODO: what if this window is on multiple workspaces?!? - uint32 workspaces = workspace_to_workspaces(fCurrentWorkspace); - SetWindowWorkspaces(window, workspaces); + if (window->IsFloating() || window->IsModal()) { + // Bring a window to front that this floating window belongs to + Window* front = _LastFocusSubsetWindow(window); + if (front == NULL) { + // We can't do anything about those. + return; + } + + ActivateWindow(front); + } else { + // Bring the window to the current workspace + // TODO: what if this window is on multiple workspaces?!? + uint32 workspaces = workspace_to_workspaces(fCurrentWorkspace); + SetWindowWorkspaces(window, workspaces); + } } if (window->IsMinimized()) { @@ -1602,11 +1627,10 @@ Desktop::ActivateWindow(Window* window) } if (avoidsFront == NULL) { - // we're already the frontmost window, we might just not have focus yet + // we're already the frontmost window, we might just not have focus + // yet if ((window->Flags() & B_AVOID_FOCUS) == 0) SetFocusWindow(window); - - UnlockAllWindows(); return; } } @@ -1642,10 +1666,9 @@ Desktop::ActivateWindow(Window* window) } _BringWindowsToFront(windows, kWorkingList, true); + if ((window->Flags() & B_AVOID_FOCUS) == 0) SetFocusWindow(window); - - UnlockAllWindows(); } @@ -1706,19 +1729,19 @@ Desktop::ShowWindow(Window* window) if (!window->IsHidden()) return; - LockAllWindows(); + AutoWriteLocker locker(fWindowLock); window->SetHidden(false); fFocusList.AddWindow(window); - if (window->InWorkspace(fCurrentWorkspace)) { + if (window->InWorkspace(fCurrentWorkspace) + || (window->IsFloating() && _LastFocusSubsetWindow(window) != NULL)) { _ShowWindow(window, true); _UpdateSubsetWorkspaces(window); ActivateWindow(window); } else { // then we don't need to send the fake mouse event either _WindowChanged(window); - UnlockAllWindows(); return; } @@ -1728,8 +1751,6 @@ Desktop::ShowWindow(Window* window) window->FindWorkspacesViews(fWorkspacesViews); } - UnlockAllWindows(); - // If the mouse cursor is directly over the newly visible window, // we'll send a fake mouse moved message to the window, so that // it knows the mouse is over it. diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 21f9a550e8..9888f862a7 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -231,6 +231,7 @@ class Desktop : public MessageLooper, public ScreenOwner { uint32 oldWorkspaces, uint32 newWorkspaces); void _BringWindowsToFront(WindowList& windows, int32 list, bool wereVisible); + Window* _LastFocusSubsetWindow(Window* window); status_t _ActivateApp(team_id team); void _SendFakeMouseMoved(Window* window = NULL); diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp index 683d1a7524..90f789984d 100644 --- a/src/servers/app/Window.cpp +++ b/src/servers/app/Window.cpp @@ -1571,7 +1571,7 @@ Window::FindWorkspacesViews(BObjectList& list) const /*! \brief Returns on which workspaces the window should be visible. - A modal or floating window may be visible on a workscreen if one + A modal or floating window may be visible on a workspace if one of its subset windows is visible there. Floating windows also need to have a subset as front window to be visible. */