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); }