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
+129
View File
@@ -0,0 +1,129 @@
/*
* Public domain source code.
*
* Author:
* Joseph "looncraz" Groover <[email protected]>
*/
#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
@@ -93,13 +93,6 @@ BeDecorAddOn::BeDecorAddOn(image_id id, const char* name)
} }
float
BeDecorAddOn::Version()
{
return 1.00;
}
Decorator* Decorator*
BeDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect, BeDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags) window_look look, uint32 flags)
@@ -24,8 +24,6 @@ class BeDecorAddOn : public DecorAddOn {
public: public:
BeDecorAddOn(image_id id, const char* name); BeDecorAddOn(image_id id, const char* name);
float Version();
protected: protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings, virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
BRect rect, window_look look, uint32 flags); BRect rect, window_look look, uint32 flags);
@@ -7,7 +7,10 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UsePrivateHeaders app shared interface graphics ; UsePrivateHeaders app shared interface graphics ;
UseLibraryHeaders agg ; UseLibraryHeaders agg ;
AddResources ClassicBe : resources.rdef ;
Addon ClassicBe : Addon ClassicBe :
BeDecorator.cpp BeDecorator.cpp
: be <nogrist>app_server $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) : be <nogrist>app_server $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++)
: resources.rdef
; ;
@@ -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
};
@@ -7,6 +7,8 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UsePrivateHeaders app shared interface graphics ; UsePrivateHeaders app shared interface graphics ;
UseLibraryHeaders agg ; UseLibraryHeaders agg ;
AddResources MacDecorator : resources.rdef ;
Addon MacDecorator : Addon MacDecorator :
MacDecorator.cpp MacDecorator.cpp
: be <nogrist>app_server $(TARGET_LIBSTDC++) : be <nogrist>app_server $(TARGET_LIBSTDC++)
@@ -38,13 +38,6 @@ MacDecorAddOn::MacDecorAddOn(image_id id, const char* name)
} }
float
MacDecorAddOn::Version()
{
return 1.00;
}
Decorator* Decorator*
MacDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect, MacDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags) window_look look, uint32 flags)
@@ -14,8 +14,6 @@ class MacDecorAddOn : public DecorAddOn {
public: public:
MacDecorAddOn(image_id id, const char* name); MacDecorAddOn(image_id id, const char* name);
float Version();
protected: protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings, virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
BRect rect, window_look look, uint32 flags); BRect rect, window_look look, uint32 flags);
@@ -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
};
@@ -8,6 +8,8 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UseFreeTypeHeaders ; UseFreeTypeHeaders ;
AddResources SATDecorator : resources.rdef ;
Addon SATDecorator : Addon SATDecorator :
SATDecorator.cpp SATDecorator.cpp
SATGroup.cpp SATGroup.cpp
@@ -66,13 +66,6 @@ SATDecorAddOn::InitCheck() const
} }
float
SATDecorAddOn::Version()
{
return 0.1;
}
Decorator* Decorator*
SATDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect, SATDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags) window_look look, uint32 flags)
@@ -19,7 +19,6 @@ public:
SATDecorAddOn(image_id id, const char* name); SATDecorAddOn(image_id id, const char* name);
virtual status_t InitCheck() const; virtual status_t InitCheck() const;
float Version();
protected: protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings, virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
@@ -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
};
@@ -7,6 +7,8 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
UsePrivateHeaders app shared interface graphics ; UsePrivateHeaders app shared interface graphics ;
UseLibraryHeaders agg ; UseLibraryHeaders agg ;
AddResources WinDecorator : resources.rdef ;
Addon WinDecorator : Addon WinDecorator :
WinDecorator.cpp WinDecorator.cpp
: be <nogrist>app_server $(TARGET_LIBSTDC++) : be <nogrist>app_server $(TARGET_LIBSTDC++)
@@ -37,13 +37,6 @@ WinDecorAddOn::WinDecorAddOn(image_id id, const char* name)
} }
float
WinDecorAddOn::Version()
{
return 1.00;
}
Decorator* Decorator*
WinDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect, WinDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
window_look look, uint32 flags) window_look look, uint32 flags)
@@ -14,7 +14,6 @@ class WinDecorAddOn : public DecorAddOn {
public: public:
WinDecorAddOn(image_id id, const char* name); WinDecorAddOn(image_id id, const char* name);
float Version();
protected: protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings, virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
@@ -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
};
+1 -1
View File
@@ -102,7 +102,6 @@ StdBinCommands
play.cpp play.cpp
quit.cpp quit.cpp
roster.cpp roster.cpp
setdecor.cpp
setversion.cpp setversion.cpp
trash.cpp trash.cpp
version.cpp version.cpp
@@ -123,6 +122,7 @@ StdBinCommands
hey.cpp hey.cpp
reindex.cpp reindex.cpp
resattr.cpp resattr.cpp
setdecor.cpp
settype.cpp settype.cpp
spybmessage.cpp spybmessage.cpp
urlwrapper.cpp urlwrapper.cpp
+192 -54
View File
@@ -1,4 +1,5 @@
/* /*
* Copyright 2011, Joseph "looncraz" Groover, looncraz@satx.rr.com
* Copyright 2007, François Revol, revol@free.fr. * Copyright 2007, François Revol, revol@free.fr.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
*/ */
@@ -7,87 +8,224 @@
#include <stdio.h> #include <stdio.h>
#include <Application.h> #include <Application.h>
#include <Bitmap.h>
#include <InterfaceDefs.h> #include <InterfaceDefs.h>
#include <String.h> #include <String.h>
#include <Window.h>
#include <View.h>
class BBitmap; #include <private/interface/DecorInfo.h>
namespace BPrivate {
int32 count_decorators(void); void
int32 get_decorator(void); print_decor_info_header()
status_t get_decorator_name(const int32 &index, BString &name); {
status_t get_decorator_preview(const int32 &index, BBitmap *bitmap); printf(" Name License\t Description\n");
status_t set_decorator(const int32 &index); 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) { if (argc < 2) {
printf("usage: %s [-l|-c|decorname]\n", argv[0]); printf("usage: %s [-l|-c|decorname]\n", argv[0]);
printf("\t-l: list available decors\n"); 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-c: give current decor name\n");
printf("\t-i: detailed information about decor\n");
printf("\t-p: see preview window\n");
return 1; 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"); 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 // we want the list
if (!strcmp(argv[1], "-l")) { if (!strcmp(argv[1], "-l")) {
int32 i, count; // Print default decorator:
count = count_decorators(); print_decor_info_header();
if (count < 0) { int32 count = util->CountDecorators();
fprintf(stderr, "error counting decorators: %s\n", strerror(count)); for (int32 i = 0; i < count; ++i) {
return 1; decor = util->DecoratorAt(i);
} if (decor == NULL) {
for (i = 0; i < count; i++) { fprintf(stderr, "error NULL entry @ %li / %li - BUG BUG BUG\n",
BString name; i, count);
err = get_decorator_name(i, name); // return 2 to track DecorInfoUtility errors
if (err < 0) return 2;
continue; }
printf("%s\n", name.String()); print_decor_summary(decor, util->IsCurrentDecorator(decor));
} }
return 0; return 0;
} }
// we want the current one
// we want the current decorator
if (!strcmp(argv[1], "-c")) { if (!strcmp(argv[1], "-c")) {
int32 i; decor = util->CurrentDecorator();
BString name;
i = get_decorator(); if (decor == NULL) {
if (i < 0) { fprintf(stderr, "Unable to determine current decorator, sorry! - "
fprintf(stderr, "error getting current decorator: %s\n", strerror(i)); "BUG BUG BUG\n");
return 1; return 2;
} }
err = get_decorator_name(i, name);
if (err < 0) { print_decor_info_header();
fprintf(stderr, "error getting name of decorator: %s\n", strerror(err)); print_decor_summary(decor, true);
return 1;
}
printf("%s\n", name.String());
return 0; 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 // we want to change it
int32 i, count; decoratorName = "";
count = count_decorators(); for (int i = 1; i < argc; ++i)
if (count < 0) { decoratorName << argv[i] << " ";
fprintf(stderr, "error counting decorators: %s\n", strerror(count)); decoratorName.RemoveLast(" ");
decor = util->FindDecorator(decoratorName.String());
if (decor == NULL) {
fprintf(stderr, "no such decorator \"%s\"\n", decoratorName.String());
return 1; return 1;
} }
for (i = 0; i < count; i++) {
BString name; if (util->IsCurrentDecorator(decor)) {
err = get_decorator_name(i, name); printf("\"%s\" is already the current decorator\n",
if (err < 0) decor->Name().String());
continue; return 0;
if (name == argv[1]) {
err = set_decorator(i);
if (err < 0) {
fprintf(stderr, "error setting decorator: %s\n", strerror(err));
return 1;
}
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;
} }
+594
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;
}
+38 -99
View File
@@ -32,10 +32,12 @@
#include <ScrollBar.h> #include <ScrollBar.h>
#include <String.h> #include <String.h>
#include <TextView.h> #include <TextView.h>
#include <Window.h>
#include <ApplicationPrivate.h> #include <ApplicationPrivate.h>
#include <AppServerLink.h> #include <AppServerLink.h>
#include <ColorConversion.h> #include <ColorConversion.h>
#include <DecorInfo.h>
#include <DefaultColors.h> #include <DefaultColors.h>
#include <InputServerTypes.h> #include <InputServerTypes.h>
#include <input_globals.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 { namespace BPrivate {
/*! \brief queries the server for the number of available decorators /*! \brief queries the server for the current decorator
\return the number of available decorators \param ref entry_ref into which to store current decorator's location
\return boolean true/false
*/ */
int32 bool
count_decorators(void) get_decorator(BString& path)
{
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)
{ {
BPrivate::AppServerLink link; BPrivate::AppServerLink link;
link.StartMessage(AS_GET_DECORATOR); link.StartMessage(AS_GET_DECORATOR);
int32 code; int32 code;
int32 index = -1; if (link.FlushWithReply(code) != B_OK || code != B_OK)
if (link.FlushWithReply(code) == B_OK && code == B_OK) return false;
link.Read<int32>(&index);
return index; return link.ReadString(path) == B_OK;
}
/*! \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;
} }
/*! \brief Private function which sets the window decorator for the system. /*! \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 status_t
set_decorator(const int32 &index) set_decorator(const BString& path)
{ {
if (index < 0)
return B_BAD_VALUE;
BPrivate::AppServerLink link; BPrivate::AppServerLink link;
link.StartMessage(AS_SET_DECORATOR); link.StartMessage(AS_SET_DECORATOR);
link.Attach<int32>(index);
link.AttachString(path.String());
link.Flush(); 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);
} }
+1
View File
@@ -49,6 +49,7 @@ MergeObject <libbe>interface_kit.o :
ColorTools.cpp ColorTools.cpp
Control.cpp Control.cpp
ControlLook.cpp ControlLook.cpp
DecorInfo.cpp
Deskbar.cpp Deskbar.cpp
Dragger.cpp Dragger.cpp
Font.cpp Font.cpp
+17 -20
View File
@@ -20,8 +20,11 @@
#include <Path.h> #include <Path.h>
#include <SpaceLayoutItem.h> #include <SpaceLayoutItem.h>
#include <private/interface/DecorInfo.h>
#include <stdio.h> #include <stdio.h>
#include "APRWindow.h" #include "APRWindow.h"
#include "defs.h" #include "defs.h"
#include "ColorWell.h" #include "ColorWell.h"
@@ -35,39 +38,33 @@
#define COLOR_DROPPED 'cldp' #define COLOR_DROPPED 'cldp'
#define DECORATOR_CHANGED 'dcch' #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) APRView::APRView(const char* name, uint32 flags)
: BView(name, flags), :
BView(name, flags),
fDefaultSet(ColorSet::DefaultColorSet()), fDefaultSet(ColorSet::DefaultColorSet()),
fDecorMenu(NULL) fDecorMenu(NULL),
fDecorUtil(new DecorInfoUtility(false))
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
#if 0 #if 0
fDecorMenu = new BMenu("Window Style"); fDecorMenu = new BMenu("Window Style");
int32 decorCount = BPrivate::count_decorators(); int32 decorCount = fDecorUtil->CountDecorators();
DecorInfo* decor = NULL;
if (decorCount > 1) { if (decorCount > 1) {
for (int32 i = 0; i < decorCount; i++) { for (int32 i = 0; i < decorCount; i++) {
BString name; decor = fDecorUtil->GetDecorator(i);
BPrivate::get_decorator_name(i, name); if (!decor)
if (name.CountChars() < 1)
continue; continue;
fDecorMenu->AddItem(new BMenuItem(name.String(), fDecorMenu->AddItem(new BMenuItem(decor->Name().String(),
new BMessage(DECORATOR_CHANGED))); new BMessage(DECORATOR_CHANGED)));
} }
BMenuField *field = new BMenuField("Window Style", fDecorMenu); BMenuField* field = new BMenuField("Window Style", fDecorMenu);
// TODO: use this menu field. // TODO: use this menu field.
} }
BMenuItem *marked = fDecorMenu->ItemAt(BPrivate::get_decorator()); BMenuItem* marked = fDecorMenu->ItemAt(fDecorUtil->IndexOfCurrentDecorator());
if (marked) if (marked)
marked->SetMarked(true); marked->SetMarked(true);
else { else {
@@ -156,7 +153,7 @@ APRView::MessageReceived(BMessage *msg)
int32 index = fDecorMenu->IndexOf(fDecorMenu->FindMarked()); int32 index = fDecorMenu->IndexOf(fDecorMenu->FindMarked());
#ifdef HAIKU_TARGET_PLATFORM_HAIKU #ifdef HAIKU_TARGET_PLATFORM_HAIKU
if (index >= 0) if (index >= 0)
BPrivate::set_decorator(index); fDecorUtil->SetDecorator(index);
#endif #endif
break; break;
} }
@@ -207,7 +204,7 @@ APRView::MessageReceived(BMessage *msg)
if (item) { if (item) {
item->SetMarked(true); item->SetMarked(true);
#ifdef HAIKU_TARGET_PLATFORM_HAIKU #ifdef HAIKU_TARGET_PLATFORM_HAIKU
BPrivate::set_decorator(fDecorMenu->IndexOf(item)); fDecorUtil->SetDecorator(fDecorMenu->IndexOf(item));
#endif #endif
} }
} }
+2
View File
@@ -28,6 +28,7 @@
#include "ColorSet.h" #include "ColorSet.h"
class ColorWell; class ColorWell;
class DecorInfoUtility;
class APRWindow; class APRWindow;
class APRView : public BView class APRView : public BView
@@ -62,6 +63,7 @@ protected:
ColorSet fDefaultSet; ColorSet fDefaultSet;
BMenu *fDecorMenu; BMenu *fDecorMenu;
DecorInfoUtility*fDecorUtil;
}; };
#endif #endif
+154 -158
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. * Distributed under the terms of the MIT license.
* *
* Author: * Author:
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
* Clemens Zeidler <haiku@clemens-zeidler.de> * Clemens Zeidler <haiku@clemens-zeidler.de>
* Joseph Groover <looncraz@satx.rr.com>
*/ */
#include "DecorManager.h" #include "DecorManager.h"
@@ -44,7 +45,6 @@ DecorAddOn::DecorAddOn(image_id id, const char* name)
DecorAddOn::~DecorAddOn() DecorAddOn::~DecorAddOn()
{ {
} }
@@ -70,6 +70,7 @@ DecorAddOn::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
if (!decorator) if (!decorator)
return NULL; return NULL;
decorator->SetDrawingEngine(engine); decorator->SetDrawingEngine(engine);
decorator->SetTitle(title); decorator->SetTitle(title);
@@ -104,87 +105,23 @@ DecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
DecorManager::DecorManager() DecorManager::DecorManager()
: :
fDefaultDecorAddOn(-1, "Default"), fDefaultDecor(-1, "Default"),
fCurrentDecor(NULL) 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(); _LoadSettingsFromDisk();
if (!fCurrentDecor)
fCurrentDecor = fDecorList.ItemAt(0L);
} }
DecorManager::~DecorManager() DecorManager::~DecorManager()
{ {
_EmptyList();
} }
void Decorator*
DecorManager::RescanDecorators() DecorManager::AllocateDecorator(Window* window)
{
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)
{ {
// Create a new instance of the current decorator. // Create a new instance of the current decorator.
// Ownership is that of the caller // Ownership is that of the caller
@@ -195,8 +132,20 @@ DecorManager::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
return NULL; return NULL;
} }
return fCurrentDecor->AllocateDecorator(desktop, engine, rect, title, // Are we previewing a specific decorator?
look, flags); 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& const DesktopListenerList&
DecorManager::GetDesktopListeners() 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 BString
DecorManager::GetDecoratorName(int32 index) DecorManager::GetCurrentDecorator() const
{ {
DecorAddOn *decor = fDecorList.ItemAt(index); return fCurrentDecorPath.String();
if (decor)
return decor->Name();
return BString("");
} }
void status_t
DecorManager::_EmptyList() DecorManager::SetDecorator(BString path, Desktop* desktop)
{ {
for (int32 i = 1; i < fDecorList.CountItems(); i++) { status_t error = B_OK;
unload_add_on(fDecorList.ItemAt(i)->ImageID()); DecorAddOn* newDecor = _LoadDecor(path, error);
delete fDecorList.ItemAt(i); 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(); // TODO: unloading the newDecor and its image
fDecorList.AddItem(&fDefaultDecorAddOn); // 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* DecorAddOn*
DecorManager::_FindDecor(BString name) DecorManager::_LoadDecor(BString _path, status_t& error )
{ {
if (!name) if (_path == "Default") {
return NULL; error = B_OK;
return &fDefaultDecor;
for (int32 i = 0; i < fDecorList.CountItems(); i++) {
DecorAddOn* decor = fDecorList.ItemAt(i);
if (decor->Name() == name)
return decor;
} }
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; BMessage settings;
if (settings.Unflatten(&file) == B_OK) { if (settings.Unflatten(&file) == B_OK) {
BString itemtext; BString itemPath;
if (settings.FindString("decorator", &itemtext) == B_OK) { if (settings.FindString("decorator", &itemPath) == B_OK) {
DecorAddOn* decor = _FindDecor(itemtext); status_t error = B_OK;
if (decor) { DecorAddOn* decor = _LoadDecor(itemPath, error);
if (decor != NULL) {
fCurrentDecor = decor; fCurrentDecor = decor;
return true; return true;
} else {
//TODO: do something with the reported error
} }
} }
} }
@@ -371,7 +367,7 @@ DecorManager::_SaveSettingsToDisk()
return false; return false;
BMessage settings; BMessage settings;
if (settings.AddString("decorator", fCurrentDecor->Name()) != B_OK) if (settings.AddString("decorator", fCurrentDecorPath.String()) != B_OK)
return false; return false;
if (settings.Flatten(&file) != B_OK) if (settings.Flatten(&file) != B_OK)
return false; return false;
+31 -38
View File
@@ -14,10 +14,11 @@
#include <String.h> #include <String.h>
#include <Locker.h> #include <Locker.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <Entry.h>
#include <DecorInfo.h>
#include "Decorator.h" #include "Decorator.h"
class DecorInfo;
class Desktop; class Desktop;
class DesktopListener; class DesktopListener;
class DrawingEngine; class DrawingEngine;
@@ -28,6 +29,9 @@ class WindowBehaviour;
typedef BObjectList<DesktopListener> DesktopListenerList; 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 { class DecorAddOn {
public: public:
DecorAddOn(image_id id, const char* name); DecorAddOn(image_id id, const char* name);
@@ -35,68 +39,57 @@ public:
virtual status_t InitCheck() const; virtual status_t InitCheck() const;
image_id ImageID() const { return fImageID; } image_id ImageID() const { return fImageID; }
BString Name() const { return fName; }
Decorator* AllocateDecorator(Desktop* desktop, Decorator* AllocateDecorator(Desktop* desktop,
DrawingEngine* engine, BRect rect, DrawingEngine* engine, BRect rect,
const char* title, window_look look, const char* title, window_look look,
uint32 flags); 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: protected:
virtual Decorator* _AllocateDecorator(DesktopSettings& settings, virtual Decorator* _AllocateDecorator(DesktopSettings& settings,
BRect rect, window_look look, uint32 flags); BRect rect, window_look look, uint32 flags);
DesktopListenerList fDesktopListeners; DesktopListenerList fDesktopListeners;
private: private:
image_id fImageID; image_id fImageID;
BString fName; BString fName;
}; };
class DecorManager class DecorManager {
{
public: public:
DecorManager(); DecorManager();
~DecorManager(); ~DecorManager();
void RescanDecorators(); Decorator* AllocateDecorator(Window *window);
WindowBehaviour* AllocateWindowBehaviour(Window *window);
void CleanupForWindow(Window *window);
Decorator* AllocateDecorator(Desktop* desktop, status_t PreviewDecorator(BString path, Window *window);
DrawingEngine* engine,
BRect rect,
const char* title, window_look look,
uint32 flags);
WindowBehaviour* AllocateWindowBehaviour(Window* window);
const DesktopListenerList& GetDesktopListeners();
int32 CountDecorators() const; const DesktopListenerList& GetDesktopListeners();
int32 GetDecorator() const; BString GetCurrentDecorator() const;
bool SetDecorator(int32 index, Desktop* desktop); status_t SetDecorator(BString path, 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);
private: private:
void _EmptyList(); DecorAddOn* _LoadDecor(BString path, status_t &error);
DecorAddOn* _FindDecor(BString name); bool _LoadSettingsFromDisk();
bool _SaveSettingsToDisk();
bool _LoadSettingsFromDisk(); private:
bool _SaveSettingsToDisk(); DecorAddOn fDefaultDecor;
DecorAddOn* fCurrentDecor;
DecorAddOn* fPreviewDecor;
BObjectList<DecorAddOn> fDecorList; Window* fPreviewWindow;
DecorAddOn fDefaultDecorAddOn; BString fCurrentDecorPath;
DecorAddOn* fCurrentDecor;
}; };
extern DecorManager gDecorManager; extern DecorManager gDecorManager;
+15 -9
View File
@@ -17,7 +17,6 @@
#include "Desktop.h" #include "Desktop.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <syslog.h> #include <syslog.h>
@@ -2044,11 +2043,13 @@ Desktop::RedrawBackground()
} }
void bool
Desktop::ReloadDecor() Desktop::ReloadDecor()
{ {
AutoWriteLocker _(fWindowLock); AutoWriteLocker _(fWindowLock);
bool returnValue = true;
// TODO it is assumed all listeners are registered by one decor // TODO it is assumed all listeners are registered by one decor
// unregister old listeners // unregister old listeners
const DesktopListenerDLList& currentListeners = GetDesktopListenerList(); const DesktopListenerDLList& currentListeners = GetDesktopListenerList();
@@ -2058,16 +2059,19 @@ Desktop::ReloadDecor()
for (Window* window = fAllWindows.FirstWindow(); window != NULL; for (Window* window = fAllWindows.FirstWindow(); window != NULL;
window = window->NextWindow(kAllWindowList)) { window = window->NextWindow(kAllWindowList)) {
BRegion oldBorder; BRegion oldBorder;
window->GetBorderRegion(&oldBorder); window->GetBorderRegion(&oldBorder);
window->ReloadDecor(); if (!window->ReloadDecor()) {
// prevent unloading previous add-on
returnValue = false;
}
BRegion border; BRegion border;
window->GetBorderRegion(&border); window->GetBorderRegion(&border);
border.Include(&oldBorder); border.Include(&oldBorder);
RebuildAndRedrawAfterWindowChange(window, border); RebuildAndRedrawAfterWindowChange(window, border);
} }
// register new listeners // register new listeners
@@ -2075,6 +2079,8 @@ Desktop::ReloadDecor()
= gDecorManager.GetDesktopListeners(); = gDecorManager.GetDesktopListeners();
for (int i = 0; i < newListeners.CountItems(); i++) for (int i = 0; i < newListeners.CountItems(); i++)
RegisterListener(newListeners.ItemAt(i)); RegisterListener(newListeners.ItemAt(i));
return returnValue;
} }
+1 -1
View File
@@ -221,7 +221,7 @@ public:
void Redraw(); void Redraw();
void RedrawBackground(); void RedrawBackground();
void ReloadDecor(); bool ReloadDecor();
BRegion& BackgroundRegion() BRegion& BackgroundRegion()
{ return fBackgroundRegion; } { return fBackgroundRegion; }
@@ -162,10 +162,6 @@ string_for_message_code(uint32 code, BString& string)
CODE(AS_SET_UI_COLOR); CODE(AS_SET_UI_COLOR);
CODE(AS_SET_DECORATOR); CODE(AS_SET_DECORATOR);
CODE(AS_GET_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_SET_WORKSPACE_LAYOUT);
CODE(AS_GET_WORKSPACE_LAYOUT); CODE(AS_GET_WORKSPACE_LAYOUT);
+10 -49
View File
@@ -648,68 +648,29 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
case AS_SET_DECORATOR: case AS_SET_DECORATOR:
{ {
// Attached Data: // Attached Data:
// int32 the index of the decorator to use // path to decorator add-on
int32 index; BString path;
link.Read<int32>(&index); link.ReadString(path);
if (gDecorManager.SetDecorator(index, fDesktop))
fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
break;
}
case AS_COUNT_DECORATORS: status_t error = gDecorManager.SetDecorator(path, fDesktop);
{
fLink.StartMessage(B_OK); fLink.Attach<status_t>(error);
fLink.Attach<int32>(gDecorManager.CountDecorators());
fLink.Flush(); fLink.Flush();
if (error == B_OK)
fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
break; break;
} }
case AS_GET_DECORATOR: case AS_GET_DECORATOR:
{ {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.Attach<int32>(gDecorManager.GetDecorator()); fLink.AttachString(gDecorManager.GetCurrentDecorator().String());
fLink.Flush(); fLink.Flush();
break; 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: case AS_CREATE_BITMAP:
{ {
STRACE(("ServerApp %s: Received BBitmap creation request\n", STRACE(("ServerApp %s: Received BBitmap creation request\n",
+16 -9
View File
@@ -129,8 +129,7 @@ Window::Window(const BRect& frame, const char *name,
SetFlags(flags, NULL); SetFlags(flags, NULL);
if (fLook != B_NO_BORDER_WINDOW_LOOK) { if (fLook != B_NO_BORDER_WINDOW_LOOK) {
fDecorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine, fDecorator = gDecorManager.AllocateDecorator(this);
frame, name, fLook, fFlags);
if (fDecorator) { if (fDecorator) {
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight,
&fMaxWidth, &fMaxHeight); &fMaxWidth, &fMaxHeight);
@@ -172,8 +171,9 @@ Window::~Window()
delete fWindowBehaviour; delete fWindowBehaviour;
delete fDecorator; delete fDecorator;
delete fDrawingEngine; delete fDrawingEngine;
gDecorManager.CleanupForWindow(this);
} }
@@ -549,18 +549,18 @@ Window::ReloadDecor()
::Decorator* decorator = NULL; ::Decorator* decorator = NULL;
WindowBehaviour* windowBehaviour = NULL; WindowBehaviour* windowBehaviour = NULL;
if (fLook != B_NO_BORDER_WINDOW_LOOK) { if (fLook != B_NO_BORDER_WINDOW_LOOK) {
// we need a new decorator // we need a new decorator
decorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine, decorator = gDecorManager.AllocateDecorator(this);
Frame(), Title(), fLook, fFlags); if (decorator == NULL)
if (!decorator)
return false; return false;
if (IsFocus()) if (IsFocus())
decorator->SetFocus(true); decorator->SetFocus(true);
} }
windowBehaviour = gDecorManager.AllocateWindowBehaviour(this); windowBehaviour = gDecorManager.AllocateWindowBehaviour(this);
if (!windowBehaviour) { if (windowBehaviour == NULL) {
delete decorator; delete decorator;
return false; return false;
} }
@@ -1108,6 +1108,14 @@ Window::TabLocation() const
bool bool
Window::SetDecoratorSettings(const BMessage& settings, BRegion& dirty) 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) if (fDecorator)
return fDecorator->SetSettings(settings, &dirty); return fDecorator->SetSettings(settings, &dirty);
return false; return false;
@@ -1142,8 +1150,7 @@ Window::SetLook(window_look look, BRegion* updateRegion)
{ {
if (fDecorator == NULL && look != B_NO_BORDER_WINDOW_LOOK) { if (fDecorator == NULL && look != B_NO_BORDER_WINDOW_LOOK) {
// we need a new decorator // we need a new decorator
fDecorator = gDecorManager.AllocateDecorator(fDesktop, fDrawingEngine, fDecorator = gDecorManager.AllocateDecorator(this);
Frame(), Title(), fLook, fFlags);
if (IsFocus()) if (IsFocus())
fDecorator->SetFocus(true); fDecorator->SetFocus(true);
} }
+2
View File
@@ -375,6 +375,8 @@ protected:
int32 fMaxHeight; int32 fMaxHeight;
int32 fWorkspacesViewCount; int32 fWorkspacesViewCount;
friend class DecorManager;
}; };
#endif // WINDOW_H #endif // WINDOW_H