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

View File

@ -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();
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)
DecorAddOn::DecorAddOn(image_id id, const char* name)
:
fID(id),
fName(name),
fAllocator(allocator)
fImageID(id),
fName(name)
{
}
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.
}
status_t
DecorAddOn::InitCheck() const
{
return B_OK;
}
Decorator*
DecorInfo::Instantiate(Desktop* desktop, DrawingEngine* engine, BRect rect,
const char *title, window_look look, uint32 flags)
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;
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();
if (!decorator)
return NULL;
}
desktop->UnlockSingleWindow();
decorator->SetDrawingEngine(engine);
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 -
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 @@ DecorManager::DecorManager()
_LoadSettingsFromDisk();
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
// 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 @@ DecorManager::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
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 @@ DecorManager::GetDecorator() const
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 @@ DecorManager::SetR5Decorator(int32 value)
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 @@ DecorManager::SetR5Decorator(int32 value)
}
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 @@ DecorManager::_LoadSettingsFromDisk()
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;

View File

@ -20,7 +20,46 @@
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
@ -36,13 +75,15 @@ public:
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 @@ public:
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;

View File

@ -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 @@ Desktop::RedrawBackground()
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);

View File

@ -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,15 +35,6 @@
#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
@ -233,7 +232,7 @@ public:
void Redraw();
void RedrawBackground();
void ReloadAllDecorators();
void ReloadDecor();
BRegion& BackgroundRegion()
{ return fBackgroundRegion; }

View File

@ -37,6 +37,13 @@ DesktopObservable::UnregisterListener(DesktopListener* listener)
}
const DesktopListenerDLList&
DesktopObservable::GetDesktopListenerList()
{
return fDesktopListenerList;
}
#define FOR_ALL_DESKTOP_LISTENER \
for (DesktopListener* listener = fDesktopListenerList.First(); \
listener != NULL; listener = fDesktopListenerList.GetNext(listener))

View File

@ -55,7 +55,7 @@ class DesktopListener : public DoublyLinkedListLinkImpl<DesktopListener>
};
typedef DoublyLinkedList<DesktopListener> DesktopListenerList;
typedef DoublyLinkedList<DesktopListener> DesktopListenerDLList;
class DesktopObservable
@ -65,6 +65,7 @@ class DesktopObservable
void RegisterListener(DesktopListener* listener);
void UnregisterListener(DesktopListener* listener);
const DesktopListenerDLList& GetDesktopListenerList();
void InvokeAddWindow(Window* window);
void InvokeRemoveWindow(Window* window);
@ -104,7 +105,7 @@ class DesktopObservable
bool& fInvoking;
};
DesktopListenerList fDesktopListenerList;
DesktopListenerDLList fDesktopListenerList;
// prevent recursive invokes
bool fWeAreInvoking;

View File

@ -10,20 +10,18 @@
* Brecht Machiels <brecht@mos6581.org>
* Clemens Zeidler <haiku@clemens-zeidler.de>
*/
#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 @@ Window::Window(const BRect& frame, const char *name,
&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 @@ Window::PreviousWindow(int32 index) const
}
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;
}

View File

@ -10,12 +10,10 @@
* Brecht Machiels <brecht@mos6581.org>
* Clemens Zeidler <haiku@clemens-zeidler.de>
*/
#ifndef WINDOW_H
#define WINDOW_H
#include "Decorator.h"
#include "RegionPool.h"
#include "ServerWindow.h"
#include "View.h"
@ -71,7 +69,7 @@ public:
::EventTarget& EventTarget() const
{ return fWindow->EventTarget(); }
void ReloadDecorator();
bool ReloadDecor();
void SetScreen(const ::Screen* screen);
const ::Screen* Screen() const;