Massive RootLayer & Workspace tearing:

* workspace switch and subset windows functionality temporarily removed
  (away with that mess!).
* no more RevealWMState() - we now have methods like ActivateWindow()
  and SendWindowBehind() that do all the work - just a little cleaner
  and with less overhead.
* Workspace is now a pretty passive class - it only stores configurations
  of the windows and screens.
* added an evil work-around for a locking problem (in RootLayer::_SetFocus()).
* I'll plan to move pretty much all of the remaining root layer functionality
  to Desktop - so that the all regions lock is only held in case clipping
  regions are affected.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15207 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-11-28 23:36:59 +00:00
parent 8fc80f17d9
commit 27adb96962
14 changed files with 707 additions and 3069 deletions

View File

@ -98,19 +98,8 @@ KeyboardFilter::Filter(BMessage* message, BHandler** /*_target*/)
#endif
{
STRACE(("Set Workspace %ld\n", key - 1));
RootLayer* root = fDesktop->RootLayer();
root->Lock();
root->SetActiveWorkspace(key - 2);
#ifdef APPSERVER_ROOTLAYER_SHOW_WORKSPACE_NUMBER
// to draw the current Workspace index on screen.
BRegion region(VisibleRegion());
fDesktop->GetDrawingEngine()->ConstrainClippingRegion(&region);
root->Draw(region.Frame());
fDesktop->GetDrawingEngine()->ConstrainClippingRegion(NULL);
#endif
root->Unlock();
fDesktop->SetWorkspace(key - 2);
return B_SKIP_MESSAGE;
}
}
@ -188,7 +177,7 @@ Desktop::Init()
// TODO: add user identity to the name
char name[32];
sprintf(name, "RootLayer %d", 1);
fRootLayer = new ::RootLayer(name, 4, this, GetDrawingEngine());
fRootLayer = new ::RootLayer(name, this, GetDrawingEngine());
#if TEST_MODE
gInputManager->AddStream(new InputServerStream);
@ -436,20 +425,13 @@ Desktop::_ActivateApp(team_id team)
int32 windowCount = WindowList().CountItems();
for (int32 i = 0; i < windowCount; ++i) {
// is this layer in fact a WindowLayer?
WindowLayer *winBorder = WindowList().ItemAt(i);
WindowLayer *windowLayer = WindowList().ItemAt(i);
// if winBorder is valid and not hidden, then we've found our target
if (winBorder != NULL && !winBorder->IsHidden()
&& winBorder->App()->ClientTeam() == team) {
if (fRootLayer->Lock()) {
fRootLayer->SetActive(winBorder);
fRootLayer->Unlock();
if (fRootLayer->Active() == winBorder)
return B_OK;
status = B_ERROR;
}
if (windowLayer != NULL && !windowLayer->IsHidden()
&& windowLayer->App()->ClientTeam() == team) {
fRootLayer->ActivateWindow(windowLayer);
return B_OK;
}
}
@ -480,6 +462,19 @@ Desktop::BroadcastToAllApps(int32 code)
}
void
Desktop::SetWorkspace(int32 index)
{
BAutolock _(this);
DesktopSettings settings(this);
if (index < 0 || index >= settings.WorkspacesCount())
return;
fRootLayer->SetWorkspace(index, fWorkspaces[index]);
}
void
Desktop::ScreenChanged(Screen* screen)
{
@ -506,204 +501,72 @@ Desktop::ScreenChanged(Screen* screen)
void
Desktop::AddWindowLayer(WindowLayer *winBorder)
Desktop::ActivateWindow(WindowLayer* windowLayer)
{
if (!winBorder)
return;
fRootLayer->ActivateWindow(windowLayer);
}
int32 feel = winBorder->Feel();
// we are ServerApp thread, we need to lock RootLayer here.
RootLayer()->Lock();
void
Desktop::SendBehindWindow(WindowLayer* windowLayer, WindowLayer* front)
{
fRootLayer->SendBehindWindow(windowLayer, front);
}
// we're playing with window list. lock first.
void
Desktop::SetWindowWorkspaces(WindowLayer* windowLayer, uint32 workspaces)
{
BAutolock _(this);
windowLayer->SetWorkspaces(workspaces);
// is the window still visible on screen?
bool remove = (workspaces & (1UL << CurrentWorkspace())) == 0;
if (remove && windowLayer->Parent() != NULL) {
// the window is no longer visible on screen
fRootLayer->RemoveWindowLayer(windowLayer);
} else if (!remove && windowLayer->Parent() == NULL) {
// the window is now visible on screen
fRootLayer->AddWindowLayer(windowLayer);
}
}
void
Desktop::AddWindowLayer(WindowLayer *windowLayer)
{
Lock();
if (fWindowLayerList.HasItem(winBorder)) {
if (fWindowLayerList.HasItem(windowLayer)) {
Unlock();
RootLayer()->Unlock();
debugger("AddWindowLayer: WindowLayer already in Desktop list\n");
return;
}
// we have a new window. store a record of it.
fWindowLayerList.AddItem(winBorder);
// add FLOATING_APP windows to the local list of all normal windows.
// This is to keep the order all floating windows (app or subset) when we go from
// one normal window to another.
if (feel == B_FLOATING_APP_WINDOW_FEEL || feel == B_NORMAL_WINDOW_FEEL) {
WindowLayer *wb = NULL;
int32 count = fWindowLayerList.CountItems();
int32 feelToLookFor = (feel == B_NORMAL_WINDOW_FEEL ?
B_FLOATING_APP_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL);
for (int32 i = 0; i < count; i++) {
wb = (WindowLayer *)fWindowLayerList.ItemAt(i);
if (wb->App()->ClientTeam() == winBorder->App()->ClientTeam()
&& wb->Feel() == feelToLookFor) {
// R2: RootLayer comparison is needed.
feel == B_NORMAL_WINDOW_FEEL ?
winBorder->fSubWindowList.AddWindowLayer(wb) :
wb->fSubWindowList.AddWindowLayer(winBorder);
}
}
}
// add application's list of modal windows.
if (feel == B_MODAL_APP_WINDOW_FEEL) {
winBorder->App()->fAppSubWindowList.AddWindowLayer(winBorder);
}
// send WindowLayer to be added to workspaces
RootLayer()->AddWindowLayer(winBorder);
// hey, unlock!
fWindowLayerList.AddItem(windowLayer);
Unlock();
RootLayer()->Unlock();
RootLayer()->AddWindowLayer(windowLayer);
}
void
Desktop::RemoveWindowLayer(WindowLayer *winBorder)
Desktop::RemoveWindowLayer(WindowLayer *windowLayer)
{
if (!winBorder)
return;
// we are ServerApp thread, we need to lock RootLayer here.
RootLayer()->Lock();
// we're playing with window list. lock first.
Lock();
// remove from main WindowLayer list.
if (fWindowLayerList.RemoveItem(winBorder)) {
int32 feel = winBorder->Feel();
// floating app/subset and modal_subset windows require special atention because
// they are/may_be added to the list of a lot normal windows.
if (feel == B_FLOATING_SUBSET_WINDOW_FEEL
|| feel == B_MODAL_SUBSET_WINDOW_FEEL
|| feel == B_FLOATING_APP_WINDOW_FEEL)
{
WindowLayer *wb = NULL;
int32 count = fWindowLayerList.CountItems();
for (int32 i = 0; i < count; i++) {
wb = (WindowLayer*)fWindowLayerList.ItemAt(i);
if (wb->Feel() == B_NORMAL_WINDOW_FEEL
&& wb->App()->ClientTeam() == winBorder->App()->ClientTeam()) {
// R2: RootLayer comparison is needed. We'll see.
wb->fSubWindowList.RemoveItem(winBorder);
}
}
}
// remove from application's list
if (feel == B_MODAL_APP_WINDOW_FEEL) {
winBorder->App()->fAppSubWindowList.RemoveItem(winBorder);
}
} else {
Unlock();
RootLayer()->Unlock();
debugger("RemoveWindowLayer: WindowLayer not found in Desktop list\n");
return;
}
// Tell to winBorder's RootLayer about this.
RootLayer()->RemoveWindowLayer(winBorder);
fWindowLayerList.RemoveItem(windowLayer);
Unlock();
RootLayer()->Unlock();
}
void
Desktop::AddWindowLayerToSubset(WindowLayer *winBorder, WindowLayer *toWindowLayer)
{
// NOTE: we can safely lock the entire method body, because this method is called from
// RootLayer's thread only.
// we're playing with window list. lock first.
Lock();
if (!winBorder || !toWindowLayer
|| !fWindowLayerList.HasItem(winBorder)
|| !fWindowLayerList.HasItem(toWindowLayer)) {
Unlock();
debugger("AddWindowLayerToSubset: NULL WindowLayer or not found in Desktop list\n");
return;
}
if ((winBorder->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL
|| winBorder->Feel() == B_MODAL_SUBSET_WINDOW_FEEL)
&& toWindowLayer->Feel() == B_NORMAL_WINDOW_FEEL
&& toWindowLayer->App()->ClientTeam() == winBorder->App()->ClientTeam()
&& !toWindowLayer->fSubWindowList.HasItem(winBorder)) {
// add to normal_window's list
toWindowLayer->fSubWindowList.AddWindowLayer(winBorder);
} else {
Unlock();
debugger("AddWindowLayerToSubset: you must add a subset_window to a normal_window's subset with the same team_id\n");
return;
}
// send WindowLayer to be added to workspaces, if not already in there.
RootLayer()->AddSubsetWindowLayer(winBorder, toWindowLayer);
Unlock();
}
void
Desktop::RemoveWindowLayerFromSubset(WindowLayer *winBorder, WindowLayer *fromWindowLayer)
{
// NOTE: we can safely lock the entire method body, because this method is called from
// RootLayer's thread only.
// we're playing with window list. lock first.
Lock();
if (!winBorder || !fromWindowLayer
|| !fWindowLayerList.HasItem(winBorder)
|| !fWindowLayerList.HasItem(fromWindowLayer)) {
Unlock();
debugger("RemoveWindowLayerFromSubset: NULL WindowLayer or not found in Desktop list\n");
return;
}
// remove WindowLayer from workspace, if needed - some other windows may still have it in their subset
RootLayer()->RemoveSubsetWindowLayer(winBorder, fromWindowLayer);
if (fromWindowLayer->Feel() == B_NORMAL_WINDOW_FEEL) {
//remove from this normal_window's subset.
fromWindowLayer->fSubWindowList.RemoveItem(winBorder);
} else {
Unlock();
debugger("RemoveWindowLayerFromSubset: you must remove a subset_window from a normal_window's subset\n");
return;
}
Unlock();
RootLayer()->RemoveWindowLayer(windowLayer);
}
void
Desktop::SetWindowLayerFeel(WindowLayer *winBorder, uint32 feel)
{
// NOTE: this method is called from RootLayer thread only
// we're playing with window list. lock first.
Lock();
RemoveWindowLayer(winBorder);
winBorder->QuietlySetFeel(feel);
AddWindowLayer(winBorder);
Unlock();
// TODO: implement
}

View File

@ -7,8 +7,8 @@
* Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef _DESKTOP_H_
#define _DESKTOP_H_
#ifndef DESKTOP_H
#define DESKTOP_H
#include "CursorManager.h"
@ -18,6 +18,7 @@
#include "VirtualScreen.h"
#include "DesktopSettings.h"
#include "MessageLooper.h"
#include "Workspace.h"
#include <InterfaceDefs.h>
#include <List.h>
@ -41,87 +42,103 @@ namespace BPrivate {
class Desktop : public MessageLooper, public ScreenOwner {
public:
// startup methods
public:
Desktop(uid_t userID);
virtual ~Desktop();
virtual ~Desktop();
void Init();
void Init();
uid_t UserID() const { return fUserID; }
virtual port_id MessagePort() const { return fMessagePort; }
uid_t UserID() const { return fUserID; }
virtual port_id MessagePort() const { return fMessagePort; }
::EventDispatcher& EventDispatcher() { return fEventDispatcher; }
::EventDispatcher& EventDispatcher() { return fEventDispatcher; }
void BroadcastToAllApps(int32 code);
void BroadcastToAllApps(int32 code);
// Methods for multiple monitors.
inline Screen* ScreenAt(int32 index) const
// Screen and drawing related methods
Screen* ScreenAt(int32 index) const
{ return fActiveScreen; }
inline Screen* ActiveScreen() const
Screen* ActiveScreen() const
{ return fActiveScreen; }
inline ::RootLayer* RootLayer() const { return fRootLayer; }
inline CursorManager& GetCursorManager() { return fCursorManager; }
::RootLayer* RootLayer() const { return fRootLayer; }
CursorManager& GetCursorManager() { return fCursorManager; }
void ScreenChanged(Screen* screen);
void ScreenChanged(Screen* screen);
virtual void ScreenRemoved(Screen* screen) {}
virtual void ScreenAdded(Screen* screen) {}
virtual bool ReleaseScreen(Screen* screen) { return false; }
void ScreenRemoved(Screen* screen) {}
void ScreenAdded(Screen* screen) {}
bool ReleaseScreen(Screen* screen) { return false; }
const ::VirtualScreen& VirtualScreen() const { return fVirtualScreen; }
inline DrawingEngine* GetDrawingEngine() const
const ::VirtualScreen& VirtualScreen() const { return fVirtualScreen; }
DrawingEngine* GetDrawingEngine() const
{ return fVirtualScreen.DrawingEngine(); }
inline ::HWInterface* HWInterface() const
::HWInterface* HWInterface() const
{ return fVirtualScreen.HWInterface(); }
// Methods for layer(WindowLayer) manipulation.
void AddWindowLayer(WindowLayer *winBorder);
void RemoveWindowLayer(WindowLayer *winBorder);
void SetWindowLayerFeel(WindowLayer *winBorder,
uint32 feel);
void AddWindowLayerToSubset(WindowLayer *winBorder,
WindowLayer *toWindowLayer);
void RemoveWindowLayerFromSubset(WindowLayer *winBorder,
WindowLayer *fromWindowLayer);
// Workspace methods
WindowLayer* FindWindowLayerByClientToken(int32 token, team_id teamID);
//WindowLayer* FindWindowLayerByServerToken(int32 token);
void SetWorkspace(int32 index);
int32 CurrentWorkspace()
{ return fCurrentWorkspace; }
::Workspace& WorkspaceAt(int32 index)
{ return fWorkspaces[index]; }
// get list of registed windows
const BObjectList<WindowLayer>& WindowList() const;
// WindowLayer methods
void WriteWindowList(team_id team, BPrivate::LinkSender& sender);
void WriteWindowInfo(int32 serverToken, BPrivate::LinkSender& sender);
void ActivateWindow(WindowLayer* window);
void SendBehindWindow(WindowLayer* window, WindowLayer* front);
private:
status_t _ActivateApp(team_id team);
virtual void _GetLooperName(char* name, size_t size);
virtual void _PrepareQuit();
virtual void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
void SetWindowWorkspaces(WindowLayer* window, uint32 workspaces);
private:
friend class DesktopSettings;
void AddWindowLayer(WindowLayer *windowLayer);
void RemoveWindowLayer(WindowLayer *windowLayer);
void SetWindowLayerFeel(WindowLayer *windowLayer,
uint32 feel);
uid_t fUserID;
::VirtualScreen fVirtualScreen;
DesktopSettings::Private* fSettings;
port_id fMessagePort;
::EventDispatcher fEventDispatcher;
port_id fInputPort;
WindowLayer* FindWindowLayerByClientToken(int32 token, team_id teamID);
//WindowLayer* FindWindowLayerByServerToken(int32 token);
BLocker fAppListLock;
BList fAppList;
// get list of registed windows
const BObjectList<WindowLayer>& WindowList() const;
sem_id fShutdownSemaphore;
int32 fShutdownCount;
void WriteWindowList(team_id team,
BPrivate::LinkSender& sender);
void WriteWindowInfo(int32 serverToken,
BPrivate::LinkSender& sender);
BObjectList<WindowLayer> fWindowLayerList;
private:
status_t _ActivateApp(team_id team);
void _GetLooperName(char* name, size_t size);
void _PrepareQuit();
void _DispatchMessage(int32 code,
BPrivate::LinkReceiver &link);
::RootLayer* fRootLayer;
Screen* fActiveScreen;
CursorManager fCursorManager;
private:
friend class DesktopSettings;
uid_t fUserID;
::VirtualScreen fVirtualScreen;
DesktopSettings::Private* fSettings;
port_id fMessagePort;
::EventDispatcher fEventDispatcher;
port_id fInputPort;
BLocker fAppListLock;
BList fAppList;
sem_id fShutdownSemaphore;
int32 fShutdownCount;
::Workspace fWorkspaces[32];//kMaxWorkspaces];
int32 fCurrentWorkspace;
BObjectList<WindowLayer> fWindowLayerList;
::RootLayer* fRootLayer;
Screen* fActiveScreen;
CursorManager fCursorManager;
};
#endif // _DESKTOP_H_
#endif // DESKTOP_H

File diff suppressed because it is too large Load Diff

View File

@ -40,116 +40,103 @@ namespace BPrivate {
class UtilityBitmap;
#endif
/*!
\class RootLayer RootLayer.h
\brief Class used for the top layer of each workspace's Layer tree
RootLayers are used to head up the top of each Layer tree and reimplement certain
Layer functions to act accordingly. There is only one for each workspace class.
*/
class RootLayer : public Layer {
public:
RootLayer(const char *name, int32 workspaceCount,
Desktop *desktop, DrawingEngine *driver);
virtual ~RootLayer(void);
public:
RootLayer(const char *name, Desktop *desktop,
DrawingEngine *driver);
virtual ~RootLayer();
Desktop* GetDesktop() const { return fDesktop; }
Desktop* GetDesktop() const { return fDesktop; }
virtual void MoveBy(float x, float y);
virtual void ResizeBy(float x, float y);
virtual void ScrollBy(float x, float y)
{ /* not allowed */ }
virtual void MoveBy(float x, float y);
virtual void ResizeBy(float x, float y);
virtual void ScrollBy(float x, float y)
{ /* not allowed */ }
void HideWindowLayer(WindowLayer* windowLayer);
void ShowWindowLayer(WindowLayer* windowLayer);
void SetWindowLayerWorskpaces(WindowLayer *windowLayer,
uint32 oldIndex, uint32 newIndex);
void HideWindowLayer(WindowLayer* windowLayer);
void ShowWindowLayer(WindowLayer* windowLayer, bool toFront = true);
void RevealNewWMState(Workspace::State &oldWMState);
// TODO: we need to replace Winborder* with Layer*
inline WindowLayer* Focus() const { return fWMState.Focus; }
inline WindowLayer* Front() const { return fWMState.Front; }
inline WindowLayer* Active() const { return fWMState.Focus; }
bool SetActive(WindowLayer* newActive, bool activate = true);
// void RevealNewWMState(Workspace::State &oldWMState);
bool SetFocus(WindowLayer* focus);
WindowLayer* Focus() const { return fFocus; }
WindowLayer* Front() const { return fFront; }
WindowLayer* Back() const { return fBack; }
inline void SetWorkspaceCount(int32 wksCount);
inline int32 WorkspaceCount() const { return fWsCount; }
inline Workspace* WorkspaceAt(int32 index) const { return fWorkspace[index]; }
inline Workspace* ActiveWorkspace() const { return fWorkspace[fActiveWksIndex]; }
inline int32 ActiveWorkspaceIndex() const { return fActiveWksIndex; }
bool SetActiveWorkspace(int32 index);
void SetWorkspace(int32 index, Workspace& workspace);
void SetWorkspacesLayer(Layer* layer) { fWorkspacesLayer = layer; }
Layer* WorkspacesLayer() const { return fWorkspacesLayer; }
void ReadWorkspaceData(const char *path);
void SaveWorkspaceData(const char *path);
#if 0
void SetBGColor(const RGBColor &col);
RGBColor BGColor(void) const;
#endif
void SetWorkspacesLayer(Layer* layer) { fWorkspacesLayer = layer; }
Layer* WorkspacesLayer() const { return fWorkspacesLayer; }
void SetBGColor(const RGBColor &col);
RGBColor BGColor(void) const;
void SetDragMessage(BMessage *msg);
BMessage* DragMessage() const;
void SetDragMessage(BMessage *msg);
BMessage* DragMessage(void) const;
void SetMouseEventLayer(Layer* layer);
void SetMouseEventLayer(Layer* layer);
void LayerRemoved(Layer* layer);
void LayerRemoved(Layer* layer);
// Other methods
bool Lock() { return fAllRegionsLock.Lock(); }
void Unlock() { fAllRegionsLock.Unlock(); }
bool IsLocked() { return fAllRegionsLock.IsLocked(); }
// Other methods
bool Lock() { return fAllRegionsLock.Lock(); }
void Unlock() { fAllRegionsLock.Unlock(); }
bool IsLocked() { return fAllRegionsLock.IsLocked(); }
void ActivateWindow(WindowLayer* window);
void SendBehindWindow(WindowLayer* window, WindowLayer* front);
void ChangeWindowLayerFeel(WindowLayer *windowLayer, int32 newFeel);
void SetWindowLayerFeel(WindowLayer *windowLayer, int32 newFeel);
void SetWindowLayerLook(WindowLayer *windowLayer, int32 newLook);
void MarkForRedraw(const BRegion &dirty);
void TriggerRedraw();
void MarkForRedraw(const BRegion &dirty);
void TriggerRedraw();
virtual void Draw(const BRect &r);
void Draw(const BRect &r);
thread_id LockingThread() { return fAllRegionsLock.LockingThread(); }
thread_id LockingThread() { return fAllRegionsLock.LockingThread(); }
private:
friend class Desktop;
void AddWindowLayer(WindowLayer* windowLayer);
void RemoveWindowLayer(WindowLayer* windowLayer);
// these are meant for Desktop class only!
void AddWindowLayer(WindowLayer* windowLayer);
void RemoveWindowLayer(WindowLayer* windowLayer);
void AddSubsetWindowLayer(WindowLayer *windowLayer, WindowLayer *toWindowLayer);
void RemoveSubsetWindowLayer(WindowLayer *windowLayer, WindowLayer *fromWindowLayer);
void MouseEventHandler(BMessage *msg);
void MouseEventHandler(BMessage *msg);
Layer* _ChildAt(BPoint where);
private:
bool _SetFocus(WindowLayer* focus, BRegion& update);
void _SetFront(WindowLayer* front, BRegion& update);
void _UpdateBack();
void _UpdateFront();
void _UpdateFronts();
Desktop* fDesktop;
BMessage* fDragMessage;
Layer* fMouseEventLayer;
void _WindowsChanged(BRegion& region);
void _UpdateWorkspace(Workspace& workspace);
uint32 fSavedEventMask;
uint32 fSavedEventOptions;
Layer* _ChildAt(BPoint where);
BLocker fAllRegionsLock;
Desktop* fDesktop;
BMessage* fDragMessage;
Layer* fMouseEventLayer;
BRegion fDirtyForRedraw;
BLocker fAllRegionsLock;
int32 fActiveWksIndex;
int32 fWsCount;
Workspace** fWorkspace;
Layer* fWorkspacesLayer;
BRegion fDirtyForRedraw;
// TODO: fWMState MUST be associated with a surface. This is the case now
// with RootLayer, but after Axel's refractoring this should go in
// WorkspaceLayer, I think.
Workspace::State fWMState;
int32 fWorkspace;
RGBColor fColor;
Layer* fWorkspacesLayer;
WindowLayer* fFocus;
WindowLayer* fFront;
WindowLayer* fBack;
#if ON_SCREEN_DEBUGGING_INFO
friend class DebugInfoManager;
void AddDebugInfo(const char* string);
BString fDebugInfo;
friend class DebugInfoManager;
void AddDebugInfo(const char* string);
BString fDebugInfo;
#endif
#if DISPLAY_HAIKU_LOGO
UtilityBitmap* fLogoBitmap;
UtilityBitmap* fLogoBitmap;
#endif
};

View File

@ -849,18 +849,12 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
{
STRACE(("ServerApp %s: get current workspace\n", Signature()));
// TODO: Locking this way is not nice
RootLayer *root = fDesktop->RootLayer();
root->Lock();
fLink.StartMessage(SERVER_TRUE);
fLink.Attach<int32>(root->ActiveWorkspaceIndex());
fLink.StartMessage(B_OK);
fLink.Attach<int32>(fDesktop->CurrentWorkspace());
fLink.Flush();
root->Unlock();
break;
}
case AS_ACTIVATE_WORKSPACE:
{
STRACE(("ServerApp %s: activate workspace\n", Signature()));
@ -868,15 +862,11 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// TODO: See above
int32 index;
link.Read<int32>(&index);
RootLayer *root = fDesktop->RootLayer();
root->Lock();
root->SetActiveWorkspace(index);
root->Unlock();
// no reply
fDesktop->SetWorkspace(index);
break;
}
case AS_SHOW_CURSOR:
{
STRACE(("ServerApp %s: Show Cursor\n", Signature()));
@ -2188,31 +2178,22 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
{
STRACE(("ServerApp %s: get desktop color\n", Signature()));
uint32 workspaceIndex;
link.Read<uint32>(&workspaceIndex);
uint32 index;
link.Read<uint32>(&index);
// ToDo: locking is probably wrong - why the hell is there no (safe)
// way to get to the workspace object directly?
RootLayer *root = fDesktop->RootLayer();
root->Lock();
Workspace *workspace;
fLink.StartMessage(B_OK);
fDesktop->Lock();
// we're nice to our children (and also take the default case
// into account which asks for the current workspace)
if (workspaceIndex > (uint32)root->WorkspaceCount())
workspace = root->ActiveWorkspace();
else
workspace = root->WorkspaceAt(workspaceIndex);
if (index >= (uint32)kMaxWorkspaces)
index = fDesktop->CurrentWorkspace();
if (workspace != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<rgb_color>(workspace->BGColor().GetColor32());
} else
fLink.StartMessage(B_ERROR);
Workspace& workspace = fDesktop->WorkspaceAt(index);
fLink.Attach<rgb_color>(workspace.Color().GetColor32());
fDesktop->Unlock();
fLink.Flush();
root->Unlock();
break;
}

View File

@ -14,7 +14,6 @@
#include "MessageLooper.h"
#include "SubWindowList.h"
#include "BGet++.h"
#include <String.h>
@ -78,9 +77,6 @@ class ServerApp : public MessageLooper {
BPrivate::BTokenSpace& ViewTokens() { return fViewTokens; }
// ToDo: public?
SubWindowList fAppSubWindowList;
private:
virtual void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
virtual void _MessageLooper();

View File

@ -294,13 +294,11 @@ ServerWindow::Show()
return;
RootLayer* rootLayer = fWindowLayer->GetRootLayer();
if (rootLayer && rootLayer->Lock()) {
if (rootLayer)
rootLayer->ShowWindowLayer(fWindowLayer);
rootLayer->Unlock();
}
if (fDirectWindowData != NULL)
HandleDirectConnection(B_DIRECT_START|B_BUFFER_RESET);
HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESET);
}
@ -316,12 +314,10 @@ ServerWindow::Hide()
if (fDirectWindowData != NULL)
HandleDirectConnection(B_DIRECT_STOP);
RootLayer* rootLayer = fWindowLayer->GetRootLayer();
if (rootLayer && rootLayer->Lock()) {
if (rootLayer)
rootLayer->HideWindowLayer(fWindowLayer);
rootLayer->Unlock();
}
}
@ -404,23 +400,6 @@ ServerWindow::NotifyZoom()
SendMessageToClient(&msg);
}
/*!
\brief Notifies window of a change in screen resolution
\param frame Size of the new resolution
\param color_space Color space of the new screen mode
*/
void
ServerWindow::NotifyScreenModeChanged(const BRect frame, const color_space colorSpace)
{
STRACE(("ServerWindow %s: ScreenModeChanged\n", fTitle));
BMessage msg(B_SCREEN_CHANGED);
msg.AddRect("frame", frame);
msg.AddInt32("mode", (int32)colorSpace);
SendMessageToClient(&msg);
}
void
ServerWindow::GetInfo(window_info& info)
@ -696,7 +675,8 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
if (rootLayer) {
rootLayer->LayerRemoved(fCurrentLayer);
rootLayer->TriggerRedraw();
if (!fCurrentLayer->IsHidden())
rootLayer->TriggerRedraw();
}
if (fCurrentLayer->EventMask() != 0) {
@ -992,7 +972,7 @@ if (rootLayer)
rootLayer->Lock();
fCurrentLayer->SetViewColor(RGBColor(c));
if (rootLayer) {
if (rootLayer && !fCurrentLayer->IsHidden()) {
rootLayer->MarkForRedraw(fCurrentLayer->VisibleRegion());
rootLayer->TriggerRedraw();
}
@ -1177,7 +1157,7 @@ if (rootLayer)
link.Read<BRect>(&invalRect);
if (rootLayer) {
if (rootLayer && !fCurrentLayer->IsHidden()) {
BRect converted(invalRect.LeftTop(), invalRect.RightBottom());
fCurrentLayer->ConvertToScreen(&converted);
@ -1206,13 +1186,12 @@ if (rootLayer)
invalidReg.Include(rect);
}
if (rootLayer) {
if (rootLayer && !fCurrentLayer->IsHidden()) {
fCurrentLayer->ConvertToScreen(&invalidReg);
rootLayer->MarkForRedraw(invalidReg);
rootLayer->TriggerRedraw();
}
break;
}
case AS_BEGIN_UPDATE:
@ -1239,41 +1218,6 @@ if (rootLayer)
STRACE(("ServerWindow %s: Message Delete_Layer_Root unimplemented\n", Title()));
break;
}
case AS_SHOW_WINDOW:
{
STRACE(("ServerWindow %s: Message AS_SHOW_WINDOW\n", Title()));
Show();
break;
}
case AS_HIDE_WINDOW:
{
STRACE(("ServerWindow %s: Message AS_HIDE_WINDOW\n", Title()));
Hide();
break;
}
case AS_SEND_BEHIND:
{
STRACE(("ServerWindow %s: Message Send_Behind unimplemented\n", Title()));
int32 token;
team_id teamID;
status_t status = B_NAME_NOT_FOUND;
link.Read<int32>(&token);
link.Read<team_id>(&teamID);
WindowLayer *behindOf;
if ((behindOf = fDesktop->FindWindowLayerByClientToken(token, teamID)) != NULL) {
fWindowLayer->GetRootLayer()->Lock();
// TODO: move to back ATM. Fix this later!
fWindowLayer->GetRootLayer()->SetActive(fWindowLayer, false);
fWindowLayer->GetRootLayer()->Unlock();
status = B_OK;
}
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_BEGIN_TRANSACTION:
{
STRACE(("ServerWindow %s: Message AS_BEGIN_TRANSACTION unimplemented\n",
@ -1333,16 +1277,14 @@ if (rootLayer)
link.Read<int32>(&mainToken);
link.Read(&teamID, sizeof(team_id));
windowLayer = fDesktop->FindWindowLayerByClientToken(mainToken, teamID);
windowLayer = NULL; //fDesktop->FindWindowLayerByClientToken(mainToken, teamID);
if (windowLayer) {
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
fLink.Flush();
fWindowLayer->GetRootLayer()->Lock();
fDesktop->AddWindowLayerToSubset(fWindowLayer, windowLayer);
fWindowLayer->GetRootLayer()->Unlock();
//fDesktop->AddWindowLayerToSubset(fWindowLayer, windowLayer);
} else {
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(B_ERROR);
fLink.Flush();
}
break;
@ -1357,16 +1299,14 @@ if (rootLayer)
link.Read<int32>(&mainToken);
link.Read(&teamID, sizeof(team_id));
windowLayer = fDesktop->FindWindowLayerByClientToken(mainToken, teamID);
windowLayer = NULL; //fDesktop->FindWindowLayerByClientToken(mainToken, teamID);
if (windowLayer) {
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
fLink.Flush();
fWindowLayer->GetRootLayer()->Lock();
fDesktop->RemoveWindowLayerFromSubset(fWindowLayer, windowLayer);
fWindowLayer->GetRootLayer()->Unlock();
//fDesktop->RemoveWindowLayerFromSubset(fWindowLayer, windowLayer);
} else {
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(B_ERROR);
fLink.Flush();
}
break;
@ -1420,10 +1360,7 @@ if (rootLayer)
uint32 newWorkspaces;
link.Read<uint32>(&newWorkspaces);
fWindowLayer->GetRootLayer()->Lock();
fWindowLayer->GetRootLayer()->SetWindowLayerWorskpaces(fWindowLayer,
fWindowLayer->Workspaces(), newWorkspaces);
fWindowLayer->GetRootLayer()->Unlock();
fDesktop->SetWindowWorkspaces(fWindowLayer, newWorkspaces);
break;
}
case AS_WINDOW_RESIZE:
@ -1485,19 +1422,6 @@ if (rootLayer)
fLink.Flush();
break;
}
case AS_ACTIVATE_WINDOW:
{
DTRACE(("ServerWindow %s: Message AS_ACTIVATE_WINDOW: Layer: %s\n", Title(), fCurrentLayer->Name()));
bool activate = true;
link.Read<bool>(&activate);
if (rootLayer && rootLayer->Lock()) {
rootLayer->SetActive(fWindowLayer, activate);
rootLayer->Unlock();
}
break;
}
// Some BView drawing messages, but which don't need clipping
case AS_LAYER_SET_HIGH_COLOR:
{
@ -2129,6 +2053,52 @@ ServerWindow::_MessageLooper()
CRITICAL("ServerWindow: a window must be hidden before it's deleted\n");
break;
// TODO: these are here temporarily, as they don't lock the root layer
case AS_SHOW_WINDOW:
STRACE(("ServerWindow %s: Message AS_SHOW_WINDOW\n", Title()));
Show();
break;
case AS_HIDE_WINDOW:
STRACE(("ServerWindow %s: Message AS_HIDE_WINDOW\n", Title()));
Hide();
break;
case AS_ACTIVATE_WINDOW:
{
DTRACE(("ServerWindow %s: Message AS_ACTIVATE_WINDOW: Layer: %s\n", Title(), fCurrentLayer->Name()));
bool activate = true;
receiver.Read<bool>(&activate);
if (activate)
fDesktop->ActivateWindow(fWindowLayer);
else
fDesktop->SendBehindWindow(fWindowLayer, NULL);
break;
}
case AS_SEND_BEHIND:
{
STRACE(("ServerWindow %s: Message Send_Behind unimplemented\n", Title()));
int32 token;
team_id teamID;
status_t status;
receiver.Read<int32>(&token);
receiver.Read<team_id>(&teamID);
WindowLayer *behindOf;
if ((behindOf = fDesktop->FindWindowLayerByClientToken(token, teamID)) != NULL) {
fDesktop->SendBehindWindow(fWindowLayer, behindOf);
status = B_OK;
} else
status = B_NAME_NOT_FOUND;
fLink.StartMessage(status);
fLink.Flush();
break;
}
case B_QUIT_REQUESTED:
STRACE(("ServerWindow %s received quit request\n", Title()));
NotifyQuitRequested();

View File

@ -14,7 +14,6 @@
#include "MessageLooper.h"
#include "SubWindowList.h"
#include <PortLink.h>
#include <TokenSpace.h>
@ -68,8 +67,6 @@ public:
void NotifyQuitRequested();
void NotifyMinimize(bool minimize);
void NotifyZoom();
void NotifyScreenModeChanged(const BRect frame,
const color_space cspace);
// util methods.
const BMessenger& FocusMessenger() const { return fFocusMessenger; }
@ -103,9 +100,6 @@ public:
void GetInfo(window_info& info);
// ToDo: public??
SubWindowList fSubWindowList;
private:
// methods for retrieving and creating a tree strcture of Layers.
Layer* CreateLayerTree(BPrivate::LinkReceiver &link, Layer **_parent);

View File

@ -17,8 +17,8 @@ class WindowLayer;
class SubWindowList : public BList {
public:
SubWindowList(void);
virtual ~SubWindowList(void);
SubWindowList();
virtual ~SubWindowList();
void AddWindowLayer(WindowLayer *windowLayer);

View File

@ -117,6 +117,7 @@ WindowLayer::WindowLayer(const BRect &frame,
if (window->App()->GetDesktop()->ScreenAt(0)) {
window->App()->GetDesktop()->ScreenAt(0)->GetMode(width, height, colorSpace, frequency);
// TODO: MOVE THIS AWAY!!! RemoveBy contains calls to virtual methods! Also, there is not TopLayer()!
fFrame.OffsetTo(B_ORIGIN);
WindowLayer::ResizeBy(width - frame.Width(), height - frame.Height());
}
}
@ -390,6 +391,8 @@ WindowLayer::GetSizeLimits(float* minWidth, float* maxWidth,
void
WindowLayer::MouseDown(BMessage *msg, BPoint where)
{
Desktop* desktop = Window()->App()->GetDesktop();
// default action is to drag the WindowLayer
Layer *target = LayerAt(where);
if (target == this) {
@ -449,19 +452,19 @@ WindowLayer::MouseDown(BMessage *msg, BPoint where)
// based on what the Decorator returned, properly place this window.
if (action == DEC_MOVETOBACK) {
GetRootLayer()->SetActive(this, false);
desktop->SendBehindWindow(this, NULL);
} else {
GetRootLayer()->SetMouseEventLayer(this);
GetRootLayer()->SetActive(this);
desktop->ActivateWindow(this);
}
} else if (target != NULL) {
// clicking a simple Layer.
if (GetRootLayer()->ActiveWorkspace()->Focus() != this) {
DesktopSettings desktopSettings(GetRootLayer()->GetDesktop());
if (GetRootLayer()->Focus() != this) {
DesktopSettings desktopSettings(desktop);
// not in FFM mode?
if (desktopSettings.MouseMode() == B_NORMAL_MOUSE)
GetRootLayer()->SetActive(this);
desktop->ActivateWindow(this);
if ((WindowFlags() & B_WILL_ACCEPT_FIRST_CLICK) == 0)
return;
@ -554,17 +557,11 @@ WindowLayer::MouseMoved(BMessage *msg, BPoint where)
fLastMousePosition = where;
// change focus in FFM mode
DesktopSettings desktopSettings(GetRootLayer()->GetDesktop());
// TODO: Focus should be a RootLayer option/feature, NOT a Workspace one!!!
WindowLayer* exFocus = GetRootLayer()->Focus();
if (desktopSettings.MouseMode() != B_NORMAL_MOUSE && exFocus != this) {
GetRootLayer()->ActiveWorkspace()->AttemptToSetFocus(this);
// Workspace::SetFocus() *attempts* to set a new focus WindowLayer, it may not succeed
// if (exFocus != Focus()) {
// TODO: invalidate border area and send message to client for the widgets to light up
// What message? Is there a message on Focus change?
// }
}
Desktop* desktop = Window()->App()->GetDesktop();
DesktopSettings desktopSettings(desktop);
if (desktopSettings.MouseMode() != B_NORMAL_MOUSE && GetRootLayer()->Focus() != this)
GetRootLayer()->SetFocus(this);
Layer* target = LayerAt(where);
if (target != NULL && target != this) {
@ -668,6 +665,16 @@ WindowLayer::UpdateScreen()
}
bool
WindowLayer::SupportsFront()
{
if (fFeel == kDesktopWindowFeel)
return false;
return true;
}
void
WindowLayer::QuietlySetFeel(int32 feel)
{

View File

@ -107,6 +107,10 @@ class WindowLayer : public Layer {
inline int32 Level() const { return fLevel; }
inline uint32 WindowFlags() const { return fWindowFlags; }
inline uint32 Workspaces() const { return fWorkspaces; }
void SetWorkspaces(uint32 workspaces)
{ fWorkspaces = workspaces; }
bool SupportsFront();
// 0.0 -> left .... 1.0 -> right
void SetTabLocation(float location);

File diff suppressed because it is too large Load Diff

View File

@ -1,166 +1,67 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2005, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Workspace.h
// Author: Adi Oanca <adioanca@cotty.iren.com>
// Description: Tracks workspaces
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Notes: IMPORTANT WARNING
// This object does not use any locking mechanism. It is designed
// to be used only by RootLayer class. DO NOT USE from another class!
//------------------------------------------------------------------------------
#ifndef _WORKSPACE_H_
#define _WORKSPACE_H_
/*
* Copyright 2005, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef WORKSPACE_H
#define WORKSPACE_H
#include <SupportDefs.h>
#include <Locker.h>
#include <Accelerant.h>
#include "RGBColor.h"
#include <ObjectList.h>
#include <String.h>
class RootLayer;
class WindowLayer;
struct ListData
{
bool isFree;
WindowLayer *layerPtr;
ListData *upperItem;
ListData *lowerItem;
struct display_info {
BString identifier;
BPoint origin;
display_mode mode;
};
class Workspace {
public:
class State {
public:
State() : Front(NULL), Focus(NULL), WindowList(50) { }
Workspace();
~Workspace();
void PrintToStream();
void SetWindows(const BObjectList<WindowLayer>& windows);
bool AddWindow(WindowLayer* window);
void RemoveWindow(WindowLayer* window);
WindowLayer* Front;
WindowLayer* Focus;
BList WindowList;
};
Workspace( const int32 ID,
const uint32 colorspace,
const RGBColor& BGColor);
~Workspace();
int32 CountWindows() const { return fWindows.CountItems(); }
WindowLayer* WindowAt(int32 index) const { return fWindows.ItemAt(index); }
int32 ID() const { return fID; }
// displays
void AddWindowLayer(WindowLayer *winBorder);
void RemoveWindowLayer(WindowLayer *winBorder);
bool HasWindowLayer(const WindowLayer *winBorder) const;
void SetDisplaysFromDesktop(Desktop* desktop);
WindowLayer* Focus() const;
WindowLayer* Front() const;
WindowLayer* Active() const;
void GetState(Workspace::State *state) const;
bool AttemptToSetFront(WindowLayer *newFront);
int32 AttemptToSetFocus(WindowLayer *newFocus);
bool AttemptToMoveToBack(WindowLayer *newBack);
bool AttemptToActivate(WindowLayer *toActivate);
int32 CountDisplays() const { return fDisplays.CountItems(); }
const display_info* DisplayAt(int32 index) const { return fDisplays.ItemAt(index); }
bool GetWindowLayerList(void **list, int32 *itemCount ) const;
// configuration
bool MoveToBack(WindowLayer *newLast);
bool MoveToFront(WindowLayer *newFront, bool doNotDisturb = false);
const RGBColor& Color() const { return fColor; }
void SetColor(const RGBColor& color);
bool HideWindowLayer(WindowLayer *winBorder);
bool ShowWindowLayer(WindowLayer *winBorder, bool userBusy = false);
void SetSettings(BMessage& settings);
void GetSettings(BMessage& settings);
// resolution related methods.
status_t SetDisplayMode(const display_mode &mode);
status_t GetDisplayMode(display_mode &mode) const;
void SetBGColor(const RGBColor &c);
RGBColor BGColor(void) const;
// settings related methods
void GetSettings(const BMessage &msg);
void GetDefaultSettings(void);
void PutSettings(BMessage *msg, const uint8 &index) const;
static void PutDefaultSettings(BMessage *msg, const uint8 &index);
// debug methods
void PrintToStream(void) const;
void PrintItem(ListData *item) const;
private:
void InsertItem(ListData *item, ListData *before);
void RemoveItem(ListData *item);
ListData* HasItem(const ListData *item, int32 *index = NULL) const;
ListData* HasItem(const WindowLayer *layer, int32 *index = NULL) const;
int32 IndexOf(const ListData *item) const;
bool placeToBack(ListData *newLast);
void placeInFront(ListData *item, const bool userBusy);
int32 _SetFocus(ListData *newFocusItem);
bool removeAndPlaceBefore(const WindowLayer *wb, ListData *beforeItem);
bool removeAndPlaceBefore(ListData *item, ListData *beforeItem);
WindowLayer* searchFirstMainWindow(WindowLayer *wb) const;
WindowLayer* searchANormalWindow(WindowLayer *wb) const;
bool windowHasVisibleModals(const WindowLayer *winBorder) const;
ListData* putModalsInFront(ListData *item);
void putFloatingInFront(ListData *item);
void saveFloatingWindows(ListData *itemNormal);
ListData* findNextFront() const;
class MemoryPool
{
public:
MemoryPool();
~MemoryPool();
ListData* GetCleanMemory(WindowLayer* winborder);
void ReleaseMemory(ListData* mem);
private:
void expandBuffer(int32 start);
ListData *buffer;
int32 count;
};
void _SetDefaults();
int32 fID;
RGBColor fBGColor;
BObjectList<WindowLayer> fWindows;
WindowLayer* fFront;
WindowLayer* fFocus;
// first visible onscreen
ListData *fBottomItem;
BObjectList<display_info> fDisplays;
// the last visible(or covered by other Layers)
ListData *fTopItem;
// the focus WindowLayer - for keyboard events
ListData *fFocusItem;
// pointer for which "big" actions are intended
ListData *fFrontItem;
// settings for each workspace
display_mode fDisplayMode;
MemoryPool fPool;
RGBColor fColor;
};
#endif
#endif /* WORKSPACE_H */

View File

@ -34,7 +34,7 @@ WorkspacesLayer::~WorkspacesLayer()
void
WorkspacesLayer::_GetGrid(int32& columns, int32& rows)
{
int32 count = GetRootLayer()->WorkspaceCount();
int32 count = 4; //GetRootLayer()->WorkspaceCount();
rows = 1;
for (int32 i = 2; i < count; i++) {
@ -140,8 +140,8 @@ WorkspacesLayer::_DrawWorkspace(int32 index)
{
BRect rect = _WorkspaceAt(index);
Workspace* workspace = GetRootLayer()->WorkspaceAt(index);
bool active = workspace == GetRootLayer()->ActiveWorkspace();
Workspace* workspace = NULL;
bool active = index == 0;
if (active) {
// draw active frame
RGBColor black(0, 0, 0);
@ -155,7 +155,7 @@ WorkspacesLayer::_DrawWorkspace(int32 index)
// ToDo: fix me - workspaces must always exist, not only on first visit!
if (workspace != NULL)
color = workspace->BGColor();
color = workspace->Color();
else
color.SetColor(51, 102, 152);
@ -171,9 +171,9 @@ WorkspacesLayer::_DrawWorkspace(int32 index)
if (workspace != NULL) {
WindowLayer* windows[256];
int32 count = 256;
if (!workspace->GetWindowLayerList((void **)&windows, &count))
return;
int32 count = 0;
// if (!workspace->GetWindowLayerList((void **)&windows, &count))
// return;
uint16 width, height;
uint32 colorSpace;
@ -244,7 +244,7 @@ WorkspacesLayer::Draw(const BRect& updateRect)
// draw workspaces
int32 count = GetRootLayer()->WorkspaceCount();
int32 count = 4; //GetRootLayer()->WorkspaceCount();
for (int32 i = 0; i < count; i++) {
_DrawWorkspace(i);