repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / deskbar / BarApp.cpp
blob6f64a98e4aa9c0acfc7c6804a2813cd54b2e28ed
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 BServer(kDeskbarSignature, true, NULL),
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 = gMinimumWindowWidth;
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 // constrain width setting within limits
338 if (settings.width < gMinimumWindowWidth)
339 settings.width = gMinimumWindowWidth;
340 else if (settings.width > gMaximumWindowWidth)
341 settings.width = gMaximumWindowWidth;
343 filePath = dirPath;
344 filePath.Append(clockSettingsFileName);
345 fClockSettingsFile = new BFile(filePath.Path(), O_RDWR);
346 if (fClockSettingsFile->InitCheck() != B_OK) {
347 BDirectory theDir(dirPath.Path());
348 if (theDir.InitCheck() == B_OK)
349 theDir.CreateFile(clockSettingsFileName, fClockSettingsFile);
352 if (fClockSettingsFile->InitCheck() == B_OK
353 && prefs.Unflatten(fClockSettingsFile) == B_OK) {
354 clock.showSeconds = prefs.GetBool("showSeconds", false);
355 clock.showDayOfWeek = prefs.GetBool("showDayOfWeek", false);
356 clock.showTimeZone = prefs.GetBool("showTimeZone", false);
360 fSettings = settings;
361 fClockSettings = clock;
365 void
366 TBarApp::MessageReceived(BMessage* message)
368 switch (message->what) {
369 // BDeskbar originating messages we can handle
370 case kMsgIsAlwaysOnTop:
372 BMessage reply('rply');
373 reply.AddBool("always on top", fSettings.alwaysOnTop);
374 message->SendReply(&reply);
375 break;
377 case kMsgIsAutoRaise:
379 BMessage reply('rply');
380 reply.AddBool("auto raise", fSettings.autoRaise);
381 message->SendReply(&reply);
382 break;
384 case kMsgIsAutoHide:
386 BMessage reply('rply');
387 reply.AddBool("auto hide", fSettings.autoHide);
388 message->SendReply(&reply);
389 break;
392 // pass rest of BDeskbar originating messages onto the window
393 // (except for setters handled below)
394 case kMsgLocation:
395 case kMsgSetLocation:
396 case kMsgIsExpanded:
397 case kMsgExpand:
398 case kMsgGetItemInfo:
399 case kMsgHasItem:
400 case kMsgCountItems:
401 case kMsgAddView:
402 case kMsgRemoveItem:
403 case kMsgAddAddOn:
404 fBarWindow->PostMessage(message);
405 break;
407 case kConfigShow:
408 ShowPreferencesWindow();
409 break;
411 case kConfigQuit:
412 QuitPreferencesWindow();
413 break;
415 case kStateChanged:
416 if (fPreferencesWindow != NULL)
417 fPreferencesWindow->PostMessage(kStateChanged);
418 break;
420 case kShowDeskbarMenu:
421 if (fBarWindow->Lock()) {
422 fBarWindow->ShowDeskbarMenu();
423 fBarWindow->Unlock();
425 break;
427 case kShowTeamMenu:
428 if (fBarWindow->Lock()) {
429 fBarWindow->ShowTeamMenu();
430 fBarWindow->Unlock();
432 break;
434 case kUpdateRecentCounts:
435 int32 count;
436 bool enabled;
438 if (message->FindInt32("applications", &count) == B_OK)
439 fSettings.recentAppsCount = count;
440 if (message->FindBool("applicationsEnabled", &enabled) == B_OK)
441 fSettings.recentAppsEnabled = enabled && count > 0;
443 if (message->FindInt32("folders", &count) == B_OK)
444 fSettings.recentFoldersCount = count;
445 if (message->FindBool("foldersEnabled", &enabled) == B_OK)
446 fSettings.recentFoldersEnabled = enabled && count > 0;
448 if (message->FindInt32("documents", &count) == B_OK)
449 fSettings.recentDocsCount = count;
450 if (message->FindBool("documentsEnabled", &enabled) == B_OK)
451 fSettings.recentDocsEnabled = enabled && count > 0;
453 if (fPreferencesWindow != NULL)
454 fPreferencesWindow->PostMessage(kUpdatePreferences);
455 break;
457 case B_SOME_APP_LAUNCHED:
459 team_id team = -1;
460 message->FindInt32("be:team", &team);
462 uint32 flags = 0;
463 message->FindInt32("be:flags", (int32*)&flags);
465 const char* signature = NULL;
466 message->FindString("be:signature", &signature);
468 entry_ref ref;
469 message->FindRef("be:ref", &ref);
471 AddTeam(team, flags, signature, &ref);
472 break;
475 case B_SOME_APP_QUIT:
477 team_id team = -1;
478 message->FindInt32("be:team", &team);
479 RemoveTeam(team);
480 break;
483 case B_ARCHIVED_OBJECT:
484 // TODO: what's this???
485 message->AddString("special", "Alex Osadzinski");
486 fStatusViewMessenger.SendMessage(message);
487 break;
489 case kToggleDraggers:
490 if (BDragger::AreDraggersDrawn())
491 BDragger::HideAllDraggers();
492 else
493 BDragger::ShowAllDraggers();
494 break;
496 case kMsgAlwaysOnTop: // from BDeskbar
497 case kAlwaysTop:
498 fSettings.alwaysOnTop = !fSettings.alwaysOnTop;
500 if (fPreferencesWindow != NULL)
501 fPreferencesWindow->PostMessage(kUpdatePreferences);
503 fBarWindow->SetFeel(fSettings.alwaysOnTop
504 ? B_FLOATING_ALL_WINDOW_FEEL
505 : B_NORMAL_WINDOW_FEEL);
506 break;
508 case kMsgAutoRaise: // from BDeskbar
509 case kAutoRaise:
510 fSettings.autoRaise = fSettings.alwaysOnTop ? false
511 : !fSettings.autoRaise;
513 if (fPreferencesWindow != NULL)
514 fPreferencesWindow->PostMessage(kUpdatePreferences);
515 break;
517 case kMsgAutoHide: // from BDeskbar
518 case kAutoHide:
519 fSettings.autoHide = !fSettings.autoHide;
521 if (fPreferencesWindow != NULL)
522 fPreferencesWindow->PostMessage(kUpdatePreferences);
524 fBarWindow->Lock();
525 fBarView->HideDeskbar(fSettings.autoHide);
526 fBarWindow->Unlock();
527 break;
529 case kTrackerFirst:
530 fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst;
532 if (fPreferencesWindow != NULL)
533 fPreferencesWindow->PostMessage(kUpdatePreferences);
535 // if mini mode we don't need to update the view
536 if (fBarView->MiniState())
537 break;
539 fBarWindow->Lock();
540 fBarView->PlaceApplicationBar();
541 fBarWindow->Unlock();
542 break;
544 case kSortRunningApps:
545 fSettings.sortRunningApps = !fSettings.sortRunningApps;
547 if (fPreferencesWindow != NULL)
548 fPreferencesWindow->PostMessage(kUpdatePreferences);
550 // if mini mode we don't need to update the view
551 if (fBarView->MiniState())
552 break;
554 fBarWindow->Lock();
555 fBarView->PlaceApplicationBar();
556 fBarWindow->Unlock();
557 break;
559 case kUnsubscribe:
561 BMessenger messenger;
562 if (message->FindMessenger("messenger", &messenger) == B_OK)
563 Unsubscribe(messenger);
564 break;
567 case kSuperExpando:
568 fSettings.superExpando = !fSettings.superExpando;
570 if (fPreferencesWindow != NULL)
571 fPreferencesWindow->PostMessage(kUpdatePreferences);
573 // if mini mode we don't need to update the view
574 if (fBarView->MiniState())
575 break;
577 fBarWindow->Lock();
578 fBarView->PlaceApplicationBar();
579 fBarWindow->Unlock();
580 break;
582 case kExpandNewTeams:
583 fSettings.expandNewTeams = !fSettings.expandNewTeams;
585 if (fPreferencesWindow != NULL)
586 fPreferencesWindow->PostMessage(kUpdatePreferences);
588 // if mini mode we don't need to update the view
589 if (fBarView->MiniState())
590 break;
592 fBarWindow->Lock();
593 fBarView->PlaceApplicationBar();
594 fBarWindow->Unlock();
595 break;
597 case kHideLabels:
598 fSettings.hideLabels = !fSettings.hideLabels;
600 if (fPreferencesWindow != NULL)
601 fPreferencesWindow->PostMessage(kUpdatePreferences);
603 // if mini mode we don't need to update the view
604 if (fBarView->MiniState())
605 break;
607 fBarWindow->Lock();
608 fBarView->PlaceApplicationBar();
609 fBarWindow->Unlock();
610 break;
612 case kResizeTeamIcons:
614 int32 oldIconSize = fSettings.iconSize;
615 int32 iconSize;
616 if (message->FindInt32("be:value", &iconSize) != B_OK)
617 break;
619 fSettings.iconSize = iconSize * kIconSizeInterval;
621 // pin icon size between min and max values
622 if (fSettings.iconSize < kMinimumIconSize)
623 fSettings.iconSize = kMinimumIconSize;
624 else if (fSettings.iconSize > kMaximumIconSize)
625 fSettings.iconSize = kMaximumIconSize;
627 // don't resize if icon size hasn't changed
628 if (fSettings.iconSize == oldIconSize)
629 break;
631 ResizeTeamIcons();
633 if (fPreferencesWindow != NULL)
634 fPreferencesWindow->PostMessage(kUpdatePreferences);
636 // if mini mode we don't need to update the view
637 if (fBarView->MiniState())
638 break;
640 fBarWindow->Lock();
641 if (!fBarView->Vertical()) {
642 // Must also resize the Deskbar menu and replicant tray in
643 // horizontal mode
644 fBarView->PlaceDeskbarMenu();
645 fBarView->PlaceTray(false, false);
647 fBarView->PlaceApplicationBar();
648 fBarWindow->Unlock();
649 break;
652 case 'TASK':
653 fSwitcherMessenger.SendMessage(message);
654 break;
656 case kSuspendSystem:
657 // TODO: Call BRoster?
658 break;
660 case kRebootSystem:
661 case kShutdownSystem:
663 bool reboot = (message->what == kRebootSystem);
664 bool confirm;
665 message->FindBool("confirm", &confirm);
667 BRoster roster;
668 BRoster::Private rosterPrivate(roster);
669 status_t error = rosterPrivate.ShutDown(reboot, confirm, false);
670 if (error != B_OK)
671 fprintf(stderr, "Shutdown failed: %s\n", strerror(error));
673 break;
676 case kShowSplash:
677 run_be_about();
678 break;
680 case B_LOCALE_CHANGED:
682 BLocaleRoster::Default()->Refresh();
684 bool localize;
685 if (message->FindBool("filesys", &localize) == B_OK)
686 gLocalizedNamePreferred = localize;
688 // fall-through
690 case kRealignReplicants:
691 case kShowHideTime:
692 case kShowSeconds:
693 case kShowDayOfWeek:
694 case kShowTimeZone:
695 case kGetClockSettings:
696 fStatusViewMessenger.SendMessage(message);
697 // Notify the replicant tray (through BarView) that the time
698 // interval has changed and it should update the time view
699 // and reflow the tray icons.
700 break;
702 default:
703 BApplication::MessageReceived(message);
704 break;
709 void
710 TBarApp::RefsReceived(BMessage* refs)
712 entry_ref ref;
713 for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) {
714 BMessage refsReceived(B_REFS_RECEIVED);
715 refsReceived.AddRef("refs", &ref);
717 BEntry entry(&ref);
718 if (!entry.IsDirectory())
719 TrackerLaunch(&refsReceived, false);
724 void
725 TBarApp::Subscribe(const BMessenger &subscriber, BList* list)
727 // called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt
728 list->MakeEmpty();
730 BAutolock autolock(sSubscriberLock);
731 if (!autolock.IsLocked())
732 return;
734 int32 numTeams = sBarTeamInfoList.CountItems();
735 for (int32 i = 0; i < numTeams; i++) {
736 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
737 BarTeamInfo* newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo);
738 if (newBarInfo != NULL)
739 list->AddItem(newBarInfo);
742 int32 subsCount = sSubscribers.CountItems();
743 for (int32 i = 0; i < subsCount; i++) {
744 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
745 if (*messenger == subscriber)
746 return;
749 sSubscribers.AddItem(new BMessenger(subscriber));
753 void
754 TBarApp::Unsubscribe(const BMessenger &subscriber)
756 BAutolock autolock(sSubscriberLock);
757 if (!autolock.IsLocked())
758 return;
760 int32 count = sSubscribers.CountItems();
761 for (int32 i = 0; i < count; i++) {
762 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
763 if (*messenger == subscriber) {
764 sSubscribers.RemoveItem(i);
765 delete messenger;
766 break;
772 void
773 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref)
775 if ((flags & B_BACKGROUND_APP) != 0
776 || strcasecmp(sig, kDeskbarSignature) == 0) {
777 // don't add if a background app or Deskbar itself
778 return;
781 BAutolock autolock(sSubscriberLock);
782 if (!autolock.IsLocked())
783 return;
785 // have we already seen this team, is this another instance of
786 // a known app?
787 BarTeamInfo* multiLaunchTeam = NULL;
788 int32 teamCount = sBarTeamInfoList.CountItems();
789 for (int32 i = 0; i < teamCount; i++) {
790 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
791 if (barInfo->teams->HasItem((void*)(addr_t)team))
792 return;
793 if (strcasecmp(barInfo->sig, sig) == 0)
794 multiLaunchTeam = barInfo;
797 if (multiLaunchTeam != NULL) {
798 multiLaunchTeam->teams->AddItem((void*)(addr_t)team);
800 int32 subsCount = sSubscribers.CountItems();
801 if (subsCount > 0) {
802 BMessage message(kAddTeam);
803 message.AddInt32("team", team);
804 message.AddString("sig", multiLaunchTeam->sig);
806 for (int32 i = 0; i < subsCount; i++)
807 ((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message);
809 return;
812 BFile file(ref, B_READ_ONLY);
813 BAppFileInfo appMime(&file);
815 BString name;
816 if (!gLocalizedNamePreferred
817 || BLocaleRoster::Default()->GetLocalizedFileName(name, *ref)
818 != B_OK) {
819 name = ref->name;
822 BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig),
823 NULL, strdup(name.String()));
824 FetchAppIcon(barInfo);
825 barInfo->teams->AddItem((void*)(addr_t)team);
826 sBarTeamInfoList.AddItem(barInfo);
828 int32 subsCount = sSubscribers.CountItems();
829 if (subsCount > 0) {
830 for (int32 i = 0; i < subsCount; i++) {
831 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
832 BMessage message(B_SOME_APP_LAUNCHED);
834 BList* tList = new BList(*(barInfo->teams));
835 message.AddPointer("teams", tList);
837 BBitmap* icon = new BBitmap(barInfo->icon);
838 ASSERT(icon);
840 message.AddPointer("icon", icon);
842 message.AddInt32("flags", static_cast<int32>(barInfo->flags));
843 message.AddString("name", barInfo->name);
844 message.AddString("sig", barInfo->sig);
846 messenger->SendMessage(&message);
852 void
853 TBarApp::RemoveTeam(team_id team)
855 BAutolock autolock(sSubscriberLock);
856 if (!autolock.IsLocked())
857 return;
859 int32 teamCount = sBarTeamInfoList.CountItems();
860 for (int32 i = 0; i < teamCount; i++) {
861 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
862 if (barInfo->teams->HasItem((void*)(addr_t)team)) {
863 int32 subsCount = sSubscribers.CountItems();
864 if (subsCount > 0) {
865 BMessage message((barInfo->teams->CountItems() == 1)
866 ? B_SOME_APP_QUIT : kRemoveTeam);
868 message.AddInt32("team", team);
869 for (int32 i = 0; i < subsCount; i++) {
870 BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
871 messenger->SendMessage(&message);
875 barInfo->teams->RemoveItem((void*)(addr_t)team);
876 if (barInfo->teams->CountItems() < 1) {
877 delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i);
878 return;
885 void
886 TBarApp::ResizeTeamIcons()
888 for (int32 i = sBarTeamInfoList.CountItems() - 1; i >= 0; i--) {
889 BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
890 if ((barInfo->flags & B_BACKGROUND_APP) == 0
891 && strcasecmp(barInfo->sig, kDeskbarSignature) != 0) {
892 FetchAppIcon(barInfo);
898 int32
899 TBarApp::IconSize()
901 return fSettings.iconSize;
905 void
906 TBarApp::ShowPreferencesWindow()
908 if (fPreferencesWindow == NULL) {
909 fPreferencesWindow = new PreferencesWindow(BRect(100, 100, 320, 240));
910 fPreferencesWindow->Show();
911 } else if (fPreferencesWindow->Lock()) {
912 if (fPreferencesWindow->IsHidden())
913 fPreferencesWindow->Show();
914 else
915 fPreferencesWindow->Activate();
917 fPreferencesWindow->Unlock();
922 void
923 TBarApp::QuitPreferencesWindow()
925 if (fPreferencesWindow == NULL)
926 return;
928 if (fPreferencesWindow->Lock()) {
929 fPreferencesWindow->Quit();
930 // Quit() destroys the window so don't unlock
931 fPreferencesWindow = NULL;
936 void
937 TBarApp::FetchAppIcon(BarTeamInfo* barInfo)
939 int32 width = IconSize();
940 int32 index = (width - kMinimumIconSize) / kIconSizeInterval;
942 // first look in the icon cache
943 barInfo->icon = barInfo->iconCache[index];
944 if (barInfo->icon != NULL)
945 return;
947 // icon wasn't in cache, get it from be_roster and cache it
948 app_info appInfo;
949 icon_size size = width >= 31 ? B_LARGE_ICON : B_MINI_ICON;
950 BBitmap* icon = new BBitmap(IconRect(), kIconColorSpace);
951 if (be_roster->GetAppInfo(barInfo->sig, &appInfo) == B_OK) {
952 // fetch the app icon
953 BFile file(&appInfo.ref, B_READ_ONLY);
954 BAppFileInfo appMime(&file);
955 if (appMime.GetIcon(icon, size) == B_OK) {
956 delete barInfo->iconCache[index];
957 barInfo->iconCache[index] = barInfo->icon = icon;
958 return;
962 // couldn't find the app icon
963 // fetch the generic 3 boxes icon and cache it
964 BMimeType defaultAppMime;
965 defaultAppMime.SetTo(B_APP_MIME_TYPE);
966 if (defaultAppMime.GetIcon(icon, size) == B_OK) {
967 delete barInfo->iconCache[index];
968 barInfo->iconCache[index] = barInfo->icon = icon;
969 return;
972 // couldn't find generic 3 boxes icon
973 // fill with transparent
974 uint8* iconBits = (uint8*)icon->Bits();
975 if (icon->ColorSpace() == B_RGBA32) {
976 int32 i = 0;
977 while (i < icon->BitsLength()) {
978 iconBits[i++] = B_TRANSPARENT_32_BIT.red;
979 iconBits[i++] = B_TRANSPARENT_32_BIT.green;
980 iconBits[i++] = B_TRANSPARENT_32_BIT.blue;
981 iconBits[i++] = B_TRANSPARENT_32_BIT.alpha;
983 } else {
984 // Assume B_CMAP8
985 for (int32 i = 0; i < icon->BitsLength(); i++)
986 iconBits[i] = B_TRANSPARENT_MAGIC_CMAP8;
989 delete barInfo->iconCache[index];
990 barInfo->iconCache[index] = barInfo->icon = icon;
994 BRect
995 TBarApp::IconRect()
997 int32 iconSize = IconSize();
998 return BRect(0, 0, iconSize - 1, iconSize - 1);
1002 // #pragma mark -
1005 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon,
1006 char* name)
1008 teams(teams),
1009 flags(flags),
1010 sig(sig),
1011 icon(icon),
1012 name(name)
1014 _Init();
1018 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info)
1020 teams(new BList(*info.teams)),
1021 flags(info.flags),
1022 sig(strdup(info.sig)),
1023 icon(new BBitmap(*info.icon)),
1024 name(strdup(info.name))
1026 _Init();
1030 BarTeamInfo::~BarTeamInfo()
1032 delete teams;
1033 free(sig);
1034 free(name);
1035 for (int32 i = 0; i < kIconCacheCount; i++)
1036 delete iconCache[i];
1040 void
1041 BarTeamInfo::_Init()
1043 for (int32 i = 0; i < kIconCacheCount; i++)
1044 iconCache[i] = NULL;