From 5e3f4c41a64d68b93b88e66bb00d6d4d5092c0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 21 Aug 2009 12:57:24 +0000 Subject: [PATCH] * ServerApp now maintains a mask of workspaces with temporary mode settings, and reverts the modes if the app goes away (ie. if it crashes). * Desktop::SetScreenMode() also set the mode on the current screen, even if it should have been set on another screen. * Cleaned up the Desktop.h header. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32564 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 86 +++++-- src/servers/app/Desktop.h | 315 ++++++++++++----------- src/servers/app/ScreenConfigurations.cpp | 14 +- src/servers/app/ScreenConfigurations.h | 2 +- src/servers/app/ServerApp.cpp | 18 ++ src/servers/app/ServerApp.h | 13 +- 6 files changed, 260 insertions(+), 188 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index a2bbdafd4f..67a6434b22 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -931,6 +931,23 @@ Desktop::SetWorkspace(int32 index) } +void +Desktop::_SetCurrentWorkspaceConfiguration() +{ + ASSERT_MULTI_WRITE_LOCKED(fWindowLock); + + uint32 changedScreens; + fVirtualScreen.SetConfiguration(*this, + fWorkspaces[fCurrentWorkspace].CurrentScreenConfiguration(), + &changedScreens); + + for (int32 i = 0; changedScreens != 0; i++, changedScreens /= 2) { + if ((changedScreens & (1 << i)) != 0) + ScreenChanged(fVirtualScreen.ScreenAt(i)); + } +} + + /*! Changes the current workspace to the one specified by \a index. You must hold the all window lock when calling this method. */ @@ -998,15 +1015,7 @@ Desktop::_SetWorkspace(int32 index) fCurrentWorkspace = index; // Change the display modes, if needed - - uint32 changedScreens; - fVirtualScreen.SetConfiguration(*this, - fWorkspaces[index].CurrentScreenConfiguration(), &changedScreens); - - for (int32 i = 0; changedScreens != 0; i++, changedScreens /= 2) { - if ((changedScreens & (1 << i)) != 0) - ScreenChanged(fVirtualScreen.ScreenAt(i)); - } + _SetCurrentWorkspaceConfiguration(); // Show windows, and include them in the changed region - but only // those that were not visible before (or whose position changed) @@ -1143,6 +1152,12 @@ Desktop::SetScreenMode(int32 workspace, int32 id, const display_mode& mode, if (!memcmp(&oldMode, &mode, sizeof(display_mode))) return B_OK; + + // Set the new one + + status_t status = screen->SetMode(mode); + if (status != B_OK) + return status; } else { // retrieve from settings screen_configuration* configuration @@ -1153,12 +1168,6 @@ Desktop::SetScreenMode(int32 workspace, int32 id, const display_mode& mode, return B_OK; } - // Set the new one - - status_t status = screen->SetMode(mode); - if (status != B_OK) - return status; - // Update our configurations monitor_info info; @@ -1241,10 +1250,55 @@ Desktop::GetScreenFrame(int32 workspace, int32 id, BRect& frame) } +void +Desktop::RevertScreenModes(uint32 workspaces) +{ + if (workspaces == 0) + return; + + AutoWriteLocker _(fWindowLock); + + for (int32 workspace = 0; workspace < kMaxWorkspaces; workspace++) { + if ((workspaces & (1U << workspace)) == 0) + continue; + + // Revert all screens on this workspace + + // TODO: ideally, we would know which screens to revert - this way, too + // many of them could be reverted + + for (int32 index = 0; index < fVirtualScreen.CountScreens(); index++) { + Screen* screen = fVirtualScreen.ScreenAt(index); + + // retrieve configurations + screen_configuration* stored = fWorkspaces[workspace] + .StoredScreenConfiguration().CurrentByID(screen->ID()); + screen_configuration* current = fWorkspaces[workspace] + .CurrentScreenConfiguration().CurrentByID(screen->ID()); + + if ((stored != NULL && current != NULL + && !memcmp(&stored->mode, ¤t->mode, + sizeof(display_mode))) + || (stored == NULL && current == NULL)) + continue; + + if (stored == NULL) { + fWorkspaces[workspace].CurrentScreenConfiguration() + .Remove(current); + + if (workspace == fCurrentWorkspace) + _SetCurrentWorkspaceConfiguration(); + } else + SetScreenMode(workspace, screen->ID(), stored->mode, false); + } + } +} + + void Desktop::ScreenChanged(Screen* screen) { - ASSERT(fWindowLock.IsWriteLocked()); + ASSERT_MULTI_WRITE_LOCKED(fWindowLock); // the entire screen is dirty, because we're actually // operating on an all new buffer in memory diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index d0cee76713..acdb4b8a77 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -58,282 +58,285 @@ namespace BPrivate { class Desktop : public MessageLooper, public ScreenOwner { - public: +public: Desktop(uid_t userID); - virtual ~Desktop(); + virtual ~Desktop(); - status_t Init(); + status_t Init(); - uid_t UserID() const { return fUserID; } - virtual port_id MessagePort() const { return fMessagePort; } - area_id SharedReadOnlyArea() const + uid_t UserID() const { return fUserID; } + virtual port_id MessagePort() const { return fMessagePort; } + area_id SharedReadOnlyArea() const { return fSharedReadOnlyArea; } - ::EventDispatcher& EventDispatcher() { return fEventDispatcher; } + ::EventDispatcher& EventDispatcher() { return fEventDispatcher; } - void BroadcastToAllApps(int32 code); - void BroadcastToAllWindows(int32 code); + void BroadcastToAllApps(int32 code); + void BroadcastToAllWindows(int32 code); - // Mouse and cursor methods + // Mouse and cursor methods - void SetCursor(ServerCursor* cursor); - ServerCursorReference Cursor() const; - void SetLastMouseState(const BPoint& position, + void SetCursor(ServerCursor* cursor); + ServerCursorReference Cursor() const; + void SetLastMouseState(const BPoint& position, int32 buttons, Window* windowUnderMouse); // for use by the mouse filter only // both mouse position calls require // the Desktop object to be locked // already - void GetLastMouseState(BPoint* position, + void GetLastMouseState(BPoint* position, int32* buttons) const; // for use by ServerWindow - // Screen and drawing related methods + // Screen and drawing related methods - Screen* ScreenAt(int32 index) const + Screen* ScreenAt(int32 index) const { return fActiveScreen; } - Screen* ActiveScreen() const + Screen* ActiveScreen() const { return fActiveScreen; } - CursorManager& GetCursorManager() { return fCursorManager; } + CursorManager& GetCursorManager() { return fCursorManager; } - status_t SetScreenMode(int32 workspace, int32 id, + status_t SetScreenMode(int32 workspace, int32 id, const display_mode& mode, bool makeDefault); - status_t GetScreenMode(int32 workspace, int32 id, + status_t GetScreenMode(int32 workspace, int32 id, display_mode& mode); - status_t GetScreenFrame(int32 workspace, int32 id, + status_t GetScreenFrame(int32 workspace, int32 id, BRect& frame); + void RevertScreenModes(uint32 workspaces); - void ScreenChanged(Screen* screen); + void ScreenChanged(Screen* screen); - const ::VirtualScreen& VirtualScreen() const { return fVirtualScreen; } - DrawingEngine* GetDrawingEngine() const + const ::VirtualScreen& VirtualScreen() const + { return fVirtualScreen; } + DrawingEngine* GetDrawingEngine() const { return fVirtualScreen.DrawingEngine(); } - ::HWInterface* HWInterface() const + ::HWInterface* HWInterface() const { return fVirtualScreen.HWInterface(); } - // ScreenOwner implementation - void ScreenRemoved(Screen* screen) {} - void ScreenAdded(Screen* screen) {} - bool ReleaseScreen(Screen* screen) { return false; } + // ScreenOwner implementation + virtual void ScreenRemoved(Screen* screen) {} + virtual void ScreenAdded(Screen* screen) {} + virtual bool ReleaseScreen(Screen* screen) { return false; } - // Workspace methods + // Workspace methods - void SetWorkspaceAsync(int32 index); - void SetWorkspace(int32 index); - int32 CurrentWorkspace() + void SetWorkspaceAsync(int32 index); + void SetWorkspace(int32 index); + int32 CurrentWorkspace() { return fCurrentWorkspace; } - Workspace::Private& WorkspaceAt(int32 index) + Workspace::Private& WorkspaceAt(int32 index) { return fWorkspaces[index]; } - status_t SetWorkspacesLayout(int32 columns, int32 rows); - BRect WorkspaceFrame(int32 index) const; + status_t SetWorkspacesLayout(int32 columns, int32 rows); + BRect WorkspaceFrame(int32 index) const; - // Window methods + // Window methods - void ActivateWindow(Window* window); - void SendWindowBehind(Window* window, + void ActivateWindow(Window* window); + void SendWindowBehind(Window* window, Window* behindOf = NULL); - void ShowWindow(Window* window); - void HideWindow(Window* window); + void ShowWindow(Window* window); + void HideWindow(Window* window); - void MoveWindowBy(Window* window, float x, float y, + void MoveWindowBy(Window* window, float x, float y, int32 workspace = -1); - void ResizeWindowBy(Window* window, float x, + void ResizeWindowBy(Window* window, float x, float y); - bool SetWindowTabLocation(Window* window, + bool SetWindowTabLocation(Window* window, float location); - bool SetWindowDecoratorSettings(Window* window, + bool SetWindowDecoratorSettings(Window* window, const BMessage& settings); - void SetWindowWorkspaces(Window* window, + void SetWindowWorkspaces(Window* window, uint32 workspaces); - void AddWindow(Window* window); - void RemoveWindow(Window* window); + void AddWindow(Window* window); + void RemoveWindow(Window* window); - bool AddWindowToSubset(Window* subset, + bool AddWindowToSubset(Window* subset, Window* window); - void RemoveWindowFromSubset(Window* subset, + void RemoveWindowFromSubset(Window* subset, Window* window); - void FontsChanged(Window* window); + void FontsChanged(Window* window); - void SetWindowLook(Window* window, window_look look); - void SetWindowFeel(Window* window, window_feel feel); - void SetWindowFlags(Window* window, uint32 flags); - void SetWindowTitle(Window* window, + void SetWindowLook(Window* window, window_look look); + void SetWindowFeel(Window* window, window_feel feel); + void SetWindowFlags(Window* window, uint32 flags); + void SetWindowTitle(Window* window, const char* title); - Window* FocusWindow() const { return fFocus; } - Window* FrontWindow() const { return fFront; } - Window* BackWindow() const { return fBack; } + Window* FocusWindow() const { return fFocus; } + Window* FrontWindow() const { return fFront; } + Window* BackWindow() const { return fBack; } - Window* WindowAt(BPoint where); + Window* WindowAt(BPoint where); - Window* MouseEventWindow() const + Window* MouseEventWindow() const { return fMouseEventWindow; } - void SetMouseEventWindow(Window* window); + void SetMouseEventWindow(Window* window); - void SetViewUnderMouse(const Window* window, + void SetViewUnderMouse(const Window* window, int32 viewToken); - int32 ViewUnderMouse(const Window* window); + int32 ViewUnderMouse(const Window* window); - void SetFocusWindow(Window* window = NULL); - EventTarget* KeyboardEventTarget(); - void SetFocusLocked(const Window* window); + void SetFocusWindow(Window* window = NULL); + EventTarget* KeyboardEventTarget(); + void SetFocusLocked(const Window* window); - Window* FindWindowByClientToken(int32 token, + Window* FindWindowByClientToken(int32 token, team_id teamID); - EventTarget* FindTarget(BMessenger& messenger); + EventTarget* FindTarget(BMessenger& messenger); #if USE_MULTI_LOCKER - bool LockSingleWindow() + bool LockSingleWindow() { return fWindowLock.ReadLock(); } - void UnlockSingleWindow() + void UnlockSingleWindow() { fWindowLock.ReadUnlock(); } - bool LockAllWindows() + bool LockAllWindows() { return fWindowLock.WriteLock(); } - void UnlockAllWindows() + void UnlockAllWindows() { fWindowLock.WriteUnlock(); } - MultiLocker WindowLocker() { return fWindowLock; } + MultiLocker WindowLocker() { return fWindowLock; } #else // USE_MULTI_LOCKER - bool LockSingleWindow() + bool LockSingleWindow() { return fWindowLock.Lock(); } - void UnlockSingleWindow() + void UnlockSingleWindow() { fWindowLock.Unlock(); } - bool LockAllWindows() + bool LockAllWindows() { return fWindowLock.Lock(); } - void UnlockAllWindows() + void UnlockAllWindows() { fWindowLock.Unlock(); } #endif // USE_MULTI_LOCKER - void MarkDirty(BRegion& region); - void Redraw(); + void MarkDirty(BRegion& region); + void Redraw(); - BRegion& BackgroundRegion() + BRegion& BackgroundRegion() { return fBackgroundRegion; } - void RedrawBackground(); - void StoreWorkspaceConfiguration(int32 index); + void RedrawBackground(); + void StoreWorkspaceConfiguration(int32 index); - void AddWorkspacesView(WorkspacesView* view); - void RemoveWorkspacesView(WorkspacesView* view); + void AddWorkspacesView(WorkspacesView* view); + void RemoveWorkspacesView(WorkspacesView* view); - void MinimizeApplication(team_id team); - void BringApplicationToFront(team_id team); - void WindowAction(int32 windowToken, int32 action); + void MinimizeApplication(team_id team); + void BringApplicationToFront(team_id team); + void WindowAction(int32 windowToken, int32 action); - void WriteWindowList(team_id team, + void WriteWindowList(team_id team, BPrivate::LinkSender& sender); - void WriteWindowInfo(int32 serverToken, + void WriteWindowInfo(int32 serverToken, BPrivate::LinkSender& sender); - void WriteApplicationOrder(int32 workspace, + void WriteApplicationOrder(int32 workspace, BPrivate::LinkSender& sender); - void WriteWindowOrder(int32 workspace, + void WriteWindowOrder(int32 workspace, BPrivate::LinkSender& sender); - private: - void _LaunchInputServer(); - void _SetWorkspace(int32 index); - void _ShowWindow(Window* window, +private: + void _LaunchInputServer(); + void _SetCurrentWorkspaceConfiguration(); + void _SetWorkspace(int32 index); + void _ShowWindow(Window* window, bool affectsOtherWindows = true); - void _HideWindow(Window* window); + void _HideWindow(Window* window); - void _UpdateSubsetWorkspaces(Window* window, + void _UpdateSubsetWorkspaces(Window* window, int32 previousIndex = -1, int32 newIndex = -1); - void _ChangeWindowWorkspaces(Window* window, + void _ChangeWindowWorkspaces(Window* window, uint32 oldWorkspaces, uint32 newWorkspaces); - void _BringWindowsToFront(WindowList& windows, + void _BringWindowsToFront(WindowList& windows, int32 list, bool wereVisible); - Window* _LastFocusSubsetWindow(Window* window); - status_t _ActivateApp(team_id team); - void _SendFakeMouseMoved(Window* window = NULL); + Window* _LastFocusSubsetWindow(Window* window); + status_t _ActivateApp(team_id team); + void _SendFakeMouseMoved(Window* window = NULL); - void _RebuildClippingForAllWindows( + void _RebuildClippingForAllWindows( BRegion& stillAvailableOnScreen); - void _TriggerWindowRedrawing( + void _TriggerWindowRedrawing( BRegion& newDirtyRegion); - void _SetBackground(BRegion& background); - void _RebuildAndRedrawAfterWindowChange( + void _SetBackground(BRegion& background); + void _RebuildAndRedrawAfterWindowChange( Window* window, BRegion& dirty); - void _UpdateFloating(int32 previousWorkspace = -1, + void _UpdateFloating(int32 previousWorkspace = -1, int32 nextWorkspace = -1, Window* mouseEventWindow = NULL); - void _UpdateBack(); - void _UpdateFront(bool updateFloating = true); - void _UpdateFronts(bool updateFloating = true); - bool _WindowHasModal(Window* window); + void _UpdateBack(); + void _UpdateFront(bool updateFloating = true); + void _UpdateFronts(bool updateFloating = true); + bool _WindowHasModal(Window* window); - void _WindowChanged(Window* window); - void _WindowRemoved(Window* window); + void _WindowChanged(Window* window); + void _WindowRemoved(Window* window); - void _GetLooperName(char* name, size_t size); - void _PrepareQuit(); - void _DispatchMessage(int32 code, + void _GetLooperName(char* name, size_t size); + void _PrepareQuit(); + void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link); - WindowList& _CurrentWindows(); - WindowList& _Windows(int32 index); + WindowList& _CurrentWindows(); + WindowList& _Windows(int32 index); - private: - friend class DesktopSettings; - friend class LockedDesktopSettings; +private: + friend class DesktopSettings; + friend class LockedDesktopSettings; - uid_t fUserID; - ::VirtualScreen fVirtualScreen; - DesktopSettingsPrivate* fSettings; - port_id fMessagePort; - ::EventDispatcher fEventDispatcher; - port_id fInputPort; - area_id fSharedReadOnlyArea; - server_read_only_memory* fServerReadOnlyMemory; + uid_t fUserID; + ::VirtualScreen fVirtualScreen; + DesktopSettingsPrivate* fSettings; + port_id fMessagePort; + ::EventDispatcher fEventDispatcher; + port_id fInputPort; + area_id fSharedReadOnlyArea; + server_read_only_memory* fServerReadOnlyMemory; - BLocker fApplicationsLock; - BObjectList fApplications; + BLocker fApplicationsLock; + BObjectList fApplications; - sem_id fShutdownSemaphore; - int32 fShutdownCount; + sem_id fShutdownSemaphore; + int32 fShutdownCount; - ::Workspace::Private fWorkspaces[kMaxWorkspaces]; - int32 fCurrentWorkspace; - int32 fPreviousWorkspace; + ::Workspace::Private fWorkspaces[kMaxWorkspaces]; + int32 fCurrentWorkspace; + int32 fPreviousWorkspace; - WindowList fAllWindows; - WindowList fSubsetWindows; - WindowList fFocusList; + WindowList fAllWindows; + WindowList fSubsetWindows; + WindowList fFocusList; - BObjectList fWorkspacesViews; - BLocker fWorkspacesLock; + BObjectList fWorkspacesViews; + BLocker fWorkspacesLock; - Screen* fActiveScreen; + Screen* fActiveScreen; - CursorManager fCursorManager; + CursorManager fCursorManager; #if USE_MULTI_LOCKER - MultiLocker fWindowLock; + MultiLocker fWindowLock; #else - BLocker fWindowLock; + BLocker fWindowLock; #endif - BRegion fBackgroundRegion; - BRegion fScreenRegion; + BRegion fBackgroundRegion; + BRegion fScreenRegion; - Window* fMouseEventWindow; - const Window* fWindowUnderMouse; - const Window* fLockedFocusWindow; - int32 fViewUnderMouse; - BPoint fLastMousePosition; - int32 fLastMouseButtons; + Window* fMouseEventWindow; + const Window* fWindowUnderMouse; + const Window* fLockedFocusWindow; + int32 fViewUnderMouse; + BPoint fLastMousePosition; + int32 fLastMouseButtons; - Window* fFocus; - Window* fFront; - Window* fBack; + Window* fFocus; + Window* fFront; + Window* fBack; }; #endif // DESKTOP_H diff --git a/src/servers/app/ScreenConfigurations.cpp b/src/servers/app/ScreenConfigurations.cpp index d268ca4381..6e6d732c5a 100644 --- a/src/servers/app/ScreenConfigurations.cpp +++ b/src/servers/app/ScreenConfigurations.cpp @@ -143,18 +143,14 @@ ScreenConfigurations::Set(int32 id, const monitor_info* info, } -status_t -ScreenConfigurations::Update(int32 id, const display_mode& mode) +void +ScreenConfigurations::Remove(screen_configuration* configuration) { - screen_configuration* configuration = CurrentByID(id); if (configuration == NULL) - return B_BAD_VALUE; + return; - configuration->is_current = true; - - memcpy(&configuration->mode, &mode, sizeof(display_mode)); - - return B_OK; + fConfigurations.RemoveItem(configuration); + // this also deletes the configuration } diff --git a/src/servers/app/ScreenConfigurations.h b/src/servers/app/ScreenConfigurations.h index 959f24d8c3..2a9d4523b9 100644 --- a/src/servers/app/ScreenConfigurations.h +++ b/src/servers/app/ScreenConfigurations.h @@ -37,7 +37,7 @@ public: status_t Set(int32 id, const monitor_info* info, const BRect& frame, const display_mode& mode); - status_t Update(int32 id, const display_mode& mode); + void Remove(screen_configuration* configuration); status_t Store(BMessage& settings) const; status_t Restore(const BMessage& settings); diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 98848e9e7e..6dca402fbb 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -95,6 +96,7 @@ ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort, fSignature(signature), fClientTeam(clientTeam), fWindowListLock("window list"), + fTemporaryDisplayModeChange(0), fAppCursor(NULL), fViewCursor(NULL), fCursorHideLevel(0), @@ -185,6 +187,8 @@ ServerApp::~ServerApp() fWindowListLock.Lock(); } + fDesktop->RevertScreenModes(fTemporaryDisplayModeChange); + for (int32 i = fBitmapList.CountItems(); i-- > 0;) { gBitmapManager->DeleteBitmap((ServerBitmap*)fBitmapList.ItemAt(i)); } @@ -2319,6 +2323,20 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) status = fDesktop->SetScreenMode(workspace, id, mode, makeDefault); } + if (status == B_OK) { + if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX + && fDesktop->LockSingleWindow()) { + workspace = fDesktop->CurrentWorkspace(); + fDesktop->UnlockSingleWindow(); + } + + if (!makeDefault) { + // Memorize the screen change, so that it can be reverted + // later + fTemporaryDisplayModeChange |= 1 << workspace; + } else + fTemporaryDisplayModeChange &= ~(1 << workspace); + } fLink.StartMessage(status); fLink.Flush(); diff --git a/src/servers/app/ServerApp.h b/src/servers/app/ServerApp.h index e75a9593e3..ab4f59f42a 100644 --- a/src/servers/app/ServerApp.h +++ b/src/servers/app/ServerApp.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2006, Haiku. + * Copyright 2001-2009, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -41,11 +41,10 @@ namespace BPrivate { class ServerApp : public MessageLooper { public: ServerApp(Desktop* desktop, - port_id clientAppPort, - port_id clientLooperPort, - team_id clientTeamID, - int32 handlerID, - const char* signature); + port_id clientAppPort, + port_id clientLooperPort, + team_id clientTeamID, int32 handlerID, + const char* signature); virtual ~ServerApp(); status_t InitCheck(); @@ -105,6 +104,7 @@ private: bool _HasWindowUnderMouse(); +private: port_id fMessagePort; port_id fClientReplyPort; // our BApplication's event port @@ -128,6 +128,7 @@ private: BPrivate::BTokenSpace fViewTokens; int32 fInitialWorkspace; + uint32 fTemporaryDisplayModeChange; // NOTE: Bitmaps and Pictures are stored globally, but ServerApps // remember which ones they own so that they can destroy them when