Author: czeidler Date: 2010-08-03 06:36:21 +0200 (Tue, 03 Aug 2010) New Revision: 37857 Changeset: http://dev.haiku-os.org/changeset/37857 Modified: haiku/trunk/src/servers/app/DecorManager.cpp haiku/trunk/src/servers/app/DecorManager.h haiku/trunk/src/servers/app/Desktop.cpp haiku/trunk/src/servers/app/Desktop.h haiku/trunk/src/servers/app/DesktopListener.cpp haiku/trunk/src/servers/app/DesktopListener.h haiku/trunk/src/servers/app/Window.cpp haiku/trunk/src/servers/app/Window.h Log: Introduce a new DecorAddOn class which provide the DecorManager with the needed Decorator, WindowBehaviour and DesktopListener. Modified: haiku/trunk/src/servers/app/DecorManager.cpp =================================================================== --- haiku/trunk/src/servers/app/DecorManager.cpp 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/DecorManager.cpp 2010-08-03 04:36:21 UTC (rev 37857) @@ -21,87 +21,55 @@ #include "AppServer.h" #include "DefaultDecorator.h" +#include "DefaultWindowBehaviour.h" #include "Desktop.h" #include "DesktopSettings.h" #include "ServerConfig.h" #include "Window.h" typedef float get_version(void); -typedef Decorator* create_decorator(DesktopSettings& desktopSettings, BRect rect, - window_look look, uint32 flags); +typedef DecorAddOn* create_decor_addon(image_id id, const char* name); // Globals DecorManager gDecorManager; -// This is a class used only by the DecorManager to track all the decorators in memory -class DecorInfo { - public: - DecorInfo(image_id id, const char* name, - create_decorator* allocator = NULL); - ~DecorInfo(); +DecorAddOn::DecorAddOn(image_id id, const char* name) + : + fImageID(id), + fName(name) +{ +} - status_t InitCheck() const; - image_id ID() const { return fID; } - const char* Name() const { return fName.String(); } +DecorAddOn::~DecorAddOn() +{ - Decorator* Instantiate(Desktop* desktop, DrawingEngine* engine, - BRect rect, const char* title, - window_look look, uint32 flags); - - private: - image_id fID; - BString fName; - create_decorator* fAllocator; -}; - - -DecorInfo::DecorInfo(image_id id, const char* name, create_decorator* allocator) - : - fID(id), - fName(name), - fAllocator(allocator) -{ } -DecorInfo::~DecorInfo() +status_t +DecorAddOn::InitCheck() const { - // Do nothing. Normal programming practice would say that one should unload - // the object's associate image_id. However, there is some funkiness with - // the R5 kernel in which addons aren't unloaded when unload_add_on() is - // called -- perhaps it's lazy unloading or something. In any event, it - // causes crashes which are *extremely* hard to track down to this. - - // Considering the usage of DecorInfo and DecorManager, we can live with - // this because the app_server will not the DecorManager is freed only - // when the app_server quits. It's not pretty, but it gets the job done. + return B_OK; } -Decorator * -DecorInfo::Instantiate(Desktop* desktop, DrawingEngine* engine, BRect rect, - const char *title, window_look look, uint32 flags) +Decorator* +DecorAddOn::AllocateDecorator(Desktop* desktop, DrawingEngine* engine, + BRect rect, const char* title, window_look look, uint32 flags) { if (!desktop->LockSingleWindow()) return NULL; DesktopSettings settings(desktop); - Decorator *decorator; - - try { - if (fAllocator != NULL) - decorator = fAllocator(settings, rect, look, flags); - else - decorator = new DefaultDecorator(settings, rect, look, flags); - } catch (...) { - desktop->UnlockSingleWindow(); - return NULL; - } + Decorator* decorator; + decorator = _AllocateDecorator(settings, rect, look, flags); desktop->UnlockSingleWindow(); + if (!decorator) + return NULL; decorator->SetDrawingEngine(engine); decorator->SetTitle(title); @@ -109,17 +77,38 @@ } +WindowBehaviour* +DecorAddOn::AllocateWindowBehaviour(Window* window) +{ + return new (std::nothrow)DefaultWindowBehaviour(window); +} + + +const DesktopListenerList& +DecorAddOn::GetDesktopListeners() +{ + return fDesktopListeners; +} + + +Decorator* +DecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect, + window_look look, uint32 flags) +{ + return new (std::nothrow)DefaultDecorator(settings, rect, look, flags); +} + + // #pragma mark - DecorManager::DecorManager() : - fDecorList(0), + fDefaultDecorAddOn(-1, "Default"), fCurrentDecor(NULL) { // Start with the default decorator - index is always 0 - DecorInfo *defaultDecor = new DecorInfo(-1, "Default", NULL); - fDecorList.AddItem(defaultDecor); + fDecorList.AddItem(&fDefaultDecorAddOn); // Add any on disk RescanDecorators(); @@ -127,7 +116,7 @@ _LoadSettingsFromDisk(); if (!fCurrentDecor) - fCurrentDecor = (DecorInfo*)fDecorList.ItemAt(0L); + fCurrentDecor = fDecorList.ItemAt(0L); } @@ -170,18 +159,25 @@ // to do so. If we *did* do anything with decorator versions, the // assignment would go here. - create_decorator* createFunc; + create_decor_addon* createFunc; // Get the instantiation function - status_t status = get_image_symbol(image, "instantiate_decorator", + status_t status = get_image_symbol(image, "instantiate_decor_addon", B_SYMBOL_TYPE_TEXT, (void**)&createFunc); if (status != B_OK) { unload_add_on(image); continue; } + DecorAddOn* addon = createFunc(image, ref.name); + // TODO: unload images until they are actually used! - fDecorList.AddItem(new DecorInfo(image, ref.name, createFunc)); + if (!addon || addon->InitCheck() != B_OK + || !fDecorList.AddItem(addon)) { + unload_add_on(image); + delete addon; + continue; + } } } @@ -199,11 +195,31 @@ return NULL; } - return fCurrentDecor->Instantiate(desktop, engine, rect, title, + return fCurrentDecor->AllocateDecorator(desktop, engine, rect, title, look, flags); } +WindowBehaviour* +DecorManager::AllocateWindowBehaviour(Window* window) +{ + if (!fCurrentDecor) { + // We should *never* be here. If we do, it's a bug. + debugger("DecorManager::AllocateDecorator has a NULL decorator"); + return NULL; + } + + return fCurrentDecor->AllocateWindowBehaviour(window); +} + + +const DesktopListenerList& +DecorManager::GetDesktopListeners() +{ + return fCurrentDecor->GetDesktopListeners(); +} + + int32 DecorManager::CountDecorators() const { @@ -221,11 +237,11 @@ bool DecorManager::SetDecorator(int32 index, Desktop* desktop) { - DecorInfo* newDecInfo = (DecorInfo*)fDecorList.ItemAt(index); + DecorAddOn* newDecor = fDecorList.ItemAt(index); - if (newDecInfo) { - fCurrentDecor = newDecInfo; - desktop->ReloadAllDecorators(); + if (newDecor) { + fCurrentDecor = newDecor; + desktop->ReloadDecor(); _SaveSettingsToDisk(); return true; } @@ -248,9 +264,9 @@ return false; } - DecorInfo *newDecInfo = _FindDecor(string.String()); - if (newDecInfo) { - fCurrentDecor = newDecInfo; + DecorAddOn *newDecor = _FindDecor(string); + if (newDecor) { + fCurrentDecor = newDecor; return true; } @@ -258,40 +274,43 @@ } -const char * +BString DecorManager::GetDecoratorName(int32 index) { - DecorInfo *info = fDecorList.ItemAt(index); - if (info) - return info->Name(); + DecorAddOn *decor = fDecorList.ItemAt(index); + if (decor) + return decor->Name(); - return NULL; + return BString(""); } void DecorManager::_EmptyList() { - for (int32 i = 0; i < fDecorList.CountItems(); i++) { - delete fDecorList.ItemAt(i);; + for (int32 i = 1; i < fDecorList.CountItems(); i++) { + unload_add_on(fDecorList.ItemAt(i)->ImageID()); + delete fDecorList.ItemAt(i); } fDecorList.MakeEmpty(); - fCurrentDecor = NULL; + fDecorList.AddItem(&fDefaultDecorAddOn); + + fCurrentDecor = &fDefaultDecorAddOn; } -DecorInfo* -DecorManager::_FindDecor(const char *name) +DecorAddOn* +DecorManager::_FindDecor(BString name) { if (!name) return NULL; for (int32 i = 0; i < fDecorList.CountItems(); i++) { - DecorInfo* info = fDecorList.ItemAt(i); + DecorAddOn* decor = fDecorList.ItemAt(i); - if (strcmp(name, info->Name()) == 0) - return info; + if (decor->Name() == name) + return decor; } return NULL; @@ -321,7 +340,7 @@ if (settings.Unflatten(&file) == B_OK) { BString itemtext; if (settings.FindString("decorator", &itemtext) == B_OK) { - DecorInfo* decor = _FindDecor(itemtext.String()); + DecorAddOn* decor = _FindDecor(itemtext); if (decor) { fCurrentDecor = decor; return true; Modified: haiku/trunk/src/servers/app/DecorManager.h =================================================================== --- haiku/trunk/src/servers/app/DecorManager.h 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/DecorManager.h 2010-08-03 04:36:21 UTC (rev 37857) @@ -20,9 +20,48 @@ class DecorInfo; class Desktop; +class DesktopListener; class DrawingEngine; +class Window; +class WindowBehaviour; +typedef BObjectList<DesktopListener> DesktopListenerList; + + +class DecorAddOn +{ +public: + DecorAddOn(image_id id, const char* name); + virtual ~DecorAddOn(); + + virtual status_t InitCheck() const; + + image_id ImageID() const { return fImageID; } + BString Name() const { return fName; } + + Decorator* AllocateDecorator(Desktop* desktop, + DrawingEngine* engine, BRect rect, + const char* title, window_look look, + uint32 flags); + + virtual float Version() { return 1.0; } + virtual WindowBehaviour* AllocateWindowBehaviour(Window* window); + + virtual const DesktopListenerList& GetDesktopListeners(); + +protected: + virtual Decorator* _AllocateDecorator(DesktopSettings& settings, + BRect rect, window_look look, uint32 flags); + + DesktopListenerList fDesktopListeners; + +private: + image_id fImageID; + BString fName; +}; + + class DecorManager { public: @@ -36,13 +75,15 @@ BRect rect, const char* title, window_look look, uint32 flags); + WindowBehaviour* AllocateWindowBehaviour(Window* window); + const DesktopListenerList& GetDesktopListeners(); int32 CountDecorators() const; int32 GetDecorator() const; bool SetDecorator(int32 index, Desktop* desktop); bool SetR5Decorator(int32 value); - const char* GetDecoratorName(int32 index); + BString GetDecoratorName(int32 index); // TODO: Implement this method once the rest of the necessary infrastructure // is in place @@ -50,13 +91,14 @@ private: void _EmptyList(); - DecorInfo* _FindDecor(const char *name); + DecorAddOn* _FindDecor(BString name); bool _LoadSettingsFromDisk(); bool _SaveSettingsToDisk(); - BObjectList<DecorInfo> fDecorList; - DecorInfo* fCurrentDecor; + BObjectList<DecorAddOn> fDecorList; + DecorAddOn fDefaultDecorAddOn; + DecorAddOn* fCurrentDecor; }; extern DecorManager gDecorManager; Modified: haiku/trunk/src/servers/app/Desktop.cpp =================================================================== --- haiku/trunk/src/servers/app/Desktop.cpp 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/Desktop.cpp 2010-08-03 04:36:21 UTC (rev 37857) @@ -36,6 +36,7 @@ #include <WindowInfo.h> #include "AppServer.h" +#include "DecorManager.h" #include "DesktopSettingsPrivate.h" #include "DrawingEngine.h" #include "HWInterface.h" @@ -1901,17 +1902,29 @@ void -Desktop::ReloadAllDecorators() +Desktop::ReloadDecor() { AutoWriteLocker _(fWindowLock); + // TODO it is assumed all listeners are registered by one decor + // unregister old listeners + const DesktopListenerDLList& currentListeners = GetDesktopListenerList(); + for (DesktopListener* listener = currentListeners.First(); + listener != NULL; listener = currentListeners.GetNext(listener)) + UnregisterListener(listener); + // register new listeners + const DesktopListenerList& newListeners + = gDecorManager.GetDesktopListeners(); + for (int i = 0; i < newListeners.CountItems(); i++) + RegisterListener(newListeners.ItemAt(i)); + for (int32 i = 0; i < kMaxWorkspaces; i++) { for (Window* window = _Windows(i).LastWindow(); window; window = window->PreviousWindow(i)) { BRegion oldBorder; window->GetBorderRegion(&oldBorder); - window->ReloadDecorator(); + window->ReloadDecor(); BRegion border; window->GetBorderRegion(&border); Modified: haiku/trunk/src/servers/app/Desktop.h =================================================================== --- haiku/trunk/src/servers/app/Desktop.h 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/Desktop.h 2010-08-03 04:36:21 UTC (rev 37857) @@ -14,6 +14,14 @@ #define DESKTOP_H +#include <Autolock.h> +#include <InterfaceDefs.h> +#include <List.h> +#include <Menu.h> +#include <ObjectList.h> +#include <Region.h> +#include <Window.h> + #include "CursorManager.h" #include "DesktopListener.h" #include "DesktopSettings.h" @@ -27,16 +35,7 @@ #include "Workspace.h" #include "WorkspacePrivate.h" -#include <ObjectList.h> -#include <Autolock.h> -#include <InterfaceDefs.h> -#include <List.h> -#include <Menu.h> -#include <Region.h> -#include <Window.h> - - #define USE_MULTI_LOCKER 1 #if USE_MULTI_LOCKER @@ -233,7 +232,7 @@ void Redraw(); void RedrawBackground(); - void ReloadAllDecorators(); + void ReloadDecor(); BRegion& BackgroundRegion() { return fBackgroundRegion; } Modified: haiku/trunk/src/servers/app/DesktopListener.cpp =================================================================== --- haiku/trunk/src/servers/app/DesktopListener.cpp 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/DesktopListener.cpp 2010-08-03 04:36:21 UTC (rev 37857) @@ -37,6 +37,13 @@ } +const DesktopListenerDLList& +DesktopObservable::GetDesktopListenerList() +{ + return fDesktopListenerList; +} + + #define FOR_ALL_DESKTOP_LISTENER \ for (DesktopListener* listener = fDesktopListenerList.First(); \ listener != NULL; listener = fDesktopListenerList.GetNext(listener)) Modified: haiku/trunk/src/servers/app/DesktopListener.h =================================================================== --- haiku/trunk/src/servers/app/DesktopListener.h 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/DesktopListener.h 2010-08-03 04:36:21 UTC (rev 37857) @@ -55,7 +55,7 @@ }; -typedef DoublyLinkedList<DesktopListener> DesktopListenerList; +typedef DoublyLinkedList<DesktopListener> DesktopListenerDLList; class DesktopObservable @@ -65,6 +65,7 @@ void RegisterListener(DesktopListener* listener); void UnregisterListener(DesktopListener* listener); + const DesktopListenerDLList& GetDesktopListenerList(); void InvokeAddWindow(Window* window); void InvokeRemoveWindow(Window* window); @@ -104,10 +105,10 @@ bool& fInvoking; }; - DesktopListenerList fDesktopListenerList; + DesktopListenerDLList fDesktopListenerList; // prevent recursive invokes - bool fWeAreInvoking; + bool fWeAreInvoking; }; #endif Modified: haiku/trunk/src/servers/app/Window.cpp =================================================================== --- haiku/trunk/src/servers/app/Window.cpp 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/Window.cpp 2010-08-03 04:36:21 UTC (rev 37857) @@ -10,20 +10,18 @@ * Brecht Machiels <brecht@xxxxxxxxxxx> * Clemens Zeidler <haiku@xxxxxxxxxxxxxxxxxx> */ - - #include "Window.h" #include "Decorator.h" #include "DecorManager.h" #include "Desktop.h" -#include "DefaultWindowBehaviour.h" #include "DrawingEngine.h" #include "HWInterface.h" #include "MessagePrivate.h" #include "PortLink.h" #include "ServerApp.h" #include "ServerWindow.h" +#include "WindowBehaviour.h" #include "Workspace.h" #include "WorkspacesView.h" @@ -135,7 +133,7 @@ &fMaxWidth, &fMaxHeight); } } - fWindowBehaviour = new (std::nothrow)DefaultWindowBehaviour(this); + fWindowBehaviour = gDecorManager.AllocateWindowBehaviour(this); // do we need to change our size to let the decorator fit? // _ResizeBy() will adapt the frame for validity before resizing @@ -542,17 +540,35 @@ } -void -Window::ReloadDecorator() +bool +Window::ReloadDecor() { + ::Decorator* decorator = NULL; + WindowBehaviour* windowBehaviour = NULL; + if (fLook != B_NO_BORDER_WINDOW_LOOK) { - delete fDecorator; // we need a new decorator - fDecorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine, + decorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine, Frame(), Title(), fLook, fFlags); + if (!decorator) + return false; if (IsFocus()) - fDecorator->SetFocus(true); + decorator->SetFocus(true); } + + windowBehaviour = gDecorManager.AllocateWindowBehaviour(this); + if (!windowBehaviour) { + delete decorator; + return false; + } + + delete fDecorator; + fDecorator = decorator; + + delete fWindowBehaviour; + fWindowBehaviour = windowBehaviour; + + return true; } Modified: haiku/trunk/src/servers/app/Window.h =================================================================== --- haiku/trunk/src/servers/app/Window.h 2010-08-03 04:30:07 UTC (rev 37856) +++ haiku/trunk/src/servers/app/Window.h 2010-08-03 04:36:21 UTC (rev 37857) @@ -10,12 +10,10 @@ * Brecht Machiels <brecht@xxxxxxxxxxx> * Clemens Zeidler <haiku@xxxxxxxxxxxxxxxxxx> */ - #ifndef WINDOW_H #define WINDOW_H -#include "Decorator.h" #include "RegionPool.h" #include "ServerWindow.h" #include "View.h" @@ -71,7 +69,7 @@ ::EventTarget& EventTarget() const { return fWindow->EventTarget(); } - void ReloadDecorator(); + bool ReloadDecor(); void SetScreen(const ::Screen* screen); const ::Screen* Screen() const;