From d689f4578d9eacc7a45260e7d223e7fca53f1d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 13 Aug 2008 09:00:36 +0000 Subject: [PATCH] * Fixed a possible deadlock in Desktop::_ActivateApp(): since ActivateWindow() will need to write lock the window lock, we cannot call it with the read lock held. * Added a TODO comment in _ActivateApp() on how we could handle minimized windows. * Added a WindowList::Count() method. * Added a WindowList::ValidateWindow() that you can use to validate a window pointer in case you had to unlock the list. * Made FirstWindow()/LastWindow() const. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26957 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 20 ++++++-------------- src/servers/app/WindowList.cpp | 30 ++++++++++++++++++++++++++++++ src/servers/app/WindowList.h | 14 +++++++++----- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index bdc1dddd2b..b6986fb323 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -669,24 +669,19 @@ Desktop::_ActivateApp(team_id team) { // search for an unhidden window in the current workspace - LockSingleWindow(); + AutoWriteLocker locker(fWindowLock); for (Window* window = _CurrentWindows().LastWindow(); window != NULL; window = window->PreviousWindow(fCurrentWorkspace)) { if (!window->IsHidden() && window->IsNormal() && window->ServerWindow()->ClientTeam() == team) { ActivateWindow(window); - UnlockSingleWindow(); return B_OK; } } - UnlockSingleWindow(); - // search for an unhidden window to give focus to - AutoWriteLocker locker(fWindowLock); - for (Window* window = fAllWindows.FirstWindow(); window != NULL; window = window->NextWindow(kAllWindowList)) { // if window is a normal window of the team, and not hidden, @@ -698,6 +693,10 @@ Desktop::_ActivateApp(team_id team) } } + // TODO: we cannot maximize minimized windows here (with the window lock + // write locked). To work-around this, we could forward the request to + // the ServerApp of this team - it maintains its own window list, and can + // therefore call ActivateWindow() without holding the window lock. return B_BAD_VALUE; } @@ -2505,14 +2504,7 @@ Desktop::WriteWindowOrder(int32 workspace, BPrivate::LinkSender& sender) return; } - // compute the number of windows - - int32 count = 0; - - for (Window *window = _Windows(workspace).LastWindow(); window != NULL; - window = window->PreviousWindow(workspace)) { - count++; - } + int32 count = _Windows(workspace).Count(); // write list diff --git a/src/servers/app/WindowList.cpp b/src/servers/app/WindowList.cpp index 2fef7f2829..33c91d2ebf 100644 --- a/src/servers/app/WindowList.cpp +++ b/src/servers/app/WindowList.cpp @@ -128,3 +128,33 @@ WindowList::HasWindow(Window* window) const || fLastWindow == window; } + +/*! Unlike HasWindow(), this will not reference the window pointer. You + can use this method to check whether or not a window is still part + of a list (when it's possible that the window is already gone). +*/ +bool +WindowList::ValidateWindow(Window* validateWindow) const +{ + for (Window *window = FirstWindow(); window != NULL; + window = window->NextWindow(fIndex)) { + if (window == validateWindow) + return true; + } + + return false; +} + + +int32 +WindowList::Count() const +{ + int32 count = 0; + + for (Window *window = FirstWindow(); window != NULL; + window = window->NextWindow(fIndex)) { + count++; + } + + return count; +} diff --git a/src/servers/app/WindowList.h b/src/servers/app/WindowList.h index 8459418f47..fd11f7ac78 100644 --- a/src/servers/app/WindowList.h +++ b/src/servers/app/WindowList.h @@ -23,14 +23,18 @@ public: void SetIndex(int32 index); int32 Index() const { return fIndex; } - - Window* FirstWindow() { return fFirstWindow; } - Window* LastWindow() { return fLastWindow; } - + + Window* FirstWindow() const { return fFirstWindow; } + Window* LastWindow() const { return fLastWindow; } + void AddWindow(Window* window, Window* before = NULL); void RemoveWindow(Window* window); - + bool HasWindow(Window* window) const; + bool ValidateWindow(Window* window) const; + + int32 Count() const; + // O(n) private: int32 fIndex;