Applied patch by Joseph "looncraz" Groover from ticket #7445.

This changes how Decorators are managed and applied. The app_server
no longer scans and maintains the available ones himself, but is
simply asked to load a Decorator add-on from a provided path.
The Decorator scanning is moved into DecorInfo and DecorInfoUtil,
private classes in the InterfaceKit. The bin command 'setdecor'
uses those.
I cleaned up all the coding style violations that I could find,
removed chunks of code which didn't make sense (if you never put
a NULL pointer into a list, you don't need to check for this and
so on) and also cleaned up other passages for improved clarity
and simplicity.
I also tested the functionality and it works fine. Would even be
Ok to include in Alpha 3, IMHO. Thanks for the patch!


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41581 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2011-05-19 15:25:54 +00:00
parent 93e483aeab
commit b46615c55a
32 changed files with 1253 additions and 476 deletions

View File

@ -0,0 +1,129 @@
/*
* Public domain source code.
*
* Author:
* Joseph "looncraz" Groover <looncraz@satx.rr.com>
*/
#ifndef DECOR_INFO_H
#define DECOR_INFO_H
#include <Entry.h>
#include <Bitmap.h>
#include <String.h>
#include <Locker.h>
#include <ObjectList.h>
// NOTE: DecorInfo itself is not thread-safe
class DecorInfo {
public:
DecorInfo();
DecorInfo(const BString& path);
DecorInfo(const entry_ref& ref);
~DecorInfo();
status_t SetTo(const entry_ref& ref);
status_t SetTo(BString path);
status_t InitCheck() const;
void Unset();
bool IsDefault() const;
BString Path() const;
// Returns "Default" for the default decorator
const entry_ref* Ref() const;
// Returns NULL if virtual (default) or InitCheck() != B_OK
// The ref returned may NOT be the same as the one given to
// SetTo or the constructor - we may have traversed a Symlink!
BString Name() const;
BString ShortcutName() const;
BString Authors() const;
BString ShortDescription() const;
BString LongDescription() const;
BString LicenseURL() const;
BString LicenseName() const;
BString SupportURL() const;
float Version() const;
time_t ModificationTime() const;
bool CheckForChanges(bool &deleted);
private:
void _Init(bool is_update = false);
private:
entry_ref fRef;
BString fPath;
BString fName;
BString fAuthors;
BString fShortDescription;
BString fLongDescription;
BString fLicenseURL;
BString fLicenseName;
BString fSupportURL;
float fVersion;
time_t fModificationTime;
status_t fInitStatus;
};
class DecorInfoUtility{
public:
DecorInfoUtility(bool scanNow = true);
// NOTE: When scanNow is passed false,
// scanning will be performed lazily, such
// as in CountDecorators() and other
// methods.
~DecorInfoUtility();
status_t ScanDecorators();
// Can also be used to rescan for changes.
// Warning: potentially destructive as we
// will remove all DecorInfo objects which
// no longer have a file system cousin.
// TODO: Would a call-back mechanism be
// worthwhile here?
int32 CountDecorators();
DecorInfo* DecoratorAt(int32);
DecorInfo* FindDecorator(const BString& string);
// Checks for ref.name, path, fName, and
// "Default," an empty-string returns the
// current decorator NULL on match failure
DecorInfo* CurrentDecorator();
DecorInfo* DefaultDecorator();
bool IsCurrentDecorator(DecorInfo*);
status_t SetDecorator(DecorInfo*);
status_t SetDecorator(int32);
status_t Preview(DecorInfo* decor, BWindow* window);
private:
DecorInfo* _FindDecor(const BString& path);
private:
BObjectList<DecorInfo> fList;
BLocker fLock;
bool fHasScanned;
};
#endif

View File

@ -93,13 +93,6 @@ BeDecorAddOn::BeDecorAddOn(image_id id, const char* name)
}
float
BeDecorAddOn::Version()
{
return 1.00;
}
Decorator*
BeDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags)

View File

@ -24,8 +24,6 @@ class BeDecorAddOn : public DecorAddOn {
public:
BeDecorAddOn(image_id id, const char* name);
float Version();
protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
BRect rect, window_look look, uint32 flags);

View File

@ -7,7 +7,10 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UsePrivateHeaders app shared interface graphics ;
UseLibraryHeaders agg ;
AddResources ClassicBe : resources.rdef ;
Addon ClassicBe :
BeDecorator.cpp
: be <nogrist>app_server $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++)
: resources.rdef
;

View File

@ -0,0 +1,10 @@
resource("be:decor:info") message('deco') {
"name" = "Classic BeOS",
"authors" = "DarkWyrm, Stephan Aßmus, Clemens Zeidler",
"short_descr" = "Basic appearance of the classic BeOS.",
"long_descr" = "",
"lic_url" = "",
"lic_name" = "MIT",
"support_url" = "http://www.haiku-os.org/",
float "version" = 1.0
};

View File

@ -7,6 +7,8 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UsePrivateHeaders app shared interface graphics ;
UseLibraryHeaders agg ;
AddResources MacDecorator : resources.rdef ;
Addon MacDecorator :
MacDecorator.cpp
: be <nogrist>app_server $(TARGET_LIBSTDC++)

View File

@ -38,13 +38,6 @@ MacDecorAddOn::MacDecorAddOn(image_id id, const char* name)
}
float
MacDecorAddOn::Version()
{
return 1.00;
}
Decorator*
MacDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags)

View File

@ -14,8 +14,6 @@ class MacDecorAddOn : public DecorAddOn {
public:
MacDecorAddOn(image_id id, const char* name);
float Version();
protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
BRect rect, window_look look, uint32 flags);

View File

@ -0,0 +1,10 @@
resource("be:decor:info") message('deco') {
"name" = "MacOS 9",
"authors" = "",
"short_descr" = "MacOS 9",
"long_descr" = "",
"lic_url" = "",
"lic_name" = "MIT",
"support_url" = "http://www.haiku-os.org/",
float "version" = 1.0
};

View File

@ -8,6 +8,8 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UseFreeTypeHeaders ;
AddResources SATDecorator : resources.rdef ;
Addon SATDecorator :
SATDecorator.cpp
SATGroup.cpp

View File

@ -66,13 +66,6 @@ SATDecorAddOn::InitCheck() const
}
float
SATDecorAddOn::Version()
{
return 0.1;
}
Decorator*
SATDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags)

View File

@ -19,7 +19,6 @@ public:
SATDecorAddOn(image_id id, const char* name);
virtual status_t InitCheck() const;
float Version();
protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings,

View File

@ -0,0 +1,11 @@
resource("be:decor:info") message('deco') {
"name" = "Stack and Tile",
"authors" = "Clemens Zeidler, Ingo Weinhold",
"short_descr" = "Default look with ability to stack & tile windows.",
"long_descr" = "Group windows together and take advantage of those"
" tabs!\n\nTODO: instructions",
"lic_url" = "",
"lic_name" = "MIT",
"support_url" = "http://www.haiku-os.org/",
float "version" = 1.0
};

View File

@ -7,6 +7,8 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UsePrivateHeaders app shared interface graphics ;
UseLibraryHeaders agg ;
AddResources WinDecorator : resources.rdef ;
Addon WinDecorator :
WinDecorator.cpp
: be <nogrist>app_server $(TARGET_LIBSTDC++)

View File

@ -37,13 +37,6 @@ WinDecorAddOn::WinDecorAddOn(image_id id, const char* name)
}
float
WinDecorAddOn::Version()
{
return 1.00;
}
Decorator*
WinDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags)

View File

@ -14,7 +14,6 @@ class WinDecorAddOn : public DecorAddOn {
public:
WinDecorAddOn(image_id id, const char* name);
float Version();
protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings,

View File

@ -0,0 +1,10 @@
resource("be:decor:info") message('deco') {
"name" = "Windows 95",
"authors" = "",
"short_descr" = "Windows 95",
"long_descr" = "",
"lic_url" = "",
"lic_name" = "MIT",
"support_url" = "http://www.haiku-os.org/",
float "version" = 1.0
};

View File

@ -102,7 +102,6 @@ StdBinCommands
play.cpp
quit.cpp
roster.cpp
setdecor.cpp
setversion.cpp
trash.cpp
version.cpp
@ -123,6 +122,7 @@ StdBinCommands
hey.cpp
reindex.cpp
resattr.cpp
setdecor.cpp
settype.cpp
spybmessage.cpp
urlwrapper.cpp

View File

@ -1,4 +1,5 @@
/*
* Copyright 2011, Joseph "looncraz" Groover, looncraz@satx.rr.com
* Copyright 2007, François Revol, revol@free.fr.
* Distributed under the terms of the MIT license.
*/
@ -7,87 +8,224 @@
#include <stdio.h>
#include <Application.h>
#include <Bitmap.h>
#include <InterfaceDefs.h>
#include <String.h>
#include <Window.h>
#include <View.h>
class BBitmap;
#include <private/interface/DecorInfo.h>
namespace BPrivate {
int32 count_decorators(void);
int32 get_decorator(void);
status_t get_decorator_name(const int32 &index, BString &name);
status_t get_decorator_preview(const int32 &index, BBitmap *bitmap);
status_t set_decorator(const int32 &index);
void
print_decor_info_header()
{
printf(" Name License\t Description\n");
printf("----------------------------------------------------\n");
}
using namespace BPrivate;
int main(int argc, char **argv)
void
print_decor_summary(DecorInfo* decor, bool isCurrent)
{
if (isCurrent)
printf("*");
printf("%-12s\t%-8s %-30s\n", decor->Name().String(),
decor->LicenseName().String(), decor->ShortDescription().String());
}
void
print_decor_shortcut(DecorInfo* decor, bool isCurrent)
{
if (isCurrent)
printf("*");
printf("%-12s\t%-12s\n", decor->ShortcutName().String(),
decor->Name().String());
}
void
print_decor_info_verbose(DecorInfo* decor, bool isCurrent)
{
printf("Name:\t\t%s\n", decor->Name().String());
printf("Version:\t%f\n", decor->Version());
printf("Author(s):\t%s\n", decor->Authors().String());
printf("Description:\t%s\n", decor->ShortDescription().String());
printf("License:\t%s (%s)\n", decor->LicenseName().String(),
decor->LicenseURL().String());
printf("Support URL:\t%s\n", decor->SupportURL().String());
printf("%s\n", isCurrent ? "Currently in use." : "Currently not in use.");
}
int
main(int argc, char** argv)
{
status_t err;
if (argc < 2) {
printf("usage: %s [-l|-c|decorname]\n", argv[0]);
printf("\t-l: list available decors\n");
printf("\t-s: list shortcut names for available decors\n");
printf("\t-c: give current decor name\n");
printf("\t-i: detailed information about decor\n");
printf("\t-p: see preview window\n");
return 1;
}
// combine remaining args into one string:
BString decoratorName;
for (int i = 2; i < argc; ++i)
decoratorName << argv[i] << " ";
decoratorName.RemoveLast(" ");
BApplication app("application/x-vnd.Haiku-setdecor");
DecorInfoUtility* util = new DecorInfoUtility();
DecorInfo* decor = NULL;
if (util == NULL) {
fprintf(stderr, "error instantiating DecoratorInfoUtility (out of"
" memory?)\n");
return 1;
}
// we want the list
if (!strcmp(argv[1], "-l")) {
int32 i, count;
count = count_decorators();
if (count < 0) {
fprintf(stderr, "error counting decorators: %s\n", strerror(count));
return 1;
}
for (i = 0; i < count; i++) {
BString name;
err = get_decorator_name(i, name);
if (err < 0)
continue;
printf("%s\n", name.String());
// Print default decorator:
print_decor_info_header();
int32 count = util->CountDecorators();
for (int32 i = 0; i < count; ++i) {
decor = util->DecoratorAt(i);
if (decor == NULL) {
fprintf(stderr, "error NULL entry @ %li / %li - BUG BUG BUG\n",
i, count);
// return 2 to track DecorInfoUtility errors
return 2;
}
print_decor_summary(decor, util->IsCurrentDecorator(decor));
}
return 0;
}
// we want the current one
// we want the current decorator
if (!strcmp(argv[1], "-c")) {
int32 i;
BString name;
i = get_decorator();
if (i < 0) {
fprintf(stderr, "error getting current decorator: %s\n", strerror(i));
return 1;
decor = util->CurrentDecorator();
if (decor == NULL) {
fprintf(stderr, "Unable to determine current decorator, sorry! - "
"BUG BUG BUG\n");
return 2;
}
err = get_decorator_name(i, name);
if (err < 0) {
fprintf(stderr, "error getting name of decorator: %s\n", strerror(err));
return 1;
}
printf("%s\n", name.String());
print_decor_info_header();
print_decor_summary(decor, true);
return 0;
}
if (!strcmp(argv[1], "-s")) {
printf(" Shortcut Name\n");
printf("------------------------------------\n");
int32 count = util->CountDecorators();
for (int32 i = 0; i < count; ++i) {
decor = util->DecoratorAt(i);
if (decor == NULL) {
fprintf(stderr, "error NULL entry @ %li / %li - BUG BUG BUG\n",
i, count);
// return 2 to track DecorInfoUtility errors
return 2;
}
print_decor_shortcut(decor, util->IsCurrentDecorator(decor));
}
return 0;
}
// we want detailed information for a specific decorator ( by name or path )
if (!strcmp(argv[1], "-i")) {
if (argc < 3) {
fprintf(stderr, "not enough arguments\n");
return 1;
}
decor = util->FindDecorator(decoratorName.String());
if (decor == NULL) {
fprintf(stderr, "Can't find decor named \"%s\", try again\n",
decoratorName.String());
return 1;
}
print_decor_info_verbose(decor, util->IsCurrentDecorator(decor));
return 0;
}
if (!strcmp(argv[1], "-p")) {
if (argc < 3) {
fprintf(stderr, "not enough arguments\n");
return 1;
}
decor = util->FindDecorator(decoratorName.String());
if (decor == NULL) {
fprintf(stderr, "Can't find decor named \"%s\", try again\n",
decoratorName.String());
return 1;
}
printf("Preparing preview...\n");
BWindow* previewWindow = new BWindow(BRect(150, 150, 390, 490),
decor->Name().String(), B_TITLED_WINDOW, B_NOT_ZOOMABLE
| B_QUIT_ON_WINDOW_CLOSE | B_NOT_RESIZABLE );
previewWindow->AddChild(new BView(previewWindow->Bounds(), "",
B_FOLLOW_ALL, 0));
if (util->Preview(decor, previewWindow) != B_OK) {
fprintf(stderr, "Unable to preview decorator, sorry!\n");
// TODO: more detailed error...
return 1;
}
previewWindow->Show();
app.Run();
return 0;
}
// we want to change it
int32 i, count;
count = count_decorators();
if (count < 0) {
fprintf(stderr, "error counting decorators: %s\n", strerror(count));
decoratorName = "";
for (int i = 1; i < argc; ++i)
decoratorName << argv[i] << " ";
decoratorName.RemoveLast(" ");
decor = util->FindDecorator(decoratorName.String());
if (decor == NULL) {
fprintf(stderr, "no such decorator \"%s\"\n", decoratorName.String());
return 1;
}
for (i = 0; i < count; i++) {
BString name;
err = get_decorator_name(i, name);
if (err < 0)
continue;
if (name == argv[1]) {
err = set_decorator(i);
if (err < 0) {
fprintf(stderr, "error setting decorator: %s\n", strerror(err));
return 1;
}
return 0;
}
if (util->IsCurrentDecorator(decor)) {
printf("\"%s\" is already the current decorator\n",
decor->Name().String());
return 0;
}
fprintf(stderr, "can't find decorator \"%s\"\n", argv[1]);
return 1;
printf("Setting %s as the current decorator...\n", decor->Name().String());
if (util->SetDecorator(decor) != B_OK ) {
fprintf(stderr, "Unable to set decorator, sorry\n\n");
return 1; // todo more detailed error...
}
return 0;
}

View File

@ -0,0 +1,594 @@
/*
* Public domain source code.
*
* Author:
* Joseph "looncraz" Groover <looncraz@satx.rr.com>
*/
#include <DecorInfo.h>
#include <new>
#include <stdio.h>
#include <Autolock.h>
#include <Directory.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Resources.h>
DecorInfo::DecorInfo()
:
fVersion(0),
fModificationTime(0),
fInitStatus(B_NO_INIT)
{
}
DecorInfo::DecorInfo(const BString& path)
:
fPath(path),
fVersion(0),
fModificationTime(0),
fInitStatus(B_NO_INIT)
{
BEntry entry(path.String(), true);
entry.GetRef(&fRef);
_Init();
}
DecorInfo::DecorInfo(const entry_ref& ref)
:
fRef(ref),
fVersion(0),
fModificationTime(0),
fInitStatus(B_NO_INIT)
{
BPath path(&ref);
fPath = path.Path();
_Init();
}
DecorInfo::~DecorInfo()
{
}
status_t
DecorInfo::SetTo(const entry_ref& ref)
{
Unset();
BPath path(&ref);
fPath = path.Path();
path.Unset();
fRef = ref;
_Init();
return InitCheck();
}
status_t
DecorInfo::SetTo(BString path)
{
entry_ref ref;
BEntry entry(path.String(), true);
entry.GetRef(&ref);
entry.Unset();
return SetTo(ref);
}
status_t
DecorInfo::InitCheck() const
{
return fInitStatus;
}
void
DecorInfo::Unset()
{
fRef = entry_ref();
fPath = "";
fName = "";
fAuthors = "";
fShortDescription = "";
fLicenseURL = "";
fLicenseName = "";
fSupportURL = "";
fVersion = 0;
fModificationTime = 0;
fInitStatus = B_NO_INIT;
}
bool
DecorInfo::IsDefault() const
{
return fInitStatus == B_OK && fPath == "Default";
}
BString
DecorInfo::Path() const
{
return fPath.String();
}
const entry_ref*
DecorInfo::Ref() const
{
if (InitCheck() != B_OK || IsDefault())
return NULL;
return &fRef;
}
BString
DecorInfo::Name() const
{
return fName;
}
BString
DecorInfo::ShortcutName() const
{
if (Ref())
return fRef.name;
return Name();
}
BString
DecorInfo::Authors() const
{
return fAuthors;
}
BString
DecorInfo::ShortDescription() const
{
return fShortDescription;
}
BString
DecorInfo::LongDescription() const
{
return fLongDescription;
}
BString
DecorInfo::LicenseURL() const
{
return fLicenseURL;
}
BString
DecorInfo::LicenseName() const
{
return fLicenseName;
}
BString
DecorInfo::SupportURL() const
{
return fSupportURL;
}
float
DecorInfo::Version() const
{
return fVersion;
}
time_t
DecorInfo::ModificationTime() const
{
return fModificationTime;
}
bool
DecorInfo::CheckForChanges(bool& deleted)
{
if (InitCheck() != B_OK)
return false;
BEntry entry(&fRef);
if (entry.InitCheck() != B_OK)
return false;
if (!entry.Exists()) {
deleted = true;
return true;
}
time_t modtime = 0;
if (entry.GetModificationTime(&modtime) != B_OK) {
fprintf(stderr, "DecorInfo::CheckForChanges()\tERROR: "
"BEntry:GetModificationTime() failed\n");
return false;
}
if (fModificationTime != modtime) {
_Init(true);
return true;
}
return false;
}
void
DecorInfo::_Init(bool isUpdate)
{
if (!isUpdate && InitCheck() != B_NO_INIT) {
// TODO: remove after validation
fprintf(stderr, "DecorInfo::_Init()\tImproper init state\n");
return;
}
BEntry entry;
if (fPath == "Default") {
if (isUpdate){
// should never happen
fprintf(stderr, "DecorInfo::_Init(true)\tBUG BUG updating default"
"decorator!?!?!\n");
return;
}
fName = "Default";
fAuthors = "DarkWyrm, Stephan Aßmus, Clemens Zeidler, Ingo Weinhold";
fShortDescription = "Default Haiku window decorator.";
fLongDescription = fShortDescription;
fLicenseURL = "http://";
fLicenseName = "MIT";
fSupportURL = "http://www.haiku-os.org/";
fVersion = 0.5;
fInitStatus = B_OK;
// The following is to get the modification time of the app_server
// and, thusly, the Default decorator...
// If you can make it more simple, please do!
BPath path;
find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
path.Append("app_server");
entry.SetTo(path.Path(), true);
if (!entry.Exists()) {
fprintf(stderr, "Server MIA the world has become its slave! "
"Call the CIA!\n");
return;
}
entry.GetModificationTime(&fModificationTime);
entry.Unset();
return;
}
// Is a file system object...
entry.SetTo(&fRef, true); // follow link
if (entry.InitCheck() != B_OK) {
fInitStatus = entry.InitCheck();
return;
}
if (!entry.Exists()) {
if (isUpdate) {
fprintf(stderr, "DecorInfo::_Init()\tERROR: decorator deleted"
" after CheckForChanges() found it!\n");
fprintf(stderr, "DecorInfo::_Init()\tERROR: DecorInfo will "
"Unset\n");
Unset();
}
return;
}
// update fRef to match file system object
entry.GetRef(&fRef);
entry.GetModificationTime(&fModificationTime);
BResources resources(&fRef);
if (resources.InitCheck() != B_OK) {
fprintf(stderr, "DecorInfo::_Init()\t BResource InitCheck() failure\n");
return;
}
size_t infoSize = 0;
const void* infoData = resources.LoadResource(B_MESSAGE_TYPE,
"be:decor:info", &infoSize);
BMessage infoMessage;
if (infoData == NULL || infoSize == 0
|| infoMessage.Unflatten((const char*)infoData) != B_OK) {
fprintf(stderr, "DecorInfo::_init()\tNo extended information found for"
" \"%s\"\n", fRef.name);
} else {
infoMessage.FindString("name", &fName);
infoMessage.FindString("authors", &fAuthors);
infoMessage.FindString("short_descr", &fShortDescription);
infoMessage.FindString("long_descr", &fLongDescription);
infoMessage.FindString("lic_url", &fLicenseURL);
infoMessage.FindString("lic_name", &fLicenseName);
infoMessage.FindString("support_url", &fSupportURL);
infoMessage.FindFloat ("version", &fVersion);
}
resources.Unset();
fInitStatus = B_OK;
fName = fRef.name;
}
// #pragma mark - DecorInfoUtility
namespace BPrivate {
// kits/interface/InterfaceDefs.cpp
bool get_decorator(BString&);
status_t set_decorator(const BString&);
status_t preview_decorator(const BString&, BWindow*);
};
using namespace BPrivate;
DecorInfoUtility::DecorInfoUtility(bool scanNow)
:
fHasScanned(false)
{
// get default decorator from app_server
DecorInfo* info = new(std::nothrow) DecorInfo("Default");
if (info == NULL || info->InitCheck() != B_OK) {
delete info;
fprintf(stderr, "DecorInfoUtility::constructor\tdefault decorator's "
"DecorInfo failed InitCheck()\n");
return;
}
fList.AddItem(info);
if (scanNow)
ScanDecorators();
}
DecorInfoUtility::~DecorInfoUtility()
{
BAutolock _(fLock);
for (int i = fList.CountItems() - 1; i >= 0; --i)
delete fList.ItemAt(i);
}
status_t
DecorInfoUtility::ScanDecorators()
{
BPath decorPath;
status_t ret = find_directory(B_USER_ADDONS_DIRECTORY, &decorPath);
if (ret != B_OK)
return ret;
ret = decorPath.Append("decorators");
if (ret != B_OK)
return ret;
BDirectory dir(decorPath.Path());
ret = dir.InitCheck();
if (ret != B_OK) {
fprintf(stderr, "DecorInfoUtility::ScanDecorators:\tERROR: "
"DECORATORS_DIR not found!\n");
return ret;
}
BAutolock _(fLock);
// First, run through our list and DecorInfos CheckForChanges()
if (fHasScanned) {
for (int i = fList.CountItems() - 1; i > 0; --i) {
DecorInfo* decorInfo = fList.ItemAt(i);
bool deleted = false;
decorInfo->CheckForChanges(deleted);
if (deleted) {
fList.RemoveItem(decorInfo);
delete decorInfo;
}
}
}
BPath path;
entry_ref ref;
// Now, look at file system, skip the entries for which we already have
// a DecorInfo in the list.
while (dir.GetNextRef(&ref) == B_OK) {
path.SetTo(decorPath.Path());
path.Append(ref.name);
if (_FindDecor(path.Path()) != NULL)
continue;
DecorInfo* decorInfo = new(std::nothrow) DecorInfo(ref);
if (decorInfo == NULL || decorInfo->InitCheck() != B_OK) {
fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tInitCheck() "
"failure on decorator, skipping\n");
delete decorInfo;
continue;
}
fList.AddItem(decorInfo);
}
fHasScanned = true;
return B_OK;
}
int32
DecorInfoUtility::CountDecorators()
{
BAutolock _(fLock);
if (!fHasScanned)
ScanDecorators();
return fList.CountItems();
}
DecorInfo*
DecorInfoUtility::DecoratorAt(int32 index)
{
BAutolock _(fLock);
return fList.ItemAt(index);
}
DecorInfo*
DecorInfoUtility::FindDecorator(const BString& string)
{
if (string.Length() == 0)
return CurrentDecorator();
if (string.ICompare("default") == 0)
return DefaultDecorator();
BAutolock _(fLock);
if (!fHasScanned)
ScanDecorators();
// search by path
DecorInfo* decor = _FindDecor(string);
if (decor != NULL)
return decor;
// search by cached name
for (int i = 1; i < fList.CountItems(); ++i) {
decor = fList.ItemAt(i);
if (string.ICompare(decor->Name()) == 0)
return decor;
}
return NULL;
}
DecorInfo*
DecorInfoUtility::CurrentDecorator()
{
BAutolock _(fLock);
if (!fHasScanned)
ScanDecorators();
BString name;
get_decorator(name);
return FindDecorator(name);
}
DecorInfo*
DecorInfoUtility::DefaultDecorator()
{
BAutolock _(fLock);
return fList.ItemAt(0);
}
bool
DecorInfoUtility::IsCurrentDecorator(DecorInfo* decor)
{
BAutolock _(fLock);
if (decor == NULL)
return false;
return decor->Path() == CurrentDecorator()->Path();
}
status_t
DecorInfoUtility::SetDecorator(DecorInfo* decor)
{
if (decor == NULL)
return B_BAD_VALUE;
BAutolock _(fLock);
if (decor->IsDefault())
return set_decorator("Default");
return set_decorator(decor->Path());
}
status_t
DecorInfoUtility::SetDecorator(int32 index)
{
BAutolock _(fLock);
if (!fHasScanned)
return B_ERROR;
DecorInfo* decor = DecoratorAt(index);
if (decor == NULL)
return B_BAD_INDEX;
return SetDecorator(decor);
}
status_t
DecorInfoUtility::Preview(DecorInfo* decor, BWindow* window)
{
if (decor == NULL)
return B_BAD_VALUE;
return preview_decorator(decor->Path(), window);
}
// #pargma mark - private
DecorInfo*
DecorInfoUtility::_FindDecor(const BString& pathString)
{
// find decor by path and path alone!
if (!fLock.IsLocked()) {
fprintf(stderr, "DecorInfoUtility::_find_decor()\tfailure to lock! - "
"BUG BUG BUG\n");
return NULL;
}
if (pathString == "Default")
return fList.ItemAt(0);
for (int i = 1; i < fList.CountItems(); ++i) {
DecorInfo* decor = fList.ItemAt(i);
// Find the DecoratorInfo either by its true current location or by
// what we still think the location is (before we had a chance to
// update). NOTE: This will only catch the case when the user moved the
// folder in which the add-on file lives. It will not work when the user
// moves the add-on file itself or renames it.
BPath path(decor->Ref());
if (path.Path() == pathString || decor->Path() == pathString)
return decor;
}
return NULL;
}

View File

@ -32,10 +32,12 @@
#include <ScrollBar.h>
#include <String.h>
#include <TextView.h>
#include <Window.h>
#include <ApplicationPrivate.h>
#include <AppServerLink.h>
#include <ColorConversion.h>
#include <DecorInfo.h>
#include <DefaultColors.h>
#include <InputServerTypes.h>
#include <input_globals.h>
@ -1185,129 +1187,66 @@ _fini_interface_kit_()
}
// #pragma mark -
/*! \brief private function used by Deskbar to set window decor
Note, we don't have to be compatible here, and could just change
the Deskbar not to use this anymore
\param theme The theme to choose
- \c 0: BeOS
- \c 1: AmigaOS
- \c 2: Win95
- \c 3: MacOS
*/
void
__set_window_decor(int32 theme)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_R5_SET_DECORATOR);
link.Attach<int32>(theme);
link.Flush();
}
namespace BPrivate {
/*! \brief queries the server for the number of available decorators
\return the number of available decorators
/*! \brief queries the server for the current decorator
\param ref entry_ref into which to store current decorator's location
\return boolean true/false
*/
int32
count_decorators(void)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_COUNT_DECORATORS);
int32 code;
int32 count = -1;
if (link.FlushWithReply(code) == B_OK && code == B_OK)
link.Read<int32>(&count);
return count;
}
/*! \brief queries the server for the index of the current decorators
\return the current decorator's index
If for some bizarre reason this function fails, it returns -1
*/
int32
get_decorator(void)
bool
get_decorator(BString& path)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_DECORATOR);
int32 code;
int32 index = -1;
if (link.FlushWithReply(code) == B_OK && code == B_OK)
link.Read<int32>(&index);
if (link.FlushWithReply(code) != B_OK || code != B_OK)
return false;
return index;
}
/*! \brief queries the server for the name of the decorator with a certain index
\param index The index of the decorator to get the name for
\param name BString to receive the name of the decorator
\return B_OK if successful, B_ERROR if not
*/
status_t
get_decorator_name(const int32 &index, BString &name)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_DECORATOR_NAME);
link.Attach<int32>(index);
int32 code;
if (link.FlushWithReply(code) == B_OK && code == B_OK) {
char *string;
if (link.ReadString(&string) == B_OK) {
name = string;
free(string);
return B_OK;
}
}
return B_ERROR;
}
/*! \brief asks the server to draw a decorator preview into a BBitmap
\param index The index of the decorator to get the name for
\param bitmap BBitmap to receive the preview
\return B_OK if successful, B_ERROR if not.
This is currently unimplemented.
*/
status_t
get_decorator_preview(const int32 &index, BBitmap *bitmap)
{
// TODO: implement get_decorator_preview
return B_ERROR;
return link.ReadString(path) == B_OK;
}
/*! \brief Private function which sets the window decorator for the system.
\param index Index of the decorator to set
\param entry_ref to the decorator to set
If the index is invalid, this function and the server do nothing
Will return detailed error status via status_t
*/
status_t
set_decorator(const int32 &index)
set_decorator(const BString& path)
{
if (index < 0)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_SET_DECORATOR);
link.Attach<int32>(index);
link.AttachString(path.String());
link.Flush();
return B_OK;
status_t error = B_OK;
link.Read<status_t>(&error);
return error;
}
/*! \brief sets a window to preview a given decorator
\param path path to any given decorator add-on
\param window pointer to BWindow which will show decorator
Piggy-backs on BWindow::SetDecoratorSettings(...)
*/
status_t
preview_decorator(const BString& path, BWindow* window)
{
if (window == NULL)
return B_ERROR;
BMessage msg('prVu');
msg.AddString("preview", path.String());
return window->SetDecoratorSettings(msg);
}

View File

@ -49,6 +49,7 @@ MergeObject <libbe>interface_kit.o :
ColorTools.cpp
Control.cpp
ControlLook.cpp
DecorInfo.cpp
Deskbar.cpp
Dragger.cpp
Font.cpp

View File

@ -20,8 +20,11 @@
#include <Path.h>
#include <SpaceLayoutItem.h>
#include <private/interface/DecorInfo.h>
#include <stdio.h>
#include "APRWindow.h"
#include "defs.h"
#include "ColorWell.h"
@ -35,39 +38,33 @@
#define COLOR_DROPPED 'cldp'
#define DECORATOR_CHANGED 'dcch'
namespace BPrivate
{
int32 count_decorators(void);
status_t set_decorator(const int32 &index);
int32 get_decorator(void);
status_t get_decorator_name(const int32 &index, BString &name);
status_t get_decorator_preview(const int32 &index, BBitmap *bitmap);
}
APRView::APRView(const char *name, uint32 flags)
: BView(name, flags),
APRView::APRView(const char* name, uint32 flags)
:
BView(name, flags),
fDefaultSet(ColorSet::DefaultColorSet()),
fDecorMenu(NULL)
fDecorMenu(NULL),
fDecorUtil(new DecorInfoUtility(false))
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
#if 0
fDecorMenu = new BMenu("Window Style");
int32 decorCount = BPrivate::count_decorators();
int32 decorCount = fDecorUtil->CountDecorators();
DecorInfo* decor = NULL;
if (decorCount > 1) {
for (int32 i = 0; i < decorCount; i++) {
BString name;
BPrivate::get_decorator_name(i, name);
if (name.CountChars() < 1)
decor = fDecorUtil->GetDecorator(i);
if (!decor)
continue;
fDecorMenu->AddItem(new BMenuItem(name.String(),
fDecorMenu->AddItem(new BMenuItem(decor->Name().String(),
new BMessage(DECORATOR_CHANGED)));
}
BMenuField *field = new BMenuField("Window Style", fDecorMenu);
BMenuField* field = new BMenuField("Window Style", fDecorMenu);
// TODO: use this menu field.
}
BMenuItem *marked = fDecorMenu->ItemAt(BPrivate::get_decorator());
BMenuItem* marked = fDecorMenu->ItemAt(fDecorUtil->IndexOfCurrentDecorator());
if (marked)
marked->SetMarked(true);
else {
@ -156,7 +153,7 @@ APRView::MessageReceived(BMessage *msg)
int32 index = fDecorMenu->IndexOf(fDecorMenu->FindMarked());
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
if (index >= 0)
BPrivate::set_decorator(index);
fDecorUtil->SetDecorator(index);
#endif
break;
}
@ -207,7 +204,7 @@ APRView::MessageReceived(BMessage *msg)
if (item) {
item->SetMarked(true);
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
BPrivate::set_decorator(fDecorMenu->IndexOf(item));
fDecorUtil->SetDecorator(fDecorMenu->IndexOf(item));
#endif
}
}

View File

@ -28,6 +28,7 @@
#include "ColorSet.h"
class ColorWell;
class DecorInfoUtility;
class APRWindow;
class APRView : public BView
@ -62,6 +63,7 @@ protected:
ColorSet fDefaultSet;
BMenu *fDecorMenu;
DecorInfoUtility*fDecorUtil;
};
#endif

View File

@ -1,10 +1,11 @@
/*
* Copyright (c) 2001-2010, Haiku, Inc.
* Copyright (c) 2001-2011, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* DarkWyrm <bpmagic@columbus.rr.com>
* Clemens Zeidler <haiku@clemens-zeidler.de>
* Joseph Groover <looncraz@satx.rr.com>
*/
#include "DecorManager.h"
@ -44,7 +45,6 @@ DecorAddOn::DecorAddOn(image_id id, const char* name)
DecorAddOn::~DecorAddOn()
{
}
@ -70,6 +70,7 @@ DecorAddOn::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
if (!decorator)
return NULL;
decorator->SetDrawingEngine(engine);
decorator->SetTitle(title);
@ -104,87 +105,23 @@ DecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
DecorManager::DecorManager()
:
fDefaultDecorAddOn(-1, "Default"),
fCurrentDecor(NULL)
fDefaultDecor(-1, "Default"),
fCurrentDecor(&fDefaultDecor),
fPreviewDecor(NULL),
fPreviewWindow(NULL),
fCurrentDecorPath("Default")
{
// Start with the default decorator - index is always 0
fDecorList.AddItem(&fDefaultDecorAddOn);
// Add any on disk
RescanDecorators();
_LoadSettingsFromDisk();
if (!fCurrentDecor)
fCurrentDecor = fDecorList.ItemAt(0L);
}
DecorManager::~DecorManager()
{
_EmptyList();
}
void
DecorManager::RescanDecorators()
{
BDirectory dir(DECORATORS_DIR);
if (dir.InitCheck() != B_OK)
return;
entry_ref ref;
while (dir.GetNextRef(&ref) == B_OK) {
BPath path;
path.SetTo(DECORATORS_DIR);
path.Append(ref.name);
// Because this function is used for both initialization and for keeping
// the list up to date, check for existence in the list. Note that we
// do not check to see if a decorator has been removed. This is for
// stability. If there is a decorator in memory already whose file has
// been deleted, it is still available until the next boot, at which point
// it will obviously not be loaded.
if (_FindDecor(ref.name))
continue;
image_id image = load_add_on(path.Path());
if (image < 0)
continue;
// As of now, we do nothing with decorator versions, but the possibility
// exists that the API will change even though I cannot forsee any reason
// to do so. If we *did* do anything with decorator versions, the
// assignment would go here.
create_decor_addon* createFunc;
// Get the instantiation function
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!
if (!addon || addon->InitCheck() != B_OK
|| !fDecorList.AddItem(addon)) {
unload_add_on(image);
delete addon;
continue;
}
}
}
Decorator *
DecorManager::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
BRect rect, const char* title, window_look look, uint32 flags)
Decorator*
DecorManager::AllocateDecorator(Window* window)
{
// Create a new instance of the current decorator.
// Ownership is that of the caller
@ -195,8 +132,20 @@ DecorManager::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
return NULL;
}
return fCurrentDecor->AllocateDecorator(desktop, engine, rect, title,
look, flags);
// Are we previewing a specific decorator?
if (window == fPreviewWindow) {
if (fPreviewDecor != NULL) {
return fPreviewDecor->AllocateDecorator(window->Desktop(),
window->GetDrawingEngine(), window->Frame(), window->Title(),
window->Look(), window->Flags());
} else {
fPreviewWindow = NULL;
}
}
return fCurrentDecor->AllocateDecorator(window->Desktop(),
window->GetDrawingEngine(), window->Frame(), window->Title(),
window->Look(), window->Flags());
}
@ -213,6 +162,63 @@ DecorManager::AllocateWindowBehaviour(Window* window)
}
void
DecorManager::CleanupForWindow(Window* window)
{
// Given window is being deleted, do any cleanup needed
if (fPreviewWindow == window && window != NULL){
fPreviewWindow = NULL;
if (fPreviewDecor != NULL)
unload_add_on(fPreviewDecor->ImageID());
fPreviewDecor = NULL;
}
}
status_t
DecorManager::PreviewDecorator(BString path, Window* window)
{
if (fPreviewWindow != NULL && fPreviewWindow != window){
// Reset other window to current decorator - only one can preview
Window* oldPreviewWindow = fPreviewWindow;
fPreviewWindow = NULL;
oldPreviewWindow->ReloadDecor();
}
if (window == NULL)
return B_BAD_VALUE;
// We have to jump some hoops because the window must be able to
// delete its decorator before we unload the add-on
status_t error = B_OK;
DecorAddOn* decorPtr = _LoadDecor(path, error);
if (decorPtr == NULL)
return error == B_OK ? B_ERROR : error;
BRegion border;
window->GetBorderRegion(&border);
DecorAddOn* oldDecor = fPreviewDecor;
fPreviewDecor = decorPtr;
fPreviewWindow = window;
// After this call, the window has deleted its decorator.
fPreviewWindow->ReloadDecor();
BRegion newBorder;
window->GetBorderRegion(&newBorder);
border.Include(&newBorder);
window->Desktop()->RebuildAndRedrawAfterWindowChange(window, border);
if (oldDecor != NULL)
unload_add_on(oldDecor->ImageID());
return B_OK;
}
const DesktopListenerList&
DecorManager::GetDesktopListeners()
{
@ -220,100 +226,87 @@ DecorManager::GetDesktopListeners()
}
int32
DecorManager::CountDecorators() const
{
return fDecorList.CountItems();
}
int32
DecorManager::GetDecorator() const
{
return fDecorList.IndexOf(fCurrentDecor);
}
bool
DecorManager::SetDecorator(int32 index, Desktop* desktop)
{
DecorAddOn* newDecor = fDecorList.ItemAt(index);
if (newDecor) {
fCurrentDecor = newDecor;
desktop->ReloadDecor();
_SaveSettingsToDisk();
return true;
}
return false;
}
bool
DecorManager::SetR5Decorator(int32 value)
{
BString string;
switch (value) {
case 0: string = "BeOS"; break;
case 1: string = "AmigaOS"; break;
case 2: string = "Windows"; break;
case 3: string = "MacOS"; break;
default:
return false;
}
DecorAddOn *newDecor = _FindDecor(string);
if (newDecor) {
fCurrentDecor = newDecor;
return true;
}
return false;
}
BString
DecorManager::GetDecoratorName(int32 index)
DecorManager::GetCurrentDecorator() const
{
DecorAddOn *decor = fDecorList.ItemAt(index);
if (decor)
return decor->Name();
return BString("");
return fCurrentDecorPath.String();
}
void
DecorManager::_EmptyList()
status_t
DecorManager::SetDecorator(BString path, Desktop* desktop)
{
for (int32 i = 1; i < fDecorList.CountItems(); i++) {
unload_add_on(fDecorList.ItemAt(i)->ImageID());
delete fDecorList.ItemAt(i);
status_t error = B_OK;
DecorAddOn* newDecor = _LoadDecor(path, error);
if (newDecor == NULL)
return error == B_OK ? B_ERROR : error;
DecorAddOn* oldDecor = fCurrentDecor;
BString oldPath = fCurrentDecorPath;
image_id oldImage = fCurrentDecor->ImageID();
fCurrentDecor = newDecor;
fCurrentDecorPath = path.String();
if (desktop->ReloadDecor()) {
// now safe to unload all old decorator data
// saves us from deleting oldDecor...
unload_add_on(oldImage);
_SaveSettingsToDisk();
return B_OK;
}
fDecorList.MakeEmpty();
fDecorList.AddItem(&fDefaultDecorAddOn);
// TODO: unloading the newDecor and its image
// problem is we don't know how many windows failed... or why they failed...
syslog(LOG_WARNING,
"app_server:DecorManager:SetDecorator:\"%s\" *partly* failed\n",
fCurrentDecorPath.String());
fCurrentDecor = &fDefaultDecorAddOn;
fCurrentDecor = oldDecor;
fCurrentDecorPath = oldPath;
return B_ERROR;
}
DecorAddOn*
DecorManager::_FindDecor(BString name)
DecorManager::_LoadDecor(BString _path, status_t& error )
{
if (!name)
return NULL;
for (int32 i = 0; i < fDecorList.CountItems(); i++) {
DecorAddOn* decor = fDecorList.ItemAt(i);
if (decor->Name() == name)
return decor;
if (_path == "Default") {
error = B_OK;
return &fDefaultDecor;
}
return NULL;
BEntry entry(_path.String(), true);
if (!entry.Exists()) {
error = B_ENTRY_NOT_FOUND;
return NULL;
}
BPath path(&entry);
image_id image = load_add_on(path.Path());
if (image < 0) {
error = B_BAD_IMAGE_ID;
return NULL;
}
create_decor_addon* createFunc;
if (get_image_symbol(image, "instantiate_decor_addon", B_SYMBOL_TYPE_TEXT,
(void**)&createFunc) != B_OK) {
unload_add_on(image);
error = B_MISSING_SYMBOL;
return NULL;
}
char name[B_FILE_NAME_LENGTH];
entry.GetName(name);
DecorAddOn* newDecor = createFunc(image, name);
if (newDecor == NULL || newDecor->InitCheck() != B_OK) {
unload_add_on(image);
error = B_ERROR;
return NULL;
}
return newDecor;
}
@ -338,12 +331,15 @@ DecorManager::_LoadSettingsFromDisk()
BMessage settings;
if (settings.Unflatten(&file) == B_OK) {
BString itemtext;
if (settings.FindString("decorator", &itemtext) == B_OK) {
DecorAddOn* decor = _FindDecor(itemtext);
if (decor) {
BString itemPath;
if (settings.FindString("decorator", &itemPath) == B_OK) {
status_t error = B_OK;
DecorAddOn* decor = _LoadDecor(itemPath, error);
if (decor != NULL) {
fCurrentDecor = decor;
return true;
} else {
//TODO: do something with the reported error
}
}
}
@ -371,7 +367,7 @@ DecorManager::_SaveSettingsToDisk()
return false;
BMessage settings;
if (settings.AddString("decorator", fCurrentDecor->Name()) != B_OK)
if (settings.AddString("decorator", fCurrentDecorPath.String()) != B_OK)
return false;
if (settings.Flatten(&file) != B_OK)
return false;

View File

@ -14,10 +14,11 @@
#include <String.h>
#include <Locker.h>
#include <ObjectList.h>
#include <Entry.h>
#include <DecorInfo.h>
#include "Decorator.h"
class DecorInfo;
class Desktop;
class DesktopListener;
class DrawingEngine;
@ -28,6 +29,9 @@ class WindowBehaviour;
typedef BObjectList<DesktopListener> DesktopListenerList;
// special name to test for use of non-fs-tied default decorator
// this just keeps things clean and simple is all
class DecorAddOn {
public:
DecorAddOn(image_id id, const char* name);
@ -35,68 +39,57 @@ public:
virtual status_t InitCheck() const;
image_id ImageID() const { return fImageID; }
BString Name() const { return fName; }
image_id ImageID() const { return fImageID; }
Decorator* AllocateDecorator(Desktop* desktop,
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 WindowBehaviour* AllocateWindowBehaviour(Window* window);
virtual const DesktopListenerList& GetDesktopListeners();
virtual const DesktopListenerList& GetDesktopListeners();
protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
BRect rect, window_look look, uint32 flags);
DesktopListenerList fDesktopListeners;
DesktopListenerList fDesktopListeners;
private:
image_id fImageID;
BString fName;
image_id fImageID;
BString fName;
};
class DecorManager
{
class DecorManager {
public:
DecorManager();
~DecorManager();
DecorManager();
~DecorManager();
void RescanDecorators();
Decorator* AllocateDecorator(Window *window);
WindowBehaviour* AllocateWindowBehaviour(Window *window);
void CleanupForWindow(Window *window);
Decorator* AllocateDecorator(Desktop* desktop,
DrawingEngine* engine,
BRect rect,
const char* title, window_look look,
uint32 flags);
WindowBehaviour* AllocateWindowBehaviour(Window* window);
const DesktopListenerList& GetDesktopListeners();
status_t PreviewDecorator(BString path, Window *window);
int32 CountDecorators() const;
const DesktopListenerList& GetDesktopListeners();
int32 GetDecorator() const;
bool SetDecorator(int32 index, Desktop* desktop);
bool SetR5Decorator(int32 value);
BString GetDecoratorName(int32 index);
// TODO: Implement this method once the rest of the necessary infrastructure
// is in place
//status_t GetPreview(int32 index, ServerBitmap *bitmap);
BString GetCurrentDecorator() const;
status_t SetDecorator(BString path, Desktop *desktop);
private:
void _EmptyList();
DecorAddOn* _FindDecor(BString name);
DecorAddOn* _LoadDecor(BString path, status_t &error);
bool _LoadSettingsFromDisk();
bool _SaveSettingsToDisk();
bool _LoadSettingsFromDisk();
bool _SaveSettingsToDisk();
private:
DecorAddOn fDefaultDecor;
DecorAddOn* fCurrentDecor;
DecorAddOn* fPreviewDecor;
BObjectList<DecorAddOn> fDecorList;
DecorAddOn fDefaultDecorAddOn;
DecorAddOn* fCurrentDecor;
Window* fPreviewWindow;
BString fCurrentDecorPath;
};
extern DecorManager gDecorManager;

View File

@ -17,7 +17,6 @@
#include "Desktop.h"
#include <stdio.h>
#include <string.h>
#include <syslog.h>
@ -2044,11 +2043,13 @@ Desktop::RedrawBackground()
}
void
bool
Desktop::ReloadDecor()
{
AutoWriteLocker _(fWindowLock);
bool returnValue = true;
// TODO it is assumed all listeners are registered by one decor
// unregister old listeners
const DesktopListenerDLList& currentListeners = GetDesktopListenerList();
@ -2058,16 +2059,19 @@ Desktop::ReloadDecor()
for (Window* window = fAllWindows.FirstWindow(); window != NULL;
window = window->NextWindow(kAllWindowList)) {
BRegion oldBorder;
window->GetBorderRegion(&oldBorder);
BRegion oldBorder;
window->GetBorderRegion(&oldBorder);
window->ReloadDecor();
if (!window->ReloadDecor()) {
// prevent unloading previous add-on
returnValue = false;
}
BRegion border;
window->GetBorderRegion(&border);
BRegion border;
window->GetBorderRegion(&border);
border.Include(&oldBorder);
RebuildAndRedrawAfterWindowChange(window, border);
border.Include(&oldBorder);
RebuildAndRedrawAfterWindowChange(window, border);
}
// register new listeners
@ -2075,6 +2079,8 @@ Desktop::ReloadDecor()
= gDecorManager.GetDesktopListeners();
for (int i = 0; i < newListeners.CountItems(); i++)
RegisterListener(newListeners.ItemAt(i));
return returnValue;
}

View File

@ -221,7 +221,7 @@ public:
void Redraw();
void RedrawBackground();
void ReloadDecor();
bool ReloadDecor();
BRegion& BackgroundRegion()
{ return fBackgroundRegion; }

View File

@ -162,10 +162,6 @@ string_for_message_code(uint32 code, BString& string)
CODE(AS_SET_UI_COLOR);
CODE(AS_SET_DECORATOR);
CODE(AS_GET_DECORATOR);
case AS_R5_SET_DECORATOR:
string = "AS_R5_SET_DECORATOR"; break;
CODE(AS_COUNT_DECORATORS);
CODE(AS_GET_DECORATOR_NAME);
CODE(AS_SET_WORKSPACE_LAYOUT);
CODE(AS_GET_WORKSPACE_LAYOUT);

View File

@ -648,68 +648,29 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
case AS_SET_DECORATOR:
{
// Attached Data:
// int32 the index of the decorator to use
// path to decorator add-on
int32 index;
link.Read<int32>(&index);
if (gDecorManager.SetDecorator(index, fDesktop))
fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
break;
}
BString path;
link.ReadString(path);
case AS_COUNT_DECORATORS:
{
fLink.StartMessage(B_OK);
fLink.Attach<int32>(gDecorManager.CountDecorators());
status_t error = gDecorManager.SetDecorator(path, fDesktop);
fLink.Attach<status_t>(error);
fLink.Flush();
if (error == B_OK)
fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
break;
}
case AS_GET_DECORATOR:
{
fLink.StartMessage(B_OK);
fLink.Attach<int32>(gDecorManager.GetDecorator());
fLink.AttachString(gDecorManager.GetCurrentDecorator().String());
fLink.Flush();
break;
}
case AS_GET_DECORATOR_NAME:
{
int32 index;
link.Read<int32>(&index);
BString str(gDecorManager.GetDecoratorName(index));
if (str.CountChars() > 0) {
fLink.StartMessage(B_OK);
fLink.AttachString(str.String());
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_R5_SET_DECORATOR:
{
// Sort of supports Tracker's nifty Easter Egg. It was easy to do
// and it's kind of neat, so why not?
// Attached Data:
// int32 value of the decorator to use
// 0: BeOS
// 1: Amiga
// 2: Windows
// 3: MacOS
int32 decindex = 0;
link.Read<int32>(&decindex);
if (gDecorManager.SetR5Decorator(decindex))
fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
break;
}
case AS_CREATE_BITMAP:
{
STRACE(("ServerApp %s: Received BBitmap creation request\n",

View File

@ -129,8 +129,7 @@ Window::Window(const BRect& frame, const char *name,
SetFlags(flags, NULL);
if (fLook != B_NO_BORDER_WINDOW_LOOK) {
fDecorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine,
frame, name, fLook, fFlags);
fDecorator = gDecorManager.AllocateDecorator(this);
if (fDecorator) {
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight,
&fMaxWidth, &fMaxHeight);
@ -172,8 +171,9 @@ Window::~Window()
delete fWindowBehaviour;
delete fDecorator;
delete fDrawingEngine;
gDecorManager.CleanupForWindow(this);
}
@ -549,18 +549,18 @@ Window::ReloadDecor()
::Decorator* decorator = NULL;
WindowBehaviour* windowBehaviour = NULL;
if (fLook != B_NO_BORDER_WINDOW_LOOK) {
// we need a new decorator
decorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine,
Frame(), Title(), fLook, fFlags);
if (!decorator)
decorator = gDecorManager.AllocateDecorator(this);
if (decorator == NULL)
return false;
if (IsFocus())
decorator->SetFocus(true);
}
windowBehaviour = gDecorManager.AllocateWindowBehaviour(this);
if (!windowBehaviour) {
if (windowBehaviour == NULL) {
delete decorator;
return false;
}
@ -1108,6 +1108,14 @@ Window::TabLocation() const
bool
Window::SetDecoratorSettings(const BMessage& settings, BRegion& dirty)
{
if (settings.what == 'prVu') {
// 'prVu' == preview a decorator!
BString path;
if (settings.FindString("preview", &path) == B_OK)
return gDecorManager.PreviewDecorator(path, this) == B_OK;
return false;
}
if (fDecorator)
return fDecorator->SetSettings(settings, &dirty);
return false;
@ -1142,8 +1150,7 @@ Window::SetLook(window_look look, BRegion* updateRegion)
{
if (fDecorator == NULL && look != B_NO_BORDER_WINDOW_LOOK) {
// we need a new decorator
fDecorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine,
Frame(), Title(), fLook, fFlags);
fDecorator = gDecorManager.AllocateDecorator(this);
if (IsFocus())
fDecorator->SetFocus(true);
}

View File

@ -375,6 +375,8 @@ protected:
int32 fMaxHeight;
int32 fWorkspacesViewCount;
friend class DecorManager;
};
#endif // WINDOW_H