From 27c43a2d8f20fd98050c6acd9abac970b1d4d7c8 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 9 Dec 2008 02:50:23 +0000 Subject: [PATCH] Implement the missing pieces to handle per workspace display mode support. Adjust Workspace view to correctly scale each workspace based on the resolution of that workspace. This exposes one or two anomalies in other places in the app_server code though which I wasn't able to track down. This fixes ticket #693. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28785 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/preferences/screen/ScreenWindow.cpp | 9 ++-- src/servers/app/Desktop.cpp | 59 +++++++++++++++++++++---- src/servers/app/Desktop.h | 4 +- src/servers/app/Screen.cpp | 8 +++- src/servers/app/ServerApp.cpp | 31 ++++++++----- src/servers/app/VirtualScreen.cpp | 1 + src/servers/app/WorkspacesView.cpp | 2 +- 7 files changed, 84 insertions(+), 30 deletions(-) diff --git a/src/preferences/screen/ScreenWindow.cpp b/src/preferences/screen/ScreenWindow.cpp index 9032f5dd33..2baaa244d9 100644 --- a/src/preferences/screen/ScreenWindow.cpp +++ b/src/preferences/screen/ScreenWindow.cpp @@ -246,12 +246,8 @@ ScreenWindow::ScreenWindow(ScreenSettings *settings) BMenuItem *item = new BMenuItem("Current Workspace", new BMessage(WORKSPACE_CHECK_MSG)); - // TODO: since per workspace settings is unimplemented (Ticket #693) - // we force the menu to "All Workspaces" for now - fAllWorkspacesItem->SetMarked(true); - item->SetEnabled(false); - popUpMenu->AddItem(item); + fAllWorkspacesItem->SetMarked(true); BMenuField* workspaceMenuField = new BMenuField(BRect(0, 0, 100, 15), "WorkspaceMenu", NULL, popUpMenu, true); @@ -1008,7 +1004,8 @@ ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const void ScreenWindow::_CheckApplyEnabled() { - fApplyButton->SetEnabled(fSelected != fActive); + fApplyButton->SetEnabled(fSelected != fActive + || fAllWorkspacesItem->IsMarked()); fRevertButton->SetEnabled(count_workspaces() != fOriginalWorkspaceCount || fSelected != fOriginal); } diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index b8de730bff..63300f883d 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -878,6 +878,29 @@ Desktop::SetWorkspacesCount(int32 newCount) } +/*! + Returns the virtual screen frame of the workspace specified by \a index. +*/ +BRect +Desktop::WorkspaceFrame(int32 index) const +{ + BRect frame; + if (index == fCurrentWorkspace) + frame = fVirtualScreen.Frame(); + else if (index >= 0 && index < fSettings->WorkspacesCount()) { + BMessage screenData; + int32 width; + int32 height; + fSettings->WorkspacesMessage(index)->FindMessage("screen", &screenData); + if (screenData.FindInt32("width", &width) != B_OK || screenData.FindInt32("height", &height) != B_OK) + frame = fVirtualScreen.Frame(); + else + frame.Set(0.0, 0.0, width - 1, height - 1); + } + return frame; +} + + /*! Changes the current workspace to the one specified by \a index. */ @@ -913,7 +936,6 @@ Desktop::SetWorkspace(int32 index) _SendFakeMouseMoved(); } - /*! Changes the current workspace to the one specified by \a index. You must hold the all window lock when calling this method. */ @@ -923,6 +945,13 @@ Desktop::_SetWorkspace(int32 index) int32 previousIndex = fCurrentWorkspace; rgb_color previousColor = fWorkspaces[fCurrentWorkspace].Color(); bool movedMouseEventWindow = false; + display_mode previousMode, newMode; + fVirtualScreen.ScreenAt(0)->GetMode(&previousMode); + fVirtualScreen.RestoreConfiguration(*this, fSettings->WorkspacesMessage(index)); + fVirtualScreen.ScreenAt(0)->GetMode(&newMode); + // We only need to invalidate the entire desktop if we changed display modes + if (memcmp(&previousMode, &newMode, sizeof(display_mode))) + ScreenChanged(fVirtualScreen.ScreenAt(0), false); if (fMouseEventWindow != NULL) { if (fMouseEventWindow->IsNormal()) { @@ -1095,7 +1124,8 @@ Desktop::ScreenChanged(Screen* screen, bool makeDefault) BRegion dirty(screen->Frame()); // update our cached screen region fScreenRegion.Set(screen->Frame()); - + gInputManager->UpdateScreenBounds(screen->Frame()); + BRegion background; _RebuildClippingForAllWindows(background); @@ -1122,17 +1152,28 @@ Desktop::ScreenChanged(Screen* screen, bool makeDefault) fVirtualScreen.UpdateFrame(); if (makeDefault) { - // store settings - BMessage settings; - fVirtualScreen.StoreConfiguration(settings); - fWorkspaces[fCurrentWorkspace].StoreConfiguration(settings); - - fSettings->SetWorkspacesMessage(fCurrentWorkspace, settings); - fSettings->Save(kWorkspacesSettings); + StoreConfiguration(fCurrentWorkspace); } } +status_t +Desktop::StoreConfiguration(int32 workspace) +{ + if (workspace >= 0 && workspace < fSettings->WorkspacesCount()) { + // store settings + BMessage settings; + fVirtualScreen.StoreConfiguration(settings); + fWorkspaces[workspace].StoreConfiguration(settings); + + fSettings->SetWorkspacesMessage(workspace, settings); + fSettings->Save(kWorkspacesSettings); + return B_OK; + } + + return B_BAD_VALUE; +} + // #pragma mark - Methods for Window manipulation diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index f5165ad53b..af5ea0a504 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -91,12 +91,11 @@ class Desktop : public MessageLooper, public ScreenOwner { void GetLastMouseState(BPoint* position, int32* buttons) const; // for use by ServerWindow - void ScreenChanged(Screen* screen, bool makeDefault); - void ScreenRemoved(Screen* screen) {} void ScreenAdded(Screen* screen) {} bool ReleaseScreen(Screen* screen) { return false; } + status_t StoreConfiguration(int32 workspace); const ::VirtualScreen& VirtualScreen() const { return fVirtualScreen; } DrawingEngine* GetDrawingEngine() const @@ -113,6 +112,7 @@ class Desktop : public MessageLooper, public ScreenOwner { Workspace::Private& WorkspaceAt(int32 index) { return fWorkspaces[index]; } status_t SetWorkspacesCount(int32 newCount); + BRect WorkspaceFrame(int32 index) const; // Window methods diff --git a/src/servers/app/Screen.cpp b/src/servers/app/Screen.cpp index 1975e0f309..17531269d2 100644 --- a/src/servers/app/Screen.cpp +++ b/src/servers/app/Screen.cpp @@ -22,7 +22,6 @@ #include #include - static float get_mode_frequency(const display_mode& mode) { @@ -91,6 +90,12 @@ Screen::Shutdown() status_t Screen::SetMode(const display_mode& mode, bool makeDefault) { + display_mode current; + GetMode(¤t); + current.flags = mode.flags; + if (!memcmp(&mode, ¤t, sizeof(display_mode))) + return B_OK; + gBitmapManager->SuspendOverlays(); status_t status = fHWInterface->SetMode(mode); @@ -162,7 +167,6 @@ Screen::SetBestMode(uint16 width, uint16 height, uint32 colorSpace, * mode.timing.v_total / 10 * int32(frequency * 10)) / 1000; adjusted = true; } - status = SetMode(mode, false); if (status < B_OK && adjusted) { // try again with the unchanged mode diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 28222d4d09..ddb2de59e0 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -2167,7 +2167,6 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) // 2) workspace index // 3) display_mode to set // 4) 'makeDefault' boolean - // TODO: See above: workspaces support, etc. screen_id id; link.Read(&id); @@ -2183,15 +2182,27 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) if (status == B_OK && fDesktop->LockAllWindows()) { display_mode oldMode; - fDesktop->ScreenAt(0)->GetMode(&oldMode); - if (memcmp(&oldMode, &mode, sizeof(display_mode))) { - status = fDesktop->ScreenAt(0)->SetMode(mode, makeDefault); - if (status == B_OK) { - gInputManager->UpdateScreenBounds(fDesktop->ScreenAt(0)->Frame()); - fDesktop->ScreenChanged(fDesktop->ScreenAt(0), makeDefault); - } - } else - status = B_OK; + if (workspace == (uint32)fDesktop->CurrentWorkspace()) { + fDesktop->ScreenAt(0)->GetMode(&oldMode); + if (memcmp(&oldMode, &mode, sizeof(display_mode))) { + status = fDesktop->ScreenAt(0)->SetMode(mode, makeDefault); + if (status == B_OK) { + fDesktop->ScreenChanged(fDesktop->ScreenAt(0), makeDefault); + } + } else + status = B_OK; + } else { + // this is perhaps not ideal - it assumes that if the + // workspace is not the active one, then pull the + // configuration from active and store it to the specified + // workspace. This is safer since it's assumed that the + // active workspace has a display mode that's usable, + // but at the same time the API implies that you can set + // a non-visible workspace to whatever mode you like + // TODO: decide what to do here. + if (makeDefault) + fDesktop->StoreConfiguration(workspace); + } fDesktop->UnlockAllWindows(); } else status = B_ERROR; diff --git a/src/servers/app/VirtualScreen.cpp b/src/servers/app/VirtualScreen.cpp index 37088e7675..484e9c3355 100644 --- a/src/servers/app/VirtualScreen.cpp +++ b/src/servers/app/VirtualScreen.cpp @@ -167,6 +167,7 @@ VirtualScreen::AddScreen(Screen* screen) fDrawingEngine = screen->GetDrawingEngine(); fHWInterface = screen->HWInterface(); fFrame = screen->Frame(); + item->frame = fFrame; fScreenList.AddItem(item); diff --git a/src/servers/app/WorkspacesView.cpp b/src/servers/app/WorkspacesView.cpp index 24698088d7..3e10334125 100644 --- a/src/servers/app/WorkspacesView.cpp +++ b/src/servers/app/WorkspacesView.cpp @@ -80,7 +80,7 @@ WorkspacesView::_GetGrid(int32& columns, int32& rows) BRect WorkspacesView::_ScreenFrame(int32 i) { - return Window()->Desktop()->VirtualScreen().Frame(); + return Window()->Desktop()->WorkspaceFrame(i); }