BPicture: Fix archive constructor.
[haiku.git] / src / apps / deskbar / BarApp.cpp
blobe5dc306a86641b001e037b7c92c8b95f82e9676e
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered
30 trademarks of Be Incorporated in the United States and other countries. Other
31 brand product names are registered trademarks or trademarks of their respective
32 holders.
33 All rights reserved.
37 #include "BarApp.h"
39 #include <locale.h>
40 #include <strings.h>
42 #include <AppFileInfo.h>
43 #include <Autolock.h>
44 #include <Bitmap.h>
45 #include <Catalog.h>
46 #include <Debug.h>
47 #include <Directory.h>
48 #include <Dragger.h>
49 #include <File.h>
50 #include <FindDirectory.h>
51 #include <Locale.h>
52 #include <Mime.h>
53 #include <Message.h>
54 #include <Messenger.h>
55 #include <Path.h>
56 #include <Roster.h>
57 #include <RosterPrivate.h>
59 #include "BarView.h"
60 #include "BarWindow.h"
61 #include "DeskbarUtils.h"
62 #include "FSUtils.h"
63 #include "PreferencesWindow.h"
64 #include "ResourceSet.h"
65 #include "StatusView.h"
66 #include "Switcher.h"
67 #include "Utilities.h"
69 #include "icons.h"
70 #include "tracker_private.h"
73 BLocker TBarApp::sSubscriberLock;
74 BList TBarApp::sBarTeamInfoList;
75 BList TBarApp::sSubscribers;
78 const uint32 kShowDeskbarMenu = 'BeMn';
79 const uint32 kShowTeamMenu = 'TmMn';
81 static const color_space kIconColorSpace = B_RGBA32;
84 int
85 main()
87 setlocale(LC_ALL, "");
88 TBarApp app;
89 app.Run();
91 return B_OK;
95 TBarApp::TBarApp()
97 BApplication(kDeskbarSignature),
98 fSettingsFile(NULL),
99 fClockSettingsFile(NULL),
100 fPreferencesWindow(NULL)
102 InitSettings();
103 InitIconPreloader();
105 fBarWindow = new TBarWindow();
106 fBarView = fBarWindow->BarView();
108 be_roster->StartWatching(this);
110 gLocalizedNamePreferred
111 = BLocaleRoster::Default()->IsFilesystemTranslationPreferred();
113 sBarTeamInfoList.MakeEmpty();
115 BList teamList;
116 int32 numTeams;
117 be_roster->GetAppList(&teamList);
118 numTeams = teamList.CountItems();
119 for (int32 i = 0; i < numTeams; i++) {
120 app_info appInfo;
121 team_id tID = (addr_t)teamList.ItemAt(i);
122 if (be_roster->GetRunningAppInfo(tID, &appInfo) == B_OK) {
123 AddTeam(appInfo.team, appInfo.flags, appInfo.signature,
124 &appInfo.ref);
128 sSubscribers.MakeEmpty();
129 fSwitcherMessenger = BMessenger(new TSwitchManager(fSettings.switcherLoc));
130 fBarWindow->Show();
132 fBarWindow->Lock();
133 fBarView->UpdatePlacement();
134 fBarWindow->Unlock();
136 // this messenger now targets the barview instead of the
137 // statusview so that all additions to the tray
138 // follow the same path
139 fStatusViewMessenger = BMessenger(fBarWindow->FindView("BarView"));
143 TBarApp::~TBarApp()
145 be_roster->StopWatching(this);
147 int32 teamCount = sBarTeamInfoList.CountItems();
148 for (int32 i = 0; i < teamCount; i++) {
149 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
150 delete barInfo;
153 int32 subsCount = sSubscribers.CountItems();
154 for (int32 i = 0; i < subsCount; i++) {
155 BMessenger* messenger
156 = static_cast<BMessenger*>(sSubscribers.ItemAt(i));
157 delete messenger;
160 SaveSettings();
162 delete fSettingsFile;
163 delete fClockSettingsFile;
167 bool
168 TBarApp::QuitRequested()
170 // don't allow the user to quit
171 if (CurrentMessage() && CurrentMessage()->FindBool("shortcut")) {
172 // but close the preferences window
173 QuitPreferencesWindow();
174 return false;
177 // system quitting, call inherited to notify all loopers
178 fBarWindow->SaveSettings();
179 BApplication::QuitRequested();
180 return true;
184 void
185 TBarApp::SaveSettings()
187 if (fSettingsFile->InitCheck() == B_OK) {
188 fSettingsFile->Seek(0, SEEK_SET);
189 BMessage prefs;
190 prefs.AddBool("vertical", fSettings.vertical);
191 prefs.AddBool("left", fSettings.left);
192 prefs.AddBool("top", fSettings.top);
193 prefs.AddInt32("state", fSettings.state);
194 prefs.AddFloat("width", fSettings.width);
195 prefs.AddPoint("switcherLoc", fSettings.switcherLoc);
196 prefs.AddBool("showClock", fSettings.showClock);
197 // applications
198 prefs.AddBool("trackerAlwaysFirst", fSettings.trackerAlwaysFirst);
199 prefs.AddBool("sortRunningApps", fSettings.sortRunningApps);
200 prefs.AddBool("superExpando", fSettings.superExpando);
201 prefs.AddBool("expandNewTeams", fSettings.expandNewTeams);
202 prefs.AddBool("hideLabels", fSettings.hideLabels);
203 prefs.AddInt32("iconSize", fSettings.iconSize);
204 // recent items
205 prefs.AddBool("recentDocsEnabled", fSettings.recentDocsEnabled);
206 prefs.AddBool("recentFoldersEnabled", fSettings.recentFoldersEnabled);
207 prefs.AddBool("recentAppsEnabled", fSettings.recentAppsEnabled);
208 prefs.AddInt32("recentDocsCount", fSettings.recentDocsCount);
209 prefs.AddInt32("recentFoldersCount", fSettings.recentFoldersCount);
210 prefs.AddInt32("recentAppsCount", fSettings.recentAppsCount);
211 // window
212 prefs.AddBool("alwaysOnTop", fSettings.alwaysOnTop);
213 prefs.AddBool("autoRaise", fSettings.autoRaise);
214 prefs.AddBool("autoHide", fSettings.autoHide);
216 prefs.Flatten(fSettingsFile);
219 if (fClockSettingsFile->InitCheck() == B_OK) {
220 fClockSettingsFile->Seek(0, SEEK_SET);
221 BMessage prefs;
222 prefs.AddBool("showSeconds", fClockSettings.showSeconds);
223 prefs.AddBool("showDayOfWeek", fClockSettings.showDayOfWeek);
224 prefs.AddBool("showTimeZone", fClockSettings.showTimeZone);
226 prefs.Flatten(fClockSettingsFile);
231 void
232 TBarApp::InitSettings()
234 desk_settings settings;
235 settings.vertical = fDefaultSettings.vertical = true;
236 settings.left = fDefaultSettings.left = false;
237 settings.top = fDefaultSettings.top = true;
238 settings.state = fDefaultSettings.state = kExpandoState;
239 settings.width = fDefaultSettings.width = 0;
240 settings.switcherLoc = fDefaultSettings.switcherLoc = BPoint(5000, 5000);
241 settings.showClock = fDefaultSettings.showClock = true;
242 // applications
243 settings.trackerAlwaysFirst = fDefaultSettings.trackerAlwaysFirst = false;
244 settings.sortRunningApps = fDefaultSettings.sortRunningApps = false;
245 settings.superExpando = fDefaultSettings.superExpando = false;
246 settings.expandNewTeams = fDefaultSettings.expandNewTeams = false;
247 settings.hideLabels = fDefaultSettings.hideLabels = false;
248 settings.iconSize = fDefaultSettings.iconSize = kMinimumIconSize;
249 // recent items
250 settings.recentDocsEnabled = fDefaultSettings.recentDocsEnabled = true;
251 settings.recentFoldersEnabled
252 = fDefaultSettings.recentFoldersEnabled = true;
253 settings.recentAppsEnabled = fDefaultSettings.recentAppsEnabled = true;
254 settings.recentDocsCount = fDefaultSettings.recentDocsCount = 10;
255 settings.recentFoldersCount = fDefaultSettings.recentFoldersCount = 10;
256 settings.recentAppsCount = fDefaultSettings.recentAppsCount = 10;
257 // window
258 settings.alwaysOnTop = fDefaultSettings.alwaysOnTop = false;
259 settings.autoRaise = fDefaultSettings.autoRaise = false;
260 settings.autoHide = fDefaultSettings.autoHide = false;
262 clock_settings clock;
263 clock.showSeconds = false;
264 clock.showDayOfWeek = false;
265 clock.showTimeZone = false;
267 BPath dirPath;
268 const char* settingsFileName = "settings";
269 const char* clockSettingsFileName = "clock_settings";
271 find_directory(B_USER_DESKBAR_DIRECTORY, &dirPath, true);
272 // just make it
274 if (GetDeskbarSettingsDirectory(dirPath, true) == B_OK) {
275 BPath filePath = dirPath;
276 filePath.Append(settingsFileName);
277 fSettingsFile = new BFile(filePath.Path(), O_RDWR);
278 if (fSettingsFile->InitCheck() != B_OK) {
279 BDirectory theDir(dirPath.Path());
280 if (theDir.InitCheck() == B_OK)
281 theDir.CreateFile(settingsFileName, fSettingsFile);
284 BMessage prefs;
285 if (fSettingsFile->InitCheck() == B_OK
286 && prefs.Unflatten(fSettingsFile) == B_OK) {
287 settings.vertical = prefs.GetBool("vertical",
288 fDefaultSettings.vertical);
289 settings.left = prefs.GetBool("left",
290 fDefaultSettings.left);
291 settings.top = prefs.GetBool("top",
292 fDefaultSettings.top);
293 settings.state = prefs.GetInt32("state",
294 fDefaultSettings.state);
295 settings.width = prefs.GetFloat("width",
296 fDefaultSettings.width);
297 settings.switcherLoc = prefs.GetPoint("switcherLoc",
298 fDefaultSettings.switcherLoc);
299 settings.showClock = prefs.GetBool("showClock",
300 fDefaultSettings.showClock);
301 // applications
302 settings.trackerAlwaysFirst = prefs.GetBool("trackerAlwaysFirst",
303 fDefaultSettings.trackerAlwaysFirst);
304 settings.sortRunningApps = prefs.GetBool("sortRunningApps",
305 fDefaultSettings.sortRunningApps);
306 settings.superExpando = prefs.GetBool("superExpando",
307 fDefaultSettings.superExpando);
308 settings.expandNewTeams = prefs.GetBool("expandNewTeams",
309 fDefaultSettings.expandNewTeams);
310 settings.hideLabels = prefs.GetBool("hideLabels",
311 fDefaultSettings.hideLabels);
312 settings.iconSize = prefs.GetInt32("iconSize",
313 fDefaultSettings.iconSize);
314 // recent items
315 settings.recentDocsEnabled = prefs.GetBool("recentDocsEnabled",
316 fDefaultSettings.recentDocsEnabled);
317 settings.recentFoldersEnabled
318 = prefs.GetBool("recentFoldersEnabled",
319 fDefaultSettings.recentFoldersEnabled);
320 settings.recentAppsEnabled = prefs.GetBool("recentAppsEnabled",
321 fDefaultSettings.recentAppsEnabled);
322 settings.recentDocsCount = prefs.GetInt32("recentDocsCount",
323 fDefaultSettings.recentDocsCount);
324 settings.recentFoldersCount = prefs.GetInt32("recentFoldersCount",
325 fDefaultSettings.recentFoldersCount);
326 settings.recentAppsCount = prefs.GetInt32("recentAppsCount",
327 fDefaultSettings.recentAppsCount);
328 // window
329 settings.alwaysOnTop = prefs.GetBool("alwaysOnTop",
330 fDefaultSettings.alwaysOnTop);
331 settings.autoRaise = prefs.GetBool("autoRaise",
332 fDefaultSettings.autoRaise);
333 settings.autoHide = prefs.GetBool("autoHide",
334 fDefaultSettings.autoHide);
337 filePath = dirPath;
338 filePath.Append(clockSettingsFileName);
339 fClockSettingsFile = new BFile(filePath.Path(), O_RDWR);
340 if (fClockSettingsFile->InitCheck() != B_OK) {
341 BDirectory theDir(dirPath.Path());
342 if (theDir.InitCheck() == B_OK)
343 theDir.CreateFile(clockSettingsFileName, fClockSettingsFile);
346 if (fClockSettingsFile->InitCheck() == B_OK
347 && prefs.Unflatten(fClockSettingsFile) == B_OK) {
348 clock.showSeconds = prefs.GetBool("showSeconds", false);
349 clock.showDayOfWeek = prefs.GetBool("showDayOfWeek", false);
350 clock.showTimeZone = prefs.GetBool("showTimeZone", false);
354 fSettings = settings;
355 fClockSettings = clock;
359 void
360 TBarApp::MessageReceived(BMessage* message)
362 switch (message->what) {
363 case 'gloc':
364 case 'sloc':
365 case 'gexp':
366 case 'sexp':
367 case 'info':
368 case 'exst':
369 case 'cwnt':
370 case 'icon':
371 case 'remv':
372 case 'adon':
373 // pass any BDeskbar originating messages on to the window
374 fBarWindow->PostMessage(message);
375 break;
377 case kConfigShow:
378 ShowPreferencesWindow();
379 break;
381 case kConfigQuit:
382 QuitPreferencesWindow();
383 break;
385 case kStateChanged:
386 if (fPreferencesWindow != NULL)
387 fPreferencesWindow->PostMessage(kStateChanged);
388 break;
390 case kShowDeskbarMenu:
391 if (fBarWindow->Lock()) {
392 fBarWindow->ShowDeskbarMenu();
393 fBarWindow->Unlock();
395 break;
397 case kShowTeamMenu:
398 if (fBarWindow->Lock()) {
399 fBarWindow->ShowTeamMenu();
400 fBarWindow->Unlock();
402 break;
404 case kUpdateRecentCounts:
405 int32 count;
406 bool enabled;
408 if (message->FindInt32("applications", &count) == B_OK)
409 fSettings.recentAppsCount = count;
410 if (message->FindBool("applicationsEnabled", &enabled) == B_OK)
411 fSettings.recentAppsEnabled = enabled && count > 0;
413 if (message->FindInt32("folders", &count) == B_OK)
414 fSettings.recentFoldersCount = count;
415 if (message->FindBool("foldersEnabled", &enabled) == B_OK)
416 fSettings.recentFoldersEnabled = enabled && count > 0;
418 if (message->FindInt32("documents", &count) == B_OK)
419 fSettings.recentDocsCount = count;
420 if (message->FindBool("documentsEnabled", &enabled) == B_OK)
421 fSettings.recentDocsEnabled = enabled && count > 0;
423 if (fPreferencesWindow != NULL)
424 fPreferencesWindow->PostMessage(kUpdatePreferences);
425 break;
427 case B_SOME_APP_LAUNCHED:
429 team_id team = -1;
430 message->FindInt32("be:team", &team);
432 uint32 flags = 0;
433 message->FindInt32("be:flags", (int32*)&flags);
435 const char* signature = NULL;
436 message->FindString("be:signature", &signature);
438 entry_ref ref;
439 message->FindRef("be:ref", &ref);
441 AddTeam(team, flags, signature, &ref);
442 break;
445 case B_SOME_APP_QUIT:
447 team_id team = -1;
448 message->FindInt32("be:team", &team);
449 RemoveTeam(team);
450 break;
453 case B_ARCHIVED_OBJECT:
454 // TODO: what's this???
455 message->AddString("special", "Alex Osadzinski");
456 fStatusViewMessenger.SendMessage(message);
457 break;
459 case kToggleDraggers:
460 if (BDragger::AreDraggersDrawn())
461 BDragger::HideAllDraggers();
462 else
463 BDragger::ShowAllDraggers();
464 break;
466 case kAlwaysTop:
467 fSettings.alwaysOnTop = !fSettings.alwaysOnTop;
469 if (fPreferencesWindow != NULL)
470 fPreferencesWindow->PostMessage(kUpdatePreferences);
472 fBarWindow->SetFeel(fSettings.alwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL
473 : B_NORMAL_WINDOW_FEEL);
474 break;
476 case kAutoRaise:
477 fSettings.autoRaise = fSettings.alwaysOnTop ? false :
478 !fSettings.autoRaise;
480 if (fPreferencesWindow != NULL)
481 fPreferencesWindow->PostMessage(kUpdatePreferences);
482 break;
484 case kAutoHide:
485 fSettings.autoHide = !fSettings.autoHide;
487 if (fPreferencesWindow != NULL)
488 fPreferencesWindow->PostMessage(kUpdatePreferences);
490 fBarWindow->Lock();
491 fBarView->HideDeskbar(fSettings.autoHide);
492 fBarWindow->Unlock();
493 break;
495 case kTrackerFirst:
496 fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst;
498 if (fPreferencesWindow != NULL)
499 fPreferencesWindow->PostMessage(kUpdatePreferences);
501 // if mini mode we don't need to update the view
502 if (fBarView->MiniState())
503 break;
505 fBarWindow->Lock();
506 fBarView->PlaceApplicationBar();
507 fBarWindow->Unlock();
508 break;
510 case kSortRunningApps:
511 fSettings.sortRunningApps = !fSettings.sortRunningApps;
513 if (fPreferencesWindow != NULL)
514 fPreferencesWindow->PostMessage(kUpdatePreferences);
516 // if mini mode we don't need to update the view
517 if (fBarView->MiniState())
518 break;
520 fBarWindow->Lock();
521 fBarView->PlaceApplicationBar();
522 fBarWindow->Unlock();
523 break;
525 case kUnsubscribe:
527 BMessenger messenger;
528 if (message->FindMessenger("messenger", &messenger) == B_OK)
529 Unsubscribe(messenger);
530 break;
533 case kSuperExpando:
534 fSettings.superExpando = !fSettings.superExpando;
536 if (fPreferencesWindow != NULL)
537 fPreferencesWindow->PostMessage(kUpdatePreferences);
539 // if mini mode we don't need to update the view
540 if (fBarView->MiniState())
541 break;
543 fBarWindow->Lock();
544 fBarView->PlaceApplicationBar();
545 fBarWindow->Unlock();
546 break;
548 case kExpandNewTeams:
549 fSettings.expandNewTeams = !fSettings.expandNewTeams;
551 if (fPreferencesWindow != NULL)
552 fPreferencesWindow->PostMessage(kUpdatePreferences);
554 // if mini mode we don't need to update the view
555 if (fBarView->MiniState())
556 break;
558 fBarWindow->Lock();
559 fBarView->PlaceApplicationBar();
560 fBarWindow->Unlock();
561 break;
563 case kHideLabels:
564 fSettings.hideLabels = !fSettings.hideLabels;
566 if (fPreferencesWindow != NULL)
567 fPreferencesWindow->PostMessage(kUpdatePreferences);
569 // if mini mode we don't need to update the view
570 if (fBarView->MiniState())
571 break;
573 fBarWindow->Lock();
574 fBarView->PlaceApplicationBar();
575 fBarWindow->Unlock();
576 break;
578 case kResizeTeamIcons:
580 int32 oldIconSize = fSettings.iconSize;
581 int32 iconSize;
582 if (message->FindInt32("be:value", &iconSize) != B_OK)
583 break;
585 fSettings.iconSize = iconSize * kIconSizeInterval;
587 // pin icon size between min and max values
588 if (fSettings.iconSize < kMinimumIconSize)
589 fSettings.iconSize = kMinimumIconSize;
590 else if (fSettings.iconSize > kMaximumIconSize)
591 fSettings.iconSize = kMaximumIconSize;
593 // don't resize if icon size hasn't changed
594 if (fSettings.iconSize == oldIconSize)
595 break;
597 ResizeTeamIcons();
599 if (fPreferencesWindow != NULL)
600 fPreferencesWindow->PostMessage(kUpdatePreferences);
602 // if mini mode we don't need to update the view
603 if (fBarView->MiniState())
604 break;
606 fBarWindow->Lock();
607 if (!fBarView->Vertical()) {
608 // Must also resize the Deskbar menu and replicant tray in
609 // horizontal mode
610 fBarView->PlaceDeskbarMenu();
611 fBarView->PlaceTray(false, false);
613 fBarView->PlaceApplicationBar();
614 fBarWindow->Unlock();
615 break;
618 case 'TASK':
619 fSwitcherMessenger.SendMessage(message);
620 break;
622 case kSuspendSystem:
623 // TODO: Call BRoster?
624 break;
626 case kRebootSystem:
627 case kShutdownSystem:
629 bool reboot = (message->what == kRebootSystem);
630 bool confirm;
631 message->FindBool("confirm", &confirm);
633 BRoster roster;
634 BRoster::Private rosterPrivate(roster);
635 status_t error = rosterPrivate.ShutDown(reboot, confirm, false);
636 if (error != B_OK)
637 fprintf(stderr, "Shutdown failed: %s\n", strerror(error));
639 break;
642 case kShowSplash:
643 run_be_about();
644 break;
646 case kRestartTracker:
648 BRoster roster;
649 roster.Launch(kTrackerSignature);
650 break;
653 case B_LOCALE_CHANGED:
655 BLocaleRoster::Default()->Refresh();
657 bool localize;
658 if (message->FindBool("filesys", &localize) == B_OK)
659 gLocalizedNamePreferred = localize;
661 // fall-through
663 case kShowHideTime:
664 case kShowSeconds:
665 case kShowDayOfWeek:
666 case kShowTimeZone:
667 case kGetClockSettings:
668 fStatusViewMessenger.SendMessage(message);
669 // Notify the replicant tray (through BarView) that the time
670 // interval has changed and it should update the time view
671 // and reflow the tray icons.
672 break;
674 default:
675 BApplication::MessageReceived(message);
676 break;
681 void
682 TBarApp::RefsReceived(BMessage* refs)
684 entry_ref ref;
685 for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) {
686 BMessage refsReceived(B_REFS_RECEIVED);
687 refsReceived.AddRef("refs", &ref);
689 BEntry entry(&ref);
690 if (!entry.IsDirectory())
691 TrackerLaunch(&refsReceived, false);
696 void
697 TBarApp::Subscribe(const BMessenger &subscriber, BList* list)
699 // called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt
700 list->MakeEmpty();
702 BAutolock autolock(sSubscriberLock);
703 if (!autolock.IsLocked())
704 return;
706 int32 numTeams = sBarTeamInfoList.CountItems();
707 for (int32 i = 0; i < numTeams; i++) {
708 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
709 BarTeamInfo* newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo);
710 if (newBarInfo != NULL)
711 list->AddItem(newBarInfo);
714 int32 subsCount = sSubscribers.CountItems();
715 for (int32 i = 0; i < subsCount; i++) {
716 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
717 if (*messenger == subscriber)
718 return;
721 sSubscribers.AddItem(new BMessenger(subscriber));
725 void
726 TBarApp::Unsubscribe(const BMessenger &subscriber)
728 BAutolock autolock(sSubscriberLock);
729 if (!autolock.IsLocked())
730 return;
732 int32 count = sSubscribers.CountItems();
733 for (int32 i = 0; i < count; i++) {
734 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
735 if (*messenger == subscriber) {
736 sSubscribers.RemoveItem(i);
737 delete messenger;
738 break;
744 void
745 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref)
747 if ((flags & B_BACKGROUND_APP) != 0
748 || strcasecmp(sig, kDeskbarSignature) == 0) {
749 // don't add if a background app or Deskbar itself
750 return;
753 BAutolock autolock(sSubscriberLock);
754 if (!autolock.IsLocked())
755 return;
757 // have we already seen this team, is this another instance of
758 // a known app?
759 BarTeamInfo* multiLaunchTeam = NULL;
760 int32 teamCount = sBarTeamInfoList.CountItems();
761 for (int32 i = 0; i < teamCount; i++) {
762 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
763 if (barInfo->teams->HasItem((void*)(addr_t)team))
764 return;
765 if (strcasecmp(barInfo->sig, sig) == 0)
766 multiLaunchTeam = barInfo;
769 if (multiLaunchTeam != NULL) {
770 multiLaunchTeam->teams->AddItem((void*)(addr_t)team);
772 int32 subsCount = sSubscribers.CountItems();
773 if (subsCount > 0) {
774 BMessage message(kAddTeam);
775 message.AddInt32("team", team);
776 message.AddString("sig", multiLaunchTeam->sig);
778 for (int32 i = 0; i < subsCount; i++)
779 ((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message);
781 return;
784 BFile file(ref, B_READ_ONLY);
785 BAppFileInfo appMime(&file);
787 BString name;
788 if (!gLocalizedNamePreferred
789 || BLocaleRoster::Default()->GetLocalizedFileName(name, *ref)
790 != B_OK) {
791 name = ref->name;
794 BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig),
795 NULL, strdup(name.String()));
796 FetchAppIcon(barInfo);
797 barInfo->teams->AddItem((void*)(addr_t)team);
798 sBarTeamInfoList.AddItem(barInfo);
800 int32 subsCount = sSubscribers.CountItems();
801 if (subsCount > 0) {
802 for (int32 i = 0; i < subsCount; i++) {
803 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
804 BMessage message(B_SOME_APP_LAUNCHED);
806 BList* tList = new BList(*(barInfo->teams));
807 message.AddPointer("teams", tList);
809 BBitmap* icon = new BBitmap(barInfo->icon);
810 ASSERT(icon);
812 message.AddPointer("icon", icon);
814 message.AddInt32("flags", static_cast<int32>(barInfo->flags));
815 message.AddString("name", barInfo->name);
816 message.AddString("sig", barInfo->sig);
818 messenger->SendMessage(&message);
824 void
825 TBarApp::RemoveTeam(team_id team)
827 BAutolock autolock(sSubscriberLock);
828 if (!autolock.IsLocked())
829 return;
831 int32 teamCount = sBarTeamInfoList.CountItems();
832 for (int32 i = 0; i < teamCount; i++) {
833 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
834 if (barInfo->teams->HasItem((void*)(addr_t)team)) {
835 int32 subsCount = sSubscribers.CountItems();
836 if (subsCount > 0) {
837 BMessage message((barInfo->teams->CountItems() == 1)
838 ? B_SOME_APP_QUIT : kRemoveTeam);
840 message.AddInt32("team", team);
841 for (int32 i = 0; i < subsCount; i++) {
842 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
843 messenger->SendMessage(&message);
847 barInfo->teams->RemoveItem((void*)(addr_t)team);
848 if (barInfo->teams->CountItems() < 1) {
849 delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i);
850 return;
857 void
858 TBarApp::ResizeTeamIcons()
860 for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) {
861 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
862 if ((barInfo->flags & B_BACKGROUND_APP) == 0
863 && strcasecmp(barInfo->sig, kDeskbarSignature) != 0) {
864 FetchAppIcon(barInfo);
870 int32
871 TBarApp::IconSize()
873 return fSettings.iconSize;
877 void
878 TBarApp::ShowPreferencesWindow()
880 if (fPreferencesWindow == NULL) {
881 fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240));
882 fPreferencesWindow->Show();
883 } else if (fPreferencesWindow->Lock()) {
884 if (fPreferencesWindow->IsHidden())
885 fPreferencesWindow->Show();
886 else
887 fPreferencesWindow->Activate();
889 fPreferencesWindow->Unlock();
894 void
895 TBarApp::QuitPreferencesWindow()
897 if (fPreferencesWindow == NULL)
898 return;
900 if (fPreferencesWindow->Lock()) {
901 fPreferencesWindow->Quit();
902 // Quit() destroys the window so don't unlock
903 fPreferencesWindow = NULL;
908 void
909 TBarApp::FetchAppIcon(BarTeamInfo* barInfo)
911 int32 width = IconSize();
912 int32 index = (width - kMinimumIconSize) / kIconSizeInterval;
914 // first look in the icon cache
915 barInfo->icon = barInfo->iconCache[index];
916 if (barInfo->icon != NULL)
917 return;
919 // icon wasn't in cache, get it from be_roster and cache it
920 app_info appInfo;
921 icon_size size = width >= 31 ? B_LARGE_ICON : B_MINI_ICON;
922 BBitmap* icon = new BBitmap(IconRect(), kIconColorSpace);
923 if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) {
924 // fetch the app icon
925 BFile file(&appInfo.ref, B_READ_ONLY);
926 BAppFileInfo appMime(&file);
927 if (appMime.GetIcon(icon, size) == B_OK) {
928 delete barInfo->iconCache[index];
929 barInfo->iconCache[index] = barInfo->icon = icon;
930 return;
934 // couldn't find the app icon
935 // fetch the generic 3 boxes icon and cache it
936 BMimeType defaultAppMime;
937 defaultAppMime.SetTo(B_APP_MIME_TYPE);
938 if (defaultAppMime.GetIcon(icon, size) == B_OK) {
939 delete barInfo->iconCache[index];
940 barInfo->iconCache[index] = barInfo->icon = icon;
941 return;
944 // couldn't find generic 3 boxes icon
945 // fill with transparent
946 uint8* iconBits = (uint8*)icon->Bits();
947 if (icon->ColorSpace() == B_RGBA32) {
948 int32 i = 0;
949 while (i < icon->BitsLength()) {
950 iconBits[i++] = B_TRANSPARENT_32_BIT.red;
951 iconBits[i++] = B_TRANSPARENT_32_BIT.green;
952 iconBits[i++] = B_TRANSPARENT_32_BIT.blue;
953 iconBits[i++] = B_TRANSPARENT_32_BIT.alpha;
955 } else {
956 // Assume B_CMAP8
957 for (int32 i = 0; i < icon->BitsLength(); i++)
958 iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8;
961 delete barInfo->iconCache[index];
962 barInfo->iconCache[index] = barInfo->icon = icon;
966 BRect
967 TBarApp::IconRect()
969 int32 iconSize = IconSize();
970 return BRect(0, 0, iconSize - 1, iconSize - 1);
974 // #pragma mark -
977 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon,
978 char* name)
980 teams(teams),
981 flags(flags),
982 sig(sig),
983 icon(icon),
984 name(name)
986 _Init();
990 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info)
992 teams(new BList(*info.teams)),
993 flags(info.flags),
994 sig(strdup(info.sig)),
995 icon(new BBitmap(*info.icon)),
996 name(strdup(info.name))
998 _Init();
1002 BarTeamInfo::~BarTeamInfo()
1004 delete teams;
1005 free(sig);
1006 free(name);
1007 for (int32 i = 0; i < kIconCacheCount; i++)
1008 delete iconCache[i];
1012 void
1013 BarTeamInfo::_Init()
1015 for (int32 i = 0; i < kIconCacheCount; i++)
1016 iconCache[i] = NULL;