* 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
This commit is contained in:
Axel Dörfler
2009-08-21 12:57:24 +00:00
parent c1df12d278
commit 5e3f4c41a6
6 changed files with 260 additions and 188 deletions
+70 -16
View File
@@ -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, &current->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
+159 -156
View File
@@ -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<ServerApp> fApplications;
BLocker fApplicationsLock;
BObjectList<ServerApp> 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<WorkspacesView> fWorkspacesViews;
BLocker fWorkspacesLock;
BObjectList<WorkspacesView> 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
+5 -9
View File
@@ -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
}
+1 -1
View File
@@ -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);
+18
View File
@@ -36,6 +36,7 @@
#include <FontPrivate.h>
#include <MessengerPrivate.h>
#include <PrivateScreen.h>
#include <RosterPrivate.h>
#include <ServerProtocol.h>
#include <WindowPrivate.h>
@@ -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();
+7 -6
View File
@@ -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