Introduce a new DecorAddOn class which provide the DecorManager with the needed Decorator, WindowBehaviour and DesktopListener.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37857 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Clemens Zeidler
2010-08-03 04:36:21 +00:00
parent bd06a41c3a
commit b6ba2290fc
8 changed files with 208 additions and 113 deletions
+100 -81
View File
@@ -21,87 +21,55 @@
#include "AppServer.h" #include "AppServer.h"
#include "DefaultDecorator.h" #include "DefaultDecorator.h"
#include "DefaultWindowBehaviour.h"
#include "Desktop.h" #include "Desktop.h"
#include "DesktopSettings.h" #include "DesktopSettings.h"
#include "ServerConfig.h" #include "ServerConfig.h"
#include "Window.h" #include "Window.h"
typedef float get_version(void); typedef float get_version(void);
typedef Decorator* create_decorator(DesktopSettings& desktopSettings, BRect rect, typedef DecorAddOn* create_decor_addon(image_id id, const char* name);
window_look look, uint32 flags);
// Globals // Globals
DecorManager gDecorManager; DecorManager gDecorManager;
// This is a class used only by the DecorManager to track all the decorators in memory DecorAddOn::DecorAddOn(image_id id, const char* name)
class DecorInfo {
public:
DecorInfo(image_id id, const char* name,
create_decorator* allocator = NULL);
~DecorInfo();
status_t InitCheck() const;
image_id ID() const { return fID; }
const char* Name() const { return fName.String(); }
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), fImageID(id),
fName(name), fName(name)
fAllocator(allocator)
{ {
} }
DecorInfo::~DecorInfo() DecorAddOn::~DecorAddOn()
{ {
// 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.
} }
Decorator * status_t
DecorInfo::Instantiate(Desktop* desktop, DrawingEngine* engine, BRect rect, DecorAddOn::InitCheck() const
const char *title, window_look look, uint32 flags) {
return B_OK;
}
Decorator*
DecorAddOn::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
BRect rect, const char* title, window_look look, uint32 flags)
{ {
if (!desktop->LockSingleWindow()) if (!desktop->LockSingleWindow())
return NULL; return NULL;
DesktopSettings settings(desktop); DesktopSettings settings(desktop);
Decorator *decorator; Decorator* decorator;
decorator = _AllocateDecorator(settings, rect, look, flags);
try {
if (fAllocator != NULL)
decorator = fAllocator(settings, rect, look, flags);
else
decorator = new DefaultDecorator(settings, rect, look, flags);
} catch (...) {
desktop->UnlockSingleWindow(); desktop->UnlockSingleWindow();
if (!decorator)
return NULL; return NULL;
}
desktop->UnlockSingleWindow();
decorator->SetDrawingEngine(engine); decorator->SetDrawingEngine(engine);
decorator->SetTitle(title); decorator->SetTitle(title);
@@ -109,17 +77,38 @@ DecorInfo::Instantiate(Desktop* desktop, DrawingEngine* engine, BRect rect,
} }
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 - // #pragma mark -
DecorManager::DecorManager() DecorManager::DecorManager()
: :
fDecorList(0), fDefaultDecorAddOn(-1, "Default"),
fCurrentDecor(NULL) fCurrentDecor(NULL)
{ {
// Start with the default decorator - index is always 0 // Start with the default decorator - index is always 0
DecorInfo *defaultDecor = new DecorInfo(-1, "Default", NULL); fDecorList.AddItem(&fDefaultDecorAddOn);
fDecorList.AddItem(defaultDecor);
// Add any on disk // Add any on disk
RescanDecorators(); RescanDecorators();
@@ -127,7 +116,7 @@ DecorManager::DecorManager()
_LoadSettingsFromDisk(); _LoadSettingsFromDisk();
if (!fCurrentDecor) if (!fCurrentDecor)
fCurrentDecor = (DecorInfo*)fDecorList.ItemAt(0L); fCurrentDecor = fDecorList.ItemAt(0L);
} }
@@ -170,18 +159,25 @@ DecorManager::RescanDecorators()
// to do so. If we *did* do anything with decorator versions, the // to do so. If we *did* do anything with decorator versions, the
// assignment would go here. // assignment would go here.
create_decorator* createFunc; create_decor_addon* createFunc;
// Get the instantiation function // 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); B_SYMBOL_TYPE_TEXT, (void**)&createFunc);
if (status != B_OK) { if (status != B_OK) {
unload_add_on(image); unload_add_on(image);
continue; continue;
} }
DecorAddOn* addon = createFunc(image, ref.name);
// TODO: unload images until they are actually used! // 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 @@ DecorManager::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
return NULL; return NULL;
} }
return fCurrentDecor->Instantiate(desktop, engine, rect, title, return fCurrentDecor->AllocateDecorator(desktop, engine, rect, title,
look, flags); 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 int32
DecorManager::CountDecorators() const DecorManager::CountDecorators() const
{ {
@@ -221,11 +237,11 @@ DecorManager::GetDecorator() const
bool bool
DecorManager::SetDecorator(int32 index, Desktop* desktop) DecorManager::SetDecorator(int32 index, Desktop* desktop)
{ {
DecorInfo* newDecInfo = (DecorInfo*)fDecorList.ItemAt(index); DecorAddOn* newDecor = fDecorList.ItemAt(index);
if (newDecInfo) { if (newDecor) {
fCurrentDecor = newDecInfo; fCurrentDecor = newDecor;
desktop->ReloadAllDecorators(); desktop->ReloadDecor();
_SaveSettingsToDisk(); _SaveSettingsToDisk();
return true; return true;
} }
@@ -248,9 +264,9 @@ DecorManager::SetR5Decorator(int32 value)
return false; return false;
} }
DecorInfo *newDecInfo = _FindDecor(string.String()); DecorAddOn *newDecor = _FindDecor(string);
if (newDecInfo) { if (newDecor) {
fCurrentDecor = newDecInfo; fCurrentDecor = newDecor;
return true; return true;
} }
@@ -258,40 +274,43 @@ DecorManager::SetR5Decorator(int32 value)
} }
const char * BString
DecorManager::GetDecoratorName(int32 index) DecorManager::GetDecoratorName(int32 index)
{ {
DecorInfo *info = fDecorList.ItemAt(index); DecorAddOn *decor = fDecorList.ItemAt(index);
if (info) if (decor)
return info->Name(); return decor->Name();
return NULL; return BString("");
} }
void void
DecorManager::_EmptyList() DecorManager::_EmptyList()
{ {
for (int32 i = 0; i < fDecorList.CountItems(); i++) { for (int32 i = 1; i < fDecorList.CountItems(); i++) {
delete fDecorList.ItemAt(i);; unload_add_on(fDecorList.ItemAt(i)->ImageID());
delete fDecorList.ItemAt(i);
} }
fDecorList.MakeEmpty(); fDecorList.MakeEmpty();
fCurrentDecor = NULL; fDecorList.AddItem(&fDefaultDecorAddOn);
fCurrentDecor = &fDefaultDecorAddOn;
} }
DecorInfo* DecorAddOn*
DecorManager::_FindDecor(const char *name) DecorManager::_FindDecor(BString name)
{ {
if (!name) if (!name)
return NULL; return NULL;
for (int32 i = 0; i < fDecorList.CountItems(); i++) { for (int32 i = 0; i < fDecorList.CountItems(); i++) {
DecorInfo* info = fDecorList.ItemAt(i); DecorAddOn* decor = fDecorList.ItemAt(i);
if (strcmp(name, info->Name()) == 0) if (decor->Name() == name)
return info; return decor;
} }
return NULL; return NULL;
@@ -321,7 +340,7 @@ DecorManager::_LoadSettingsFromDisk()
if (settings.Unflatten(&file) == B_OK) { if (settings.Unflatten(&file) == B_OK) {
BString itemtext; BString itemtext;
if (settings.FindString("decorator", &itemtext) == B_OK) { if (settings.FindString("decorator", &itemtext) == B_OK) {
DecorInfo* decor = _FindDecor(itemtext.String()); DecorAddOn* decor = _FindDecor(itemtext);
if (decor) { if (decor) {
fCurrentDecor = decor; fCurrentDecor = decor;
return true; return true;
+46 -4
View File
@@ -20,7 +20,46 @@
class DecorInfo; class DecorInfo;
class Desktop; class Desktop;
class DesktopListener;
class DrawingEngine; 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 class DecorManager
@@ -36,13 +75,15 @@ public:
BRect rect, BRect rect,
const char* title, window_look look, const char* title, window_look look,
uint32 flags); uint32 flags);
WindowBehaviour* AllocateWindowBehaviour(Window* window);
const DesktopListenerList& GetDesktopListeners();
int32 CountDecorators() const; int32 CountDecorators() const;
int32 GetDecorator() const; int32 GetDecorator() const;
bool SetDecorator(int32 index, Desktop* desktop); bool SetDecorator(int32 index, Desktop* desktop);
bool SetR5Decorator(int32 value); bool SetR5Decorator(int32 value);
const char* GetDecoratorName(int32 index); BString GetDecoratorName(int32 index);
// TODO: Implement this method once the rest of the necessary infrastructure // TODO: Implement this method once the rest of the necessary infrastructure
// is in place // is in place
@@ -50,13 +91,14 @@ public:
private: private:
void _EmptyList(); void _EmptyList();
DecorInfo* _FindDecor(const char *name); DecorAddOn* _FindDecor(BString name);
bool _LoadSettingsFromDisk(); bool _LoadSettingsFromDisk();
bool _SaveSettingsToDisk(); bool _SaveSettingsToDisk();
BObjectList<DecorInfo> fDecorList; BObjectList<DecorAddOn> fDecorList;
DecorInfo* fCurrentDecor; DecorAddOn fDefaultDecorAddOn;
DecorAddOn* fCurrentDecor;
}; };
extern DecorManager gDecorManager; extern DecorManager gDecorManager;
+15 -2
View File
@@ -36,6 +36,7 @@
#include <WindowInfo.h> #include <WindowInfo.h>
#include "AppServer.h" #include "AppServer.h"
#include "DecorManager.h"
#include "DesktopSettingsPrivate.h" #include "DesktopSettingsPrivate.h"
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "HWInterface.h" #include "HWInterface.h"
@@ -1901,17 +1902,29 @@ Desktop::RedrawBackground()
void void
Desktop::ReloadAllDecorators() Desktop::ReloadDecor()
{ {
AutoWriteLocker _(fWindowLock); 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 (int32 i = 0; i < kMaxWorkspaces; i++) {
for (Window* window = _Windows(i).LastWindow(); window; for (Window* window = _Windows(i).LastWindow(); window;
window = window->PreviousWindow(i)) { window = window->PreviousWindow(i)) {
BRegion oldBorder; BRegion oldBorder;
window->GetBorderRegion(&oldBorder); window->GetBorderRegion(&oldBorder);
window->ReloadDecorator(); window->ReloadDecor();
BRegion border; BRegion border;
window->GetBorderRegion(&border); window->GetBorderRegion(&border);
+9 -10
View File
@@ -14,6 +14,14 @@
#define DESKTOP_H #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 "CursorManager.h"
#include "DesktopListener.h" #include "DesktopListener.h"
#include "DesktopSettings.h" #include "DesktopSettings.h"
@@ -27,15 +35,6 @@
#include "Workspace.h" #include "Workspace.h"
#include "WorkspacePrivate.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 #define USE_MULTI_LOCKER 1
@@ -233,7 +232,7 @@ public:
void Redraw(); void Redraw();
void RedrawBackground(); void RedrawBackground();
void ReloadAllDecorators(); void ReloadDecor();
BRegion& BackgroundRegion() BRegion& BackgroundRegion()
{ return fBackgroundRegion; } { return fBackgroundRegion; }
+7
View File
@@ -37,6 +37,13 @@ DesktopObservable::UnregisterListener(DesktopListener* listener)
} }
const DesktopListenerDLList&
DesktopObservable::GetDesktopListenerList()
{
return fDesktopListenerList;
}
#define FOR_ALL_DESKTOP_LISTENER \ #define FOR_ALL_DESKTOP_LISTENER \
for (DesktopListener* listener = fDesktopListenerList.First(); \ for (DesktopListener* listener = fDesktopListenerList.First(); \
listener != NULL; listener = fDesktopListenerList.GetNext(listener)) listener != NULL; listener = fDesktopListenerList.GetNext(listener))
+3 -2
View File
@@ -55,7 +55,7 @@ class DesktopListener : public DoublyLinkedListLinkImpl<DesktopListener>
}; };
typedef DoublyLinkedList<DesktopListener> DesktopListenerList; typedef DoublyLinkedList<DesktopListener> DesktopListenerDLList;
class DesktopObservable class DesktopObservable
@@ -65,6 +65,7 @@ class DesktopObservable
void RegisterListener(DesktopListener* listener); void RegisterListener(DesktopListener* listener);
void UnregisterListener(DesktopListener* listener); void UnregisterListener(DesktopListener* listener);
const DesktopListenerDLList& GetDesktopListenerList();
void InvokeAddWindow(Window* window); void InvokeAddWindow(Window* window);
void InvokeRemoveWindow(Window* window); void InvokeRemoveWindow(Window* window);
@@ -104,7 +105,7 @@ class DesktopObservable
bool& fInvoking; bool& fInvoking;
}; };
DesktopListenerList fDesktopListenerList; DesktopListenerDLList fDesktopListenerList;
// prevent recursive invokes // prevent recursive invokes
bool fWeAreInvoking; bool fWeAreInvoking;
+25 -9
View File
@@ -10,20 +10,18 @@
* Brecht Machiels <brecht@mos6581.org> * Brecht Machiels <brecht@mos6581.org>
* Clemens Zeidler <haiku@clemens-zeidler.de> * Clemens Zeidler <haiku@clemens-zeidler.de>
*/ */
#include "Window.h" #include "Window.h"
#include "Decorator.h" #include "Decorator.h"
#include "DecorManager.h" #include "DecorManager.h"
#include "Desktop.h" #include "Desktop.h"
#include "DefaultWindowBehaviour.h"
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "HWInterface.h" #include "HWInterface.h"
#include "MessagePrivate.h" #include "MessagePrivate.h"
#include "PortLink.h" #include "PortLink.h"
#include "ServerApp.h" #include "ServerApp.h"
#include "ServerWindow.h" #include "ServerWindow.h"
#include "WindowBehaviour.h"
#include "Workspace.h" #include "Workspace.h"
#include "WorkspacesView.h" #include "WorkspacesView.h"
@@ -135,7 +133,7 @@ Window::Window(const BRect& frame, const char *name,
&fMaxWidth, &fMaxHeight); &fMaxWidth, &fMaxHeight);
} }
} }
fWindowBehaviour = new (std::nothrow)DefaultWindowBehaviour(this); fWindowBehaviour = gDecorManager.AllocateWindowBehaviour(this);
// do we need to change our size to let the decorator fit? // do we need to change our size to let the decorator fit?
// _ResizeBy() will adapt the frame for validity before resizing // _ResizeBy() will adapt the frame for validity before resizing
@@ -542,17 +540,35 @@ Window::PreviousWindow(int32 index) const
} }
void bool
Window::ReloadDecorator() Window::ReloadDecor()
{ {
::Decorator* decorator = NULL;
WindowBehaviour* windowBehaviour = NULL;
if (fLook != B_NO_BORDER_WINDOW_LOOK) { if (fLook != B_NO_BORDER_WINDOW_LOOK) {
delete fDecorator;
// we need a new decorator // we need a new decorator
fDecorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine, decorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine,
Frame(), Title(), fLook, fFlags); Frame(), Title(), fLook, fFlags);
if (!decorator)
return false;
if (IsFocus()) 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;
} }
+1 -3
View File
@@ -10,12 +10,10 @@
* Brecht Machiels <brecht@mos6581.org> * Brecht Machiels <brecht@mos6581.org>
* Clemens Zeidler <haiku@clemens-zeidler.de> * Clemens Zeidler <haiku@clemens-zeidler.de>
*/ */
#ifndef WINDOW_H #ifndef WINDOW_H
#define WINDOW_H #define WINDOW_H
#include "Decorator.h"
#include "RegionPool.h" #include "RegionPool.h"
#include "ServerWindow.h" #include "ServerWindow.h"
#include "View.h" #include "View.h"
@@ -71,7 +69,7 @@ public:
::EventTarget& EventTarget() const ::EventTarget& EventTarget() const
{ return fWindow->EventTarget(); } { return fWindow->EventTarget(); }
void ReloadDecorator(); bool ReloadDecor();
void SetScreen(const ::Screen* screen); void SetScreen(const ::Screen* screen);
const ::Screen* Screen() const; const ::Screen* Screen() const;