#include "BarApp.h"
#include <locale.h>
#include <strings.h>
#include <AppFileInfo.h>
#include <Autolock.h>
#include <Bitmap.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <Debug.h>
#include <Directory.h>
#include <Dragger.h>
#include <File.h>
#include <FindDirectory.h>
#include <IconUtils.h>
#include <Locale.h>
#include <Message.h>
#include <Messenger.h>
#include <Mime.h>
#include <Path.h>
#include <Roster.h>
#include <DeskbarPrivate.h>
#include <RosterPrivate.h>
#include "tracker_private.h"
#include "BarView.h"
#include "BarWindow.h"
#include "DeskbarUtils.h"
#include "FSUtils.h"
#include "PreferencesWindow.h"
#include "ResourceSet.h"
#include "StatusView.h"
#include "Switcher.h"
#include "icons.h"
BLocker TBarApp::sSubscriberLock;
BList TBarApp::sBarTeamInfoList;
BList TBarApp::sWindowIconCache;
BList TBarApp::sSubscribers;
const uint32 kShowDeskbarMenu = 'BeMn';
const uint32 kShowTeamMenu = 'TmMn';
int
main()
{
setlocale(LC_ALL, "");
TBarApp app;
app.Run();
return B_OK;
}
TBarApp::TBarApp()
:
BServer(kDeskbarSignature, true, NULL),
fSettingsFile(NULL),
fClockSettingsFile(NULL),
fPreferencesWindow(NULL)
{
InitSettings();
InitIconPreloader();
fBarWindow = new TBarWindow();
fBarView = fBarWindow->BarView();
be_roster->StartWatching(this);
gLocalizedNamePreferred
= BLocaleRoster::Default()->IsFilesystemTranslationPreferred();
sBarTeamInfoList.MakeEmpty();
BList teamList;
int32 numTeams;
be_roster->GetAppList(&teamList);
numTeams = teamList.CountItems();
for (int32 i = 0; i < numTeams; i++) {
app_info appInfo;
team_id tID = (addr_t)teamList.ItemAt(i);
if (be_roster->GetRunningAppInfo(tID, &appInfo) == B_OK) {
AddTeam(appInfo.team, appInfo.flags, appInfo.signature,
&appInfo.ref);
}
}
sWindowIconCache.MakeEmpty();
for (int32 id = R_WindowShownIcon; id <= R_WindowHiddenSwitchIcon; id++) {
if (id == R_ResizeIcon)
continue;
WindowIconCache* winCache = new WindowIconCache(id);
_CacheWindowIcon(winCache);
sWindowIconCache.AddItem(winCache);
}
sSubscribers.MakeEmpty();
fSwitcherMessenger = BMessenger(new TSwitchManager());
fBarWindow->Show();
fBarWindow->Lock();
fBarView->UpdatePlacement();
fBarWindow->Unlock();
fStatusViewMessenger = BMessenger(fBarWindow->FindView("BarView"));
}
TBarApp::~TBarApp()
{
be_roster->StopWatching(this);
int32 teamCount = sBarTeamInfoList.CountItems();
for (int32 i = 0; i < teamCount; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
delete barInfo;
}
int32 subsCount = sSubscribers.CountItems();
for (int32 i = 0; i < subsCount; i++) {
BMessenger* messenger
= static_cast<BMessenger*>(sSubscribers.ItemAt(i));
delete messenger;
}
SaveSettings();
delete fSettingsFile;
delete fClockSettingsFile;
}
bool
TBarApp::QuitRequested()
{
if (CurrentMessage() && CurrentMessage()->FindBool("shortcut")) {
QuitPreferencesWindow();
return false;
}
fBarWindow->SaveSettings();
BApplication::QuitRequested();
return true;
}
void
TBarApp::SaveSettings()
{
if (fSettingsFile->InitCheck() == B_OK) {
fSettingsFile->Seek(0, SEEK_SET);
BMessage prefs;
prefs.AddBool("vertical", fSettings.vertical);
prefs.AddBool("left", fSettings.left);
prefs.AddBool("top", fSettings.top);
prefs.AddInt32("state", fSettings.state);
prefs.AddFloat("width", fSettings.width);
prefs.AddPoint("switcherLoc", fSettings.switcherLoc);
prefs.AddBool("showClock", fSettings.showClock);
prefs.AddBool("trackerAlwaysFirst", fSettings.trackerAlwaysFirst);
prefs.AddBool("sortRunningApps", fSettings.sortRunningApps);
prefs.AddBool("superExpando", fSettings.superExpando);
prefs.AddBool("expandNewTeams", fSettings.expandNewTeams);
prefs.AddBool("hideLabels", fSettings.hideLabels);
prefs.AddInt32("iconSize", fSettings.iconSize);
prefs.AddBool("recentDocsEnabled", fSettings.recentDocsEnabled);
prefs.AddBool("recentFoldersEnabled", fSettings.recentFoldersEnabled);
prefs.AddBool("recentAppsEnabled", fSettings.recentAppsEnabled);
prefs.AddInt32("recentDocsCount", fSettings.recentDocsCount);
prefs.AddInt32("recentFoldersCount", fSettings.recentFoldersCount);
prefs.AddInt32("recentAppsCount", fSettings.recentAppsCount);
prefs.AddBool("alwaysOnTop", fSettings.alwaysOnTop);
prefs.AddBool("autoRaise", fSettings.autoRaise);
prefs.AddBool("autoHide", fSettings.autoHide);
prefs.Flatten(fSettingsFile);
}
if (fClockSettingsFile->InitCheck() == B_OK) {
fClockSettingsFile->Seek(0, SEEK_SET);
BMessage prefs;
prefs.AddBool("showSeconds", fClockSettings.showSeconds);
prefs.AddBool("showDayOfWeek", fClockSettings.showDayOfWeek);
prefs.AddBool("showTimeZone", fClockSettings.showTimeZone);
prefs.Flatten(fClockSettingsFile);
}
}
void
TBarApp::InitSettings()
{
sIconGap = ceilf(be_control_look->DefaultLabelSpacing() / 3.0f);
gDragRegionWidth = be_control_look->ComposeSpacing(B_USE_HALF_ITEM_SPACING);
gDragWidth = ceilf(gDragRegionWidth * 0.6f);
gMinReplicantHeight = gMinReplicantWidth =
be_control_look->ComposeIconSize(B_MINI_ICON).IntegerWidth() + 1;
gMinimumTrayWidth = sIconGap + gMinReplicantWidth
+ (kMinimumReplicantCount * sIconGap)
+ (kMinimumReplicantCount * gMinReplicantWidth) + kGutter;
gMinimumWindowWidth = kGutter + gMinimumTrayWidth + gDragRegionWidth;
gMaximumWindowWidth = gMinimumWindowWidth * 2;
desk_settings settings;
settings.vertical = fDefaultSettings.vertical = true;
settings.left = fDefaultSettings.left = false;
settings.top = fDefaultSettings.top = true;
settings.state = fDefaultSettings.state = kExpandoState;
settings.width = fDefaultSettings.width = gMinimumWindowWidth;
settings.switcherLoc = fDefaultSettings.switcherLoc = BPoint(5000, 5000);
settings.showClock = fDefaultSettings.showClock = true;
settings.trackerAlwaysFirst = fDefaultSettings.trackerAlwaysFirst = true;
settings.sortRunningApps = fDefaultSettings.sortRunningApps = false;
settings.superExpando = fDefaultSettings.superExpando = false;
settings.expandNewTeams = fDefaultSettings.expandNewTeams = false;
settings.hideLabels = fDefaultSettings.hideLabels = false;
settings.iconSize = fDefaultSettings.iconSize = kMinimumIconSize;
settings.recentDocsEnabled = fDefaultSettings.recentDocsEnabled = true;
settings.recentFoldersEnabled
= fDefaultSettings.recentFoldersEnabled = true;
settings.recentAppsEnabled = fDefaultSettings.recentAppsEnabled = true;
settings.recentDocsCount = fDefaultSettings.recentDocsCount = 10;
settings.recentFoldersCount = fDefaultSettings.recentFoldersCount = 10;
settings.recentAppsCount = fDefaultSettings.recentAppsCount = 10;
settings.alwaysOnTop = fDefaultSettings.alwaysOnTop = false;
settings.autoRaise = fDefaultSettings.autoRaise = false;
settings.autoHide = fDefaultSettings.autoHide = false;
clock_settings clock;
clock.showSeconds = false;
clock.showDayOfWeek = false;
clock.showTimeZone = false;
BPath dirPath;
const char* settingsFileName = "settings";
const char* clockSettingsFileName = "clock_settings";
find_directory(B_USER_DESKBAR_DIRECTORY, &dirPath, true);
if (GetDeskbarSettingsDirectory(dirPath, true) == B_OK) {
BPath filePath = dirPath;
filePath.Append(settingsFileName);
fSettingsFile = new BFile(filePath.Path(), O_RDWR);
if (fSettingsFile->InitCheck() != B_OK) {
BDirectory theDir(dirPath.Path());
if (theDir.InitCheck() == B_OK)
theDir.CreateFile(settingsFileName, fSettingsFile);
}
BMessage prefs;
if (fSettingsFile->InitCheck() == B_OK
&& prefs.Unflatten(fSettingsFile) == B_OK) {
settings.vertical = prefs.GetBool("vertical",
fDefaultSettings.vertical);
settings.left = prefs.GetBool("left",
fDefaultSettings.left);
settings.top = prefs.GetBool("top",
fDefaultSettings.top);
settings.state = prefs.GetInt32("state",
fDefaultSettings.state);
settings.width = prefs.GetFloat("width",
fDefaultSettings.width);
settings.switcherLoc = prefs.GetPoint("switcherLoc",
fDefaultSettings.switcherLoc);
settings.showClock = prefs.GetBool("showClock",
fDefaultSettings.showClock);
settings.trackerAlwaysFirst = prefs.GetBool("trackerAlwaysFirst",
fDefaultSettings.trackerAlwaysFirst);
settings.sortRunningApps = prefs.GetBool("sortRunningApps",
fDefaultSettings.sortRunningApps);
settings.superExpando = prefs.GetBool("superExpando",
fDefaultSettings.superExpando);
settings.expandNewTeams = prefs.GetBool("expandNewTeams",
fDefaultSettings.expandNewTeams);
settings.hideLabels = prefs.GetBool("hideLabels",
fDefaultSettings.hideLabels);
settings.iconSize = prefs.GetInt32("iconSize",
fDefaultSettings.iconSize);
settings.recentDocsEnabled = prefs.GetBool("recentDocsEnabled",
fDefaultSettings.recentDocsEnabled);
settings.recentFoldersEnabled
= prefs.GetBool("recentFoldersEnabled",
fDefaultSettings.recentFoldersEnabled);
settings.recentAppsEnabled = prefs.GetBool("recentAppsEnabled",
fDefaultSettings.recentAppsEnabled);
settings.recentDocsCount = prefs.GetInt32("recentDocsCount",
fDefaultSettings.recentDocsCount);
settings.recentFoldersCount = prefs.GetInt32("recentFoldersCount",
fDefaultSettings.recentFoldersCount);
settings.recentAppsCount = prefs.GetInt32("recentAppsCount",
fDefaultSettings.recentAppsCount);
settings.alwaysOnTop = prefs.GetBool("alwaysOnTop",
fDefaultSettings.alwaysOnTop);
settings.autoRaise = prefs.GetBool("autoRaise",
fDefaultSettings.autoRaise);
settings.autoHide = prefs.GetBool("autoHide",
fDefaultSettings.autoHide);
}
if (settings.width < gMinimumWindowWidth)
settings.width = gMinimumWindowWidth;
else if (settings.width > gMaximumWindowWidth)
settings.width = gMaximumWindowWidth;
filePath = dirPath;
filePath.Append(clockSettingsFileName);
fClockSettingsFile = new BFile(filePath.Path(), O_RDWR);
if (fClockSettingsFile->InitCheck() != B_OK) {
BDirectory theDir(dirPath.Path());
if (theDir.InitCheck() == B_OK)
theDir.CreateFile(clockSettingsFileName, fClockSettingsFile);
}
if (fClockSettingsFile->InitCheck() == B_OK
&& prefs.Unflatten(fClockSettingsFile) == B_OK) {
clock.showSeconds = prefs.GetBool("showSeconds", false);
clock.showDayOfWeek = prefs.GetBool("showDayOfWeek", false);
clock.showTimeZone = prefs.GetBool("showTimeZone", false);
}
}
fSettings = settings;
fClockSettings = clock;
}
void
TBarApp::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgIsAlwaysOnTop:
{
BMessage reply('rply');
reply.AddBool("always on top", fSettings.alwaysOnTop);
message->SendReply(&reply);
break;
}
case kMsgIsAutoRaise:
{
BMessage reply('rply');
reply.AddBool("auto raise", fSettings.autoRaise);
message->SendReply(&reply);
break;
}
case kMsgIsAutoHide:
{
BMessage reply('rply');
reply.AddBool("auto hide", fSettings.autoHide);
message->SendReply(&reply);
break;
}
case kMsgLocation:
case kMsgSetLocation:
case kMsgIsExpanded:
case kMsgExpand:
case kMsgGetItemInfo:
case kMsgHasItem:
case kMsgCountItems:
case kMsgMaxItemSize:
case kMsgAddView:
case kMsgRemoveItem:
case kMsgAddAddOn:
fBarWindow->PostMessage(message);
break;
case kConfigShow:
ShowPreferencesWindow();
break;
case kConfigQuit:
QuitPreferencesWindow();
break;
case kStateChanged:
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kStateChanged);
break;
case kShowDeskbarMenu:
if (fBarWindow->Lock()) {
fBarWindow->ShowDeskbarMenu();
fBarWindow->Unlock();
}
break;
case kShowTeamMenu:
if (fBarWindow->Lock()) {
fBarWindow->ShowTeamMenu();
fBarWindow->Unlock();
}
break;
case kUpdateRecentCounts:
int32 count;
bool enabled;
if (message->FindInt32("applications", &count) == B_OK)
fSettings.recentAppsCount = count;
if (message->FindBool("applicationsEnabled", &enabled) == B_OK)
fSettings.recentAppsEnabled = enabled && count > 0;
if (message->FindInt32("folders", &count) == B_OK)
fSettings.recentFoldersCount = count;
if (message->FindBool("foldersEnabled", &enabled) == B_OK)
fSettings.recentFoldersEnabled = enabled && count > 0;
if (message->FindInt32("documents", &count) == B_OK)
fSettings.recentDocsCount = count;
if (message->FindBool("documentsEnabled", &enabled) == B_OK)
fSettings.recentDocsEnabled = enabled && count > 0;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
break;
case B_SOME_APP_LAUNCHED:
{
team_id team = -1;
message->FindInt32("be:team", &team);
uint32 flags = 0;
message->FindInt32("be:flags", (int32*)&flags);
const char* signature = NULL;
message->FindString("be:signature", &signature);
entry_ref ref;
message->FindRef("be:ref", &ref);
AddTeam(team, flags, signature, &ref);
break;
}
case B_SOME_APP_QUIT:
{
team_id team = -1;
message->FindInt32("be:team", &team);
RemoveTeam(team);
break;
}
case B_ARCHIVED_OBJECT:
message->AddString("special", "Alex Osadzinski");
fStatusViewMessenger.SendMessage(message);
break;
case kToggleDraggers:
if (BDragger::AreDraggersDrawn())
BDragger::HideAllDraggers();
else
BDragger::ShowAllDraggers();
break;
case kMsgAlwaysOnTop:
case kAlwaysTop:
fSettings.alwaysOnTop = !fSettings.alwaysOnTop;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
fBarWindow->SetFeel(fSettings.alwaysOnTop
? B_FLOATING_ALL_WINDOW_FEEL
: B_NORMAL_WINDOW_FEEL);
break;
case kMsgAutoRaise:
case kAutoRaise:
fSettings.autoRaise = fSettings.alwaysOnTop ? false
: !fSettings.autoRaise;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
break;
case kMsgAutoHide:
case kAutoHide:
fSettings.autoHide = !fSettings.autoHide;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
fBarWindow->Lock();
fBarView->HideDeskbar(fSettings.autoHide);
fBarWindow->Unlock();
break;
case kTrackerFirst:
fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
if (fBarView->MiniState())
break;
fBarWindow->Lock();
fBarView->PlaceApplicationBar();
fBarWindow->Unlock();
break;
case kSortRunningApps:
fSettings.sortRunningApps = !fSettings.sortRunningApps;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
if (fBarView->MiniState())
break;
fBarWindow->Lock();
fBarView->PlaceApplicationBar();
fBarWindow->Unlock();
break;
case kUnsubscribe:
{
BMessenger messenger;
if (message->FindMessenger("messenger", &messenger) == B_OK)
Unsubscribe(messenger);
break;
}
case kSuperExpando:
fSettings.superExpando = !fSettings.superExpando;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
if (fBarView->MiniState())
break;
fBarWindow->Lock();
fBarView->PlaceApplicationBar();
fBarWindow->Unlock();
break;
case kExpandNewTeams:
fSettings.expandNewTeams = !fSettings.expandNewTeams;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
if (fBarView->MiniState())
break;
fBarWindow->Lock();
fBarView->PlaceApplicationBar();
fBarWindow->Unlock();
break;
case kHideLabels:
fSettings.hideLabels = !fSettings.hideLabels;
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
if (fBarView->MiniState())
break;
fBarWindow->Lock();
fBarView->PlaceApplicationBar();
fBarWindow->Unlock();
break;
case kResizeTeamIcons:
{
int32 oldIconSize = fSettings.iconSize;
int32 value;
if (message->FindInt32("be:value", &value) != B_OK)
break;
int32 iconSize = value * kIconSizeInterval;
fSettings.iconSize = iconSize;
if (fSettings.iconSize < kMinimumIconSize)
fSettings.iconSize = kMinimumIconSize;
else if (fSettings.iconSize > kMaximumIconSize)
fSettings.iconSize = kMaximumIconSize;
if (fSettings.iconSize == oldIconSize)
break;
ResizeTeamIcons();
if (fPreferencesWindow != NULL)
fPreferencesWindow->PostMessage(kUpdatePreferences);
if (fBarView->MiniState())
break;
fBarWindow->Lock();
if (!fBarView->Vertical()) {
fBarView->PlaceDeskbarMenu();
fBarView->PlaceTray(false, false);
}
fBarView->PlaceApplicationBar();
fBarWindow->Unlock();
break;
}
case 'TASK':
fSwitcherMessenger.SendMessage(message);
break;
case kSuspendSystem:
break;
case kRebootSystem:
case kShutdownSystem:
{
bool reboot = (message->what == kRebootSystem);
bool confirm;
message->FindBool("confirm", &confirm);
BRoster roster;
BRoster::Private rosterPrivate(roster);
status_t error = rosterPrivate.ShutDown(reboot, confirm, false);
if (error != B_OK)
fprintf(stderr, "Shutdown failed: %s\n", strerror(error));
break;
}
case kShowSplash:
run_be_about();
break;
case B_LOCALE_CHANGED:
{
BLocaleRoster::Default()->Refresh();
bool localize;
if (message->FindBool("filesys", &localize) == B_OK)
gLocalizedNamePreferred = localize;
}
case kRealignReplicants:
case kShowHideTime:
case kShowSeconds:
case kShowDayOfWeek:
case kShowTimeZone:
case kGetClockSettings:
fStatusViewMessenger.SendMessage(message);
break;
default:
BApplication::MessageReceived(message);
break;
}
}
void
TBarApp::RefsReceived(BMessage* refs)
{
entry_ref ref;
for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) {
BMessage refsReceived(B_REFS_RECEIVED);
refsReceived.AddRef("refs", &ref);
BEntry entry(&ref);
if (!entry.IsDirectory())
TrackerLaunch(&refsReceived, false);
}
}
void
TBarApp::Subscribe(const BMessenger &subscriber, BList* list)
{
list->MakeEmpty();
BAutolock autolock(sSubscriberLock);
if (!autolock.IsLocked())
return;
int32 numTeams = sBarTeamInfoList.CountItems();
for (int32 i = 0; i < numTeams; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
BarTeamInfo* newBarInfo = new(std::nothrow) BarTeamInfo(*barInfo);
if (newBarInfo != NULL)
list->AddItem(newBarInfo);
}
int32 subsCount = sSubscribers.CountItems();
for (int32 i = 0; i < subsCount; i++) {
BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
if (*messenger == subscriber)
return;
}
sSubscribers.AddItem(new BMessenger(subscriber));
}
void
TBarApp::Unsubscribe(const BMessenger &subscriber)
{
BAutolock autolock(sSubscriberLock);
if (!autolock.IsLocked())
return;
int32 count = sSubscribers.CountItems();
for (int32 i = 0; i < count; i++) {
BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
if (*messenger == subscriber) {
sSubscribers.RemoveItem(i);
delete messenger;
break;
}
}
}
BBitmap*
TBarApp::FetchTeamIcon(team_id team, int32 size)
{
int32 teamCount = sBarTeamInfoList.CountItems();
for (int32 i = 0; i < teamCount; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
if (barInfo->teams->HasItem((void*)(addr_t)team)) {
_CacheTeamIcon(barInfo, size);
BBitmap* icon = barInfo->icon;
if (size != fSettings.iconSize) {
int32 index = (fSettings.iconSize - kMinimumIconSize)
/ kIconSizeInterval;
barInfo->icon = barInfo->iconCache[index];
}
return icon;
}
}
return NULL;
}
BBitmap*
TBarApp::FetchWindowIcon(bool local, bool minimized)
{
int32 id = R_WindowShownIcon;
int32 index = 0;
if (local) {
if (!minimized) {
id = R_WindowShownIcon;
index = 0;
}
else {
id = R_WindowHiddenIcon;
index = 1;
}
} else {
if (!minimized) {
id = R_WindowShownSwitchIcon;
index = 2;
}
else {
id = R_WindowHiddenSwitchIcon;
index = 3;
}
}
WindowIconCache* winCache
= (WindowIconCache*)sWindowIconCache.ItemAt(index);
if (winCache == NULL)
winCache = new WindowIconCache(id);
_CacheWindowIcon(winCache);
return winCache->icon;
}
void
TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref)
{
if ((flags & B_BACKGROUND_APP) != 0
|| strcasecmp(sig, kDeskbarSignature) == 0) {
return;
}
BAutolock autolock(sSubscriberLock);
if (!autolock.IsLocked())
return;
BarTeamInfo* multiLaunchTeam = NULL;
int32 teamCount = sBarTeamInfoList.CountItems();
for (int32 i = 0; i < teamCount; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
if (barInfo->teams->HasItem((void*)(addr_t)team))
return;
if (strcasecmp(barInfo->sig, sig) == 0)
multiLaunchTeam = barInfo;
}
if (multiLaunchTeam != NULL) {
multiLaunchTeam->teams->AddItem((void*)(addr_t)team);
int32 subsCount = sSubscribers.CountItems();
if (subsCount > 0) {
BMessage message(kAddTeam);
message.AddInt32("team", team);
message.AddString("sig", multiLaunchTeam->sig);
for (int32 i = 0; i < subsCount; i++)
((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message);
}
return;
}
BString name;
if (!gLocalizedNamePreferred
|| BLocaleRoster::Default()->GetLocalizedFileName(name, *ref)
!= B_OK) {
name = ref->name;
}
BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig),
strdup(name.String()));
_CacheTeamIcon(barInfo);
barInfo->teams->AddItem((void*)(addr_t)team);
sBarTeamInfoList.AddItem(barInfo);
int32 subsCount = sSubscribers.CountItems();
if (subsCount > 0) {
for (int32 i = 0; i < subsCount; i++) {
BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
BMessage message(B_SOME_APP_LAUNCHED);
BList* tList = new BList(*(barInfo->teams));
message.AddPointer("teams", tList);
BBitmap* icon = new BBitmap(barInfo->icon);
ASSERT(icon);
message.AddPointer("icon", icon);
message.AddInt32("flags", static_cast<int32>(barInfo->flags));
message.AddString("name", barInfo->name);
message.AddString("sig", barInfo->sig);
messenger->SendMessage(&message);
}
}
}
void
TBarApp::RemoveTeam(team_id team)
{
BAutolock autolock(sSubscriberLock);
if (!autolock.IsLocked())
return;
int32 teamCount = sBarTeamInfoList.CountItems();
for (int32 i = 0; i < teamCount; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
if (barInfo->teams->HasItem((void*)(addr_t)team)) {
int32 subsCount = sSubscribers.CountItems();
if (subsCount > 0) {
BMessage message((barInfo->teams->CountItems() == 1)
? B_SOME_APP_QUIT : kRemoveTeam);
message.AddInt32("team", team);
for (int32 i = 0; i < subsCount; i++) {
BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
messenger->SendMessage(&message);
}
}
barInfo->teams->RemoveItem((void*)(addr_t)team);
if (barInfo->teams->CountItems() < 1) {
delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i);
return;
}
}
}
}
void
TBarApp::ResizeTeamIcons()
{
for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) {
BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
if ((barInfo->flags & B_BACKGROUND_APP) == 0
&& strcasecmp(barInfo->sig, kDeskbarSignature) != 0) {
_CacheTeamIcon(barInfo);
}
}
}
int32
TBarApp::TeamIconSize()
{
static int32 iconSize = 0, composed = 0;
int32 saved = fSettings.iconSize;
if (iconSize != saved) {
composed = be_control_look->ComposeIconSize(saved).IntegerWidth() + 1;
iconSize = saved;
}
return composed;
}
void
TBarApp::ShowPreferencesWindow()
{
if (fPreferencesWindow == NULL) {
fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240));
fPreferencesWindow->Show();
} else if (fPreferencesWindow->Lock()) {
if (fPreferencesWindow->IsHidden())
fPreferencesWindow->Show();
else
fPreferencesWindow->Activate();
fPreferencesWindow->Unlock();
}
}
void
TBarApp::QuitPreferencesWindow()
{
if (fPreferencesWindow == NULL)
return;
if (fPreferencesWindow->Lock()) {
fPreferencesWindow->Quit();
fPreferencesWindow = NULL;
}
}
status_t
TBarApp::_CacheTeamIcon(BarTeamInfo* barInfo)
{
if (barInfo == NULL)
return B_BAD_VALUE;
return _CacheTeamIcon(barInfo, fSettings.iconSize);
}
status_t
TBarApp::_CacheTeamIcon(BarTeamInfo* barInfo, int32 size)
{
if (barInfo == NULL || size < kMinimumIconSize)
return B_BAD_VALUE;
const int32 index = (size - kMinimumIconSize) / kIconSizeInterval;
barInfo->icon = barInfo->iconCache[index];
if (barInfo->icon != NULL)
return B_OK;
int32 composed = be_control_look->ComposeIconSize(size).IntegerWidth() + 1;
BRect iconRect = BRect(0, 0, composed - 1, composed - 1);
BBitmap* icon = new BBitmap(iconRect, B_RGBA32);
app_info appInfo;
if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) {
BFile file(&appInfo.ref, B_READ_ONLY);
BAppFileInfo appMime(&file);
if (appMime.GetIcon(icon, (icon_size)size) == B_OK) {
barInfo->iconCache[index] = barInfo->icon = icon;
return B_OK;
}
}
BMimeType defaultAppMime;
defaultAppMime.SetTo(B_APP_MIME_TYPE);
if (defaultAppMime.GetIcon(icon, (icon_size)size) == B_OK) {
barInfo->iconCache[index] = barInfo->icon = icon;
return B_OK;
}
uint8* iconBits = (uint8*)icon->Bits();
if (icon->ColorSpace() == B_RGBA32) {
int32 i = 0;
while (i < icon->BitsLength()) {
iconBits[i++] = B_TRANSPARENT_32_BIT.red;
iconBits[i++] = B_TRANSPARENT_32_BIT.green;
iconBits[i++] = B_TRANSPARENT_32_BIT.blue;
iconBits[i++] = B_TRANSPARENT_32_BIT.alpha;
}
} else {
for (int32 i = 0; i < icon->BitsLength(); i++)
iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8;
}
barInfo->iconCache[index] = barInfo->icon = icon;
return B_OK;
}
status_t
TBarApp::_CacheWindowIcon(WindowIconCache* winCache)
{
if (winCache == NULL)
return B_BAD_VALUE;
int32 fontSize = (int32)floorf(be_plain_font->Size());
if (fontSize < kMinimumFontSize)
fontSize = kMinimumFontSize;
if (fontSize > kMaximumFontSize)
fontSize = kMaximumFontSize;
const int32 index = (fontSize - kMinimumFontSize) / kFontSizeInterval;
winCache->icon = winCache->iconCache[index];
if (winCache->icon != NULL)
return B_OK;
int32 id = winCache->id;
uint8* data;
size_t size;
data = (uint8*)AppResSet()->FindResource(B_VECTOR_ICON_TYPE, id, &size);
if (data != NULL && size > 0) {
BBitmap* icon = new(std::nothrow) BBitmap(
BRect(B_ORIGIN, be_control_look->ComposeIconSize(B_MINI_ICON)),
B_RGBA32);
if (icon != NULL && icon->InitCheck() == B_OK
&& BIconUtils::GetVectorIcon(const_cast<const uint8*>(data),
size, icon) == B_OK) {
winCache->iconCache[index] = winCache->icon = icon;
return B_OK;
} else if (icon != NULL) {
delete icon;
delete winCache->iconCache[index];
winCache->iconCache[index] = winCache->icon = NULL;
return B_NO_MEMORY;
}
}
return B_ERROR;
}
BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, char* name,
BBitmap* icon)
:
teams(teams),
flags(flags),
sig(sig),
name(name),
icon(icon)
{
_Init();
}
BarTeamInfo::BarTeamInfo(const BarTeamInfo &info)
:
teams(new BList(*info.teams)),
flags(info.flags),
sig(strdup(info.sig)),
name(strdup(info.name)),
icon(new BBitmap(*info.icon))
{
_Init();
}
BarTeamInfo::~BarTeamInfo()
{
delete teams;
free(sig);
free(name);
for (int32 i = 0; i < kIconCacheCount; i++)
delete iconCache[i];
}
void
BarTeamInfo::_Init()
{
for (int32 i = 0; i < kIconCacheCount; i++)
iconCache[i] = NULL;
}
WindowIconCache::WindowIconCache(int32 id, BBitmap* icon)
:
id(id),
icon(icon)
{
_Init();
}
WindowIconCache::WindowIconCache(const WindowIconCache &cache)
:
id(cache.id),
icon(new BBitmap(*cache.icon))
{
_Init();
}
WindowIconCache::~WindowIconCache()
{
for (int32 i = 0; i < kWindowIconCacheCount; i++)
delete iconCache[i];
}
void
WindowIconCache::_Init()
{
for (int32 i = 0; i < kWindowIconCacheCount; i++)
iconCache[i] = NULL;
}