From 2c184b20ed06343ba39e3c84a9542c7069f9011d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 8 Mar 2008 11:42:20 +0000 Subject: [PATCH] * The Desktop is now maintaining a list of workspaces views, and supports more than one of them at the time. * Changed ViewLayer::FindView() to FindViews() that collects all views with the given flag set, not just the first one. * Made ViewLayer::AttachedToWindow() and DetachFromWindow() virtual, WorkspacesLayer now overloads them to register itself with the window and the desktop. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24300 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 64 ++++++++++++++++++++++---- src/servers/app/Desktop.h | 6 ++- src/servers/app/ServerWindow.cpp | 5 +- src/servers/app/ViewLayer.cpp | 25 +++++----- src/servers/app/ViewLayer.h | 8 ++-- src/servers/app/WindowLayer.cpp | 16 ++++++- src/servers/app/WindowLayer.h | 32 +++++++++---- src/servers/app/WorkspacesLayer.cpp | 23 +++++++++- src/servers/app/WorkspacesLayer.h | 71 +++++++++++++++-------------- 9 files changed, 173 insertions(+), 77 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 7d9b7f2bfe..b7e5c62dc5 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -317,7 +317,7 @@ Desktop::Desktop(uid_t userID) fAllWindows(kAllWindowList), fSubsetWindows(kSubsetList), fFocusList(kFocusList), - fWorkspacesLayer(NULL), + fWorkspacesViews(false), fActiveScreen(NULL), fWindowLock("window lock"), @@ -1255,10 +1255,49 @@ Desktop::_WindowHasModal(WindowLayer* window) void Desktop::_WindowChanged(WindowLayer* window) { - if (fWorkspacesLayer == NULL) + for (uint32 i = fWorkspacesViews.CountItems(); i-- > 0;) { + WorkspacesLayer* view = fWorkspacesViews.ItemAt(i); + view->WindowChanged(window); + } +} + + +/*! + You must at least hold a single window lock when calling this method. +*/ +void +Desktop::_WindowRemoved(WindowLayer* window) +{ + for (uint32 i = fWorkspacesViews.CountItems(); i-- > 0;) { + WorkspacesLayer* view = fWorkspacesViews.ItemAt(i); + view->WindowRemoved(window); + } +} + + +void +Desktop::AddWorkspacesView(WorkspacesLayer* view) +{ + if (view->Window() == NULL || view->Window()->IsHidden()) return; - fWorkspacesLayer->WindowChanged(window); + if (!LockAllWindows()) + return; + + if (!fWorkspacesViews.HasItem(view)) + fWorkspacesViews.AddItem(view); + UnlockAllWindows(); +} + + +void +Desktop::RemoveWorkspacesView(WorkspacesLayer* view) +{ + if (!LockAllWindows()) + return; + + fWorkspacesViews.RemoveItem(view); + UnlockAllWindows(); } @@ -1621,10 +1660,9 @@ Desktop::ShowWindow(WindowLayer* window) return; } - if ((window->Flags() & kWorkspacesWindowFlag) != 0) { + if (window->HasWorkspacesViews()) { // find workspaces layer in view hierarchy - fWorkspacesLayer = dynamic_cast( - window->TopLayer()->FindView(kWorkspacesViewFlag)); + window->FindWorkspacesViews(fWorkspacesViews); } UnlockAllWindows(); @@ -1662,11 +1700,17 @@ Desktop::HideWindow(WindowLayer* window) } else _WindowChanged(window); - if (fWorkspacesLayer != NULL) - fWorkspacesLayer->WindowRemoved(window); + _WindowRemoved(window); - if ((window->Flags() & kWorkspacesWindowFlag) != 0) - fWorkspacesLayer = NULL; + if (window->HasWorkspacesViews()) { + // remove workspaces views from this window + BObjectList list(false); + window->FindWorkspacesViews(list); + + while (WorkspacesLayer* view = list.RemoveItemAt(0)) { + fWorkspacesViews.RemoveItem(view); + } + } UnlockAllWindows(); diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 97d6a18804..4903ac64a0 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -181,6 +181,9 @@ class Desktop : public MessageLooper, public ScreenOwner { void RedrawBackground(); void StoreWorkspaceConfiguration(int32 index); + void AddWorkspacesView(WorkspacesLayer* view); + void RemoveWorkspacesView(WorkspacesLayer* view); + void MinimizeApplication(team_id team); void BringApplicationToFront(team_id team); void WindowAction(int32 windowToken, int32 action); @@ -220,6 +223,7 @@ class Desktop : public MessageLooper, public ScreenOwner { bool _WindowHasModal(WindowLayer* window); void _WindowChanged(WindowLayer* window); + void _WindowRemoved(WindowLayer* window); void _GetLooperName(char* name, size_t size); void _PrepareQuit(); @@ -254,7 +258,7 @@ class Desktop : public MessageLooper, public ScreenOwner { WindowList fAllWindows; WindowList fSubsetWindows; WindowList fFocusList; - WorkspacesLayer* fWorkspacesLayer; + BObjectList fWorkspacesViews; Screen* fActiveScreen; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 639c813c03..a09720d248 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -562,10 +562,7 @@ ServerWindow::_CreateLayerTree(BPrivate::LinkReceiver &link, ViewLayer **_parent ViewLayer* newLayer; - if ((fWindowLayer->Flags() & kWorkspacesWindowFlag) != 0 - && (flags & kWorkspacesViewFlag) != 0) { - // TODO: there can currently only be one of these views per desktop! - // TODO: get rid of the kWorkspacesWindowFlag + if ((flags & kWorkspacesViewFlag) != 0) { newLayer = new (nothrow) WorkspacesLayer(frame, scrollingOffset, name, token, resizeMask, flags); } else { diff --git a/src/servers/app/ViewLayer.cpp b/src/servers/app/ViewLayer.cpp index 0bf3f62034..3562c2a4df 100644 --- a/src/servers/app/ViewLayer.cpp +++ b/src/servers/app/ViewLayer.cpp @@ -206,9 +206,9 @@ ViewLayer::AddChild(ViewLayer* layer) printf("ViewLayer::AddChild() - ViewLayer already has a parent\n"); return; } - + layer->fParent = this; - + if (!fLastChild) { // no children yet fFirstChild = layer; @@ -376,19 +376,20 @@ ViewLayer::MarkAt(DrawingEngine* engine, const BPoint& where, int32 level) #endif -ViewLayer* -ViewLayer::FindView(uint32 flags) +void +ViewLayer::FindViews(uint32 flags, BObjectList& list, int32& left) { - if ((Flags() & flags) == flags) - return this; - - for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) { - ViewLayer* layer = child->FindView(flags); - if (layer != NULL) - return layer; + if ((Flags() & flags) == flags) { + list.AddItem(this); + left--; + return; } - return NULL; + for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) { + child->FindViews(flags, list, left); + if (left == 0) + break; + } } diff --git a/src/servers/app/ViewLayer.h b/src/servers/app/ViewLayer.h index 5505ab784e..86536d5db0 100644 --- a/src/servers/app/ViewLayer.h +++ b/src/servers/app/ViewLayer.h @@ -16,6 +16,7 @@ #include "IntRect.h" #include +#include #include #include @@ -76,8 +77,8 @@ class ViewLayer { // clips to each views bounds void ConvertToVisibleInTopView(IntRect* bounds) const; - void AttachedToWindow(WindowLayer* window); - void DetachedFromWindow(); + virtual void AttachedToWindow(WindowLayer* window); + virtual void DetachedFromWindow(); WindowLayer* Window() const { return fWindow; } // tree stuff @@ -100,7 +101,8 @@ class ViewLayer { uint32 CountChildren(bool deep = false) const; void CollectTokensForChildren(BList* tokenMap) const; - ViewLayer* FindView(uint32 flags); + void FindViews(uint32 flags, + BObjectList& list, int32& left); ViewLayer* ViewAt(const BPoint& where); diff --git a/src/servers/app/WindowLayer.cpp b/src/servers/app/WindowLayer.cpp index e69af7adcc..215f0b3614 100644 --- a/src/servers/app/WindowLayer.cpp +++ b/src/servers/app/WindowLayer.cpp @@ -25,6 +25,7 @@ #include "Workspace.h" #include "WorkspacesLayer.h" +#include #include #include @@ -126,7 +127,9 @@ WindowLayer::WindowLayer(const BRect& frame, const char *name, fMinWidth(1), fMaxWidth(32768), fMinHeight(1), - fMaxHeight(32768) + fMaxHeight(32768), + + fWorkspacesViewCount(0) { // make sure our arguments are valid if (!IsValidLook(fLook)) @@ -1525,6 +1528,17 @@ WindowLayer::HasInSubset(const WindowLayer* window) const } +/*! \brief Collects all workspaces views in this window and puts it into \a list +*/ +void +WindowLayer::FindWorkspacesViews(BObjectList& list) const +{ + int32 count = fWorkspacesViewCount; + TopLayer()->FindViews(kWorkspacesViewFlag, (BObjectList&)list, + count); +} + + /*! \brief Returns on which workspaces the window should be visible. A modal or floating window may be visible on a workscreen if one diff --git a/src/servers/app/WindowLayer.h b/src/servers/app/WindowLayer.h index bc232c867b..4d09bdcc9c 100644 --- a/src/servers/app/WindowLayer.h +++ b/src/servers/app/WindowLayer.h @@ -1,11 +1,12 @@ /* - * Copyright (c) 2001-2006, Haiku, Inc. + * Copyright (c) 2001-2008, Haiku, Inc. * Distributed under the terms of the MIT license. * - * Author: DarkWyrm - * Adi Oanca - * Stephan Aßmus - * Axel Dörfler, axeld@pinc-software.de + * Authors: + * DarkWyrm + * Adi Oanca + * Stephan Aßmus + * Axel Dörfler, axeld@pinc-software.de */ #ifndef WINDOW_LAYER_H #define WINDOW_LAYER_H @@ -30,7 +31,7 @@ class Decorator; class Desktop; class DrawingEngine; class EventDispatcher; -class WindowLayer; +class WorkspacesLayer; // TODO: move this into a proper place #define AS_REDRAW 'rdrw' @@ -41,7 +42,7 @@ enum { }; class WindowLayer { - public: +public: WindowLayer(const BRect& frame, const char *name, window_look look, window_feel feel, uint32 flags, @@ -208,6 +209,15 @@ class WindowLayer { bool SameSubset(WindowLayer* window); uint32 SubsetWorkspaces() const; + bool HasWorkspacesViews() const + { return fWorkspacesViewCount != 0; } + void AddWorkspacesView() + { fWorkspacesViewCount++; } + void RemoveWorkspacesView() + { fWorkspacesViewCount--; } + void FindWorkspacesViews( + BObjectList& list) const; + static bool IsValidLook(window_look look); static bool IsValidFeel(window_feel feel); static bool IsModalFeel(window_feel feel); @@ -216,7 +226,7 @@ class WindowLayer { static uint32 ValidWindowFlags(); static uint32 ValidWindowFlags(window_feel feel); - protected: +protected: friend class Desktop; // TODO: for now (list management) @@ -298,7 +308,7 @@ class WindowLayer { // redraw requests from the Desktop will go // into the pending update session. class UpdateSession { - public: + public: UpdateSession(); virtual ~UpdateSession(); @@ -320,7 +330,7 @@ class WindowLayer { inline bool IsRequest() const { return fCause & UPDATE_REQUEST; } - private: + private: BRegion fDirtyRegion; bool fInUse; uint8 fCause; @@ -352,6 +362,8 @@ class WindowLayer { int32 fMaxWidth; int32 fMinHeight; int32 fMaxHeight; + + int32 fWorkspacesViewCount; }; #endif // WINDOW_LAYER_H diff --git a/src/servers/app/WorkspacesLayer.cpp b/src/servers/app/WorkspacesLayer.cpp index 2d82cc00e4..1aca8b263d 100644 --- a/src/servers/app/WorkspacesLayer.cpp +++ b/src/servers/app/WorkspacesLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007, Haiku Inc. + * Copyright 2005-2008, Haiku Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -33,7 +33,26 @@ WorkspacesLayer::WorkspacesLayer(BRect frame, BPoint scrollingOffset, WorkspacesLayer::~WorkspacesLayer() { - // TODO: we actually need to tell the Desktop that we're gone +} + + +void +WorkspacesLayer::AttachedToWindow(WindowLayer* window) +{ + ViewLayer::AttachedToWindow(window); + + window->AddWorkspacesView(); + window->Desktop()->AddWorkspacesView(this); +} + + +void +WorkspacesLayer::DetachedFromWindow() +{ + fWindow->Desktop()->RemoveWorkspacesView(this); + fWindow->RemoveWorkspacesView(); + + ViewLayer::DetachedFromWindow(); } diff --git a/src/servers/app/WorkspacesLayer.h b/src/servers/app/WorkspacesLayer.h index 028ce2c175..be6d2e5908 100644 --- a/src/servers/app/WorkspacesLayer.h +++ b/src/servers/app/WorkspacesLayer.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006, Haiku Inc. + * Copyright 2005-2008, Haiku Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -15,47 +15,50 @@ class WindowLayer; class WorkspacesLayer : public ViewLayer { - public: - WorkspacesLayer(BRect frame, BPoint scrollingOffset, const char* name, - int32 token, uint32 resize, uint32 flags); - virtual ~WorkspacesLayer(); +public: + WorkspacesLayer(BRect frame, BPoint scrollingOffset, + const char* name, int32 token, uint32 resize, + uint32 flags); + virtual ~WorkspacesLayer(); - virtual void Draw(DrawingEngine* drawingEngine, + virtual void AttachedToWindow(WindowLayer* window); + virtual void DetachedFromWindow(); + + virtual void Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, - BRegion* windowContentClipping, - bool deep = false); + BRegion* windowContentClipping, bool deep = false); - virtual void MouseDown(BMessage* message, BPoint where); - virtual void MouseUp(BMessage* message, BPoint where); - virtual void MouseMoved(BMessage* message, BPoint where); + virtual void MouseDown(BMessage* message, BPoint where); + virtual void MouseUp(BMessage* message, BPoint where); + virtual void MouseMoved(BMessage* message, BPoint where); - void WindowChanged(WindowLayer* window); - void WindowRemoved(WindowLayer* window); + void WindowChanged(WindowLayer* window); + void WindowRemoved(WindowLayer* window); - private: - void _GetGrid(int32& columns, int32& rows); - BRect _ScreenFrame(int32 index); - BRect _WorkspaceAt(int32 index); - BRect _WorkspaceAt(BPoint where, int32& index); - BRect _WindowFrame(const BRect& workspaceFrame, - const BRect& screenFrame, const BRect& windowFrame, - BPoint windowPosition); +private: + void _GetGrid(int32& columns, int32& rows); + BRect _ScreenFrame(int32 index); + BRect _WorkspaceAt(int32 index); + BRect _WorkspaceAt(BPoint where, int32& index); + BRect _WindowFrame(const BRect& workspaceFrame, + const BRect& screenFrame, const BRect& windowFrame, + BPoint windowPosition); - void _DrawWindow(DrawingEngine* drawingEngine, const BRect& workspaceFrame, - const BRect& screenFrame, WindowLayer* window, - BPoint windowPosition, BRegion& backgroundRegion, - bool active); - void _DrawWorkspace(DrawingEngine* drawingEngine, BRegion& redraw, - int32 index); + void _DrawWindow(DrawingEngine* drawingEngine, + const BRect& workspaceFrame, const BRect& screenFrame, + WindowLayer* window, BPoint windowPosition, + BRegion& backgroundRegion, bool active); + void _DrawWorkspace(DrawingEngine* drawingEngine, + BRegion& redraw, int32 index); - void _DarkenColor(rgb_color& color) const; - void _Invalidate() const; + void _DarkenColor(rgb_color& color) const; + void _Invalidate() const; - private: - WindowLayer* fSelectedWindow; - int32 fSelectedWorkspace; - bool fHasMoved; - BPoint fLeftTopOffset; +private: + WindowLayer* fSelectedWindow; + int32 fSelectedWorkspace; + bool fHasMoved; + BPoint fLeftTopOffset; }; #endif // WORKSPACES_LAYER_H