xref: /haiku/src/apps/deskbar/BarApp.cpp (revision c4b463c5cd2ae950989531a3caf7c1fa7c378573)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
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:
14 
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.
17 
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.
24 
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.
28 
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.
34 */
35 
36 #include <Debug.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #include <AppFileInfo.h>
41 #include <Autolock.h>
42 #include <Bitmap.h>
43 #include <Catalog.h>
44 #include <Directory.h>
45 #include <Dragger.h>
46 #include <File.h>
47 #include <FindDirectory.h>
48 #include <Locale.h>
49 #include <Mime.h>
50 #include <Path.h>
51 #include <Roster.h>
52 #include <RosterPrivate.h>
53 
54 #include "icons.h"
55 #include "tracker_private.h"
56 #include "BarApp.h"
57 #include "BarView.h"
58 #include "BarWindow.h"
59 #include "DeskbarUtils.h"
60 #include "FSUtils.h"
61 #include "PublicCommands.h"
62 #include "ResourceSet.h"
63 #include "Switcher.h"
64 #include "Utilities.h"
65 
66 
67 BLocker TBarApp::sSubscriberLock;
68 BList TBarApp::sBarTeamInfoList;
69 BList TBarApp::sSubscribers;
70 
71 
72 const uint32 kShowDeskbarMenu = 'BeMn';
73 const uint32 kShowTeamMenu = 'TmMn';
74 
75 
76 const BRect kIconRect(0.0f, 0.0f, 15.0f, 15.0f);
77 static const color_space kIconFormat = B_RGBA32;
78 
79 
80 int
81 main()
82 {
83 	TBarApp app;
84 	app.Run();
85 
86 	return B_OK;
87 }
88 
89 
90 TBarApp::TBarApp()
91 	:	BApplication(kDeskbarSignature),
92 		fSettingsFile(NULL),
93 		fPreferencesWindow(NULL)
94 {
95 	InitSettings();
96 	InitIconPreloader();
97 
98 	fBarWindow = new TBarWindow();
99 
100 	be_roster->StartWatching(this);
101 
102 	gLocalizedNamePreferred
103 		= BLocaleRoster::Default()->IsFilesystemTranslationPreferred();
104 
105 	sBarTeamInfoList.MakeEmpty();
106 
107 	BList teamList;
108 	int32 numTeams;
109 	be_roster->GetAppList(&teamList);
110 	numTeams = teamList.CountItems();
111 	for (int32 i = 0; i < numTeams; i++) {
112 		app_info appInfo;
113 		team_id tID = (team_id)teamList.ItemAt(i);
114 		if (be_roster->GetRunningAppInfo(tID, &appInfo) == B_OK) {
115 			AddTeam(appInfo.team, appInfo.flags, appInfo.signature,
116 				&appInfo.ref);
117 		}
118 	}
119 
120 	sSubscribers.MakeEmpty();
121 
122 	fSwitcherMessenger = BMessenger(new TSwitchManager(fSettings.switcherLoc));
123 
124 	fBarWindow->Show();
125 
126 	// Call UpdatePlacement() after the window is shown because expanded apps
127 	// need to resize the window.
128 	if (fBarWindow->Lock()) {
129 		BarView()->UpdatePlacement();
130 		fBarWindow->Unlock();
131 	}
132 
133 	// this messenger now targets the barview instead of the
134 	// statusview so that all additions to the tray
135 	// follow the same path
136 	fStatusViewMessenger = BMessenger(fBarWindow->FindView("BarView"));
137 }
138 
139 
140 TBarApp::~TBarApp()
141 {
142 	be_roster->StopWatching(this);
143 
144 	int32 teamCount = sBarTeamInfoList.CountItems();
145 	for (int32 i = 0; i < teamCount; i++) {
146 		BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
147 		delete barInfo;
148 	}
149 
150 	int32 subsCount = sSubscribers.CountItems();
151 	for (int32 i = 0; i < subsCount; i++) {
152 		BMessenger* messenger
153 			= static_cast<BMessenger*>(sSubscribers.ItemAt(i));
154 		delete messenger;
155 	}
156 	SaveSettings();
157 	delete fSettingsFile;
158 }
159 
160 
161 bool
162 TBarApp::QuitRequested()
163 {
164 	// don't allow user quitting
165 	if (CurrentMessage() && CurrentMessage()->FindBool("shortcut")) {
166 		// but allow quitting to hide fPreferencesWindow
167 		int32 index = 0;
168 		BWindow* window = NULL;
169 		while ((window = WindowAt(index++)) != NULL) {
170 			if (window == fPreferencesWindow) {
171 				if (fPreferencesWindow->Lock()) {
172 					if (fPreferencesWindow->IsActive())
173 						fPreferencesWindow->PostMessage(B_QUIT_REQUESTED);
174 					fPreferencesWindow->Unlock();
175 				}
176 				break;
177 			}
178 		}
179 		return false;
180 	}
181 
182 	// system quitting, call inherited to notify all loopers
183 	fBarWindow->SaveSettings();
184 	BApplication::QuitRequested();
185 	return true;
186 }
187 
188 
189 void
190 TBarApp::SaveSettings()
191 {
192 	if (fSettingsFile->InitCheck() == B_OK) {
193 		fSettingsFile->Seek(0, SEEK_SET);
194 		BMessage storedSettings;
195 		storedSettings.AddBool("vertical", fSettings.vertical);
196 		storedSettings.AddBool("left", fSettings.left);
197 		storedSettings.AddBool("top", fSettings.top);
198 		storedSettings.AddBool("ampmMode", fSettings.ampmMode);
199 
200 		storedSettings.AddInt32("state", fSettings.state);
201 		storedSettings.AddFloat("width", fSettings.width);
202 		storedSettings.AddBool("showTime", fSettings.showTime);
203 		storedSettings.AddPoint("switcherLoc", fSettings.switcherLoc);
204 		storedSettings.AddInt32("recentAppsCount", fSettings.recentAppsCount);
205 		storedSettings.AddInt32("recentDocsCount", fSettings.recentDocsCount);
206 		storedSettings.AddBool("timeShowSeconds", fSettings.timeShowSeconds);
207 		storedSettings.AddInt32("recentFoldersCount",
208 			fSettings.recentFoldersCount);
209 		storedSettings.AddBool("alwaysOnTop", fSettings.alwaysOnTop);
210 		storedSettings.AddBool("timeFullDate", fSettings.timeFullDate);
211 		storedSettings.AddBool("trackerAlwaysFirst",
212 			fSettings.trackerAlwaysFirst);
213 		storedSettings.AddBool("sortRunningApps", fSettings.sortRunningApps);
214 		storedSettings.AddBool("superExpando", fSettings.superExpando);
215 		storedSettings.AddBool("expandNewTeams", fSettings.expandNewTeams);
216 		storedSettings.AddBool("autoRaise", fSettings.autoRaise);
217 		storedSettings.AddBool("autoHide", fSettings.autoHide);
218 		storedSettings.AddBool("recentAppsEnabled",
219 			fSettings.recentAppsEnabled);
220 		storedSettings.AddBool("recentDocsEnabled",
221 			fSettings.recentDocsEnabled);
222 		storedSettings.AddBool("recentFoldersEnabled",
223 			fSettings.recentFoldersEnabled);
224 
225 		storedSettings.Flatten(fSettingsFile);
226 	}
227 }
228 
229 
230 void
231 TBarApp::InitSettings()
232 {
233 	desk_settings settings;
234 	settings.vertical = true;
235 	settings.left = false;
236 	settings.top = true;
237 	settings.ampmMode = true;
238 	settings.showTime = true;
239 	settings.state = kExpandoState;
240 	settings.width = 0;
241 	settings.switcherLoc = BPoint(5000, 5000);
242 	settings.recentAppsCount = 10;
243 	settings.recentDocsCount = 10;
244 	settings.timeShowSeconds = false;
245 	settings.recentFoldersCount = 10;
246 	settings.alwaysOnTop = false;
247 	settings.timeFullDate = false;
248 	settings.trackerAlwaysFirst = false;
249 	settings.sortRunningApps = false;
250 	settings.superExpando = false;
251 	settings.expandNewTeams = false;
252 	settings.autoRaise = false;
253 	settings.autoHide = false;
254 	settings.recentAppsEnabled = true;
255 	settings.recentDocsEnabled = true;
256 	settings.recentFoldersEnabled = true;
257 
258 	BPath dirPath;
259 	const char* settingsFileName = "Deskbar_settings";
260 
261 	find_directory(B_USER_DESKBAR_DIRECTORY, &dirPath, true);
262 	// just make it
263 
264 	if (find_directory (B_USER_SETTINGS_DIRECTORY, &dirPath, true) == B_OK) {
265 		BPath filePath = dirPath;
266 		filePath.Append(settingsFileName);
267 		fSettingsFile = new BFile(filePath.Path(), O_RDWR);
268 		if (fSettingsFile->InitCheck() != B_OK) {
269 			BDirectory theDir(dirPath.Path());
270 			if (theDir.InitCheck() == B_OK)
271 				theDir.CreateFile(settingsFileName, fSettingsFile);
272 		}
273 
274 		BMessage storedSettings;
275 		if (fSettingsFile->InitCheck() == B_OK
276 			&& storedSettings.Unflatten(fSettingsFile) == B_OK) {
277 			storedSettings.FindBool("vertical", &settings.vertical);
278 			storedSettings.FindBool("left", &settings.left);
279 			storedSettings.FindBool("top", &settings.top);
280 			storedSettings.FindBool("ampmMode", &settings.ampmMode);
281 
282 			storedSettings.FindInt32("state", (int32*)&settings.state);
283 			storedSettings.FindFloat("width", &settings.width);
284 			storedSettings.FindBool("showTime", &settings.showTime);
285 			storedSettings.FindPoint("switcherLoc", &settings.switcherLoc);
286 			storedSettings.FindInt32("recentAppsCount",
287 				&settings.recentAppsCount);
288 			storedSettings.FindInt32("recentDocsCount",
289 				&settings.recentDocsCount);
290 			storedSettings.FindBool("timeShowSeconds",
291 				&settings.timeShowSeconds);
292 			storedSettings.FindInt32("recentFoldersCount",
293 				&settings.recentFoldersCount);
294 			storedSettings.FindBool("alwaysOnTop", &settings.alwaysOnTop);
295 			storedSettings.FindBool("timeFullDate", &settings.timeFullDate);
296 			storedSettings.FindBool("trackerAlwaysFirst",
297 				&settings.trackerAlwaysFirst);
298 			storedSettings.FindBool("sortRunningApps",
299 				&settings.sortRunningApps);
300 			storedSettings.FindBool("superExpando", &settings.superExpando);
301 			storedSettings.FindBool("expandNewTeams", &settings.expandNewTeams);
302 			storedSettings.FindBool("autoRaise", &settings.autoRaise);
303 			storedSettings.FindBool("autoHide", &settings.autoHide);
304 			storedSettings.FindBool("recentAppsEnabled",
305 				&settings.recentAppsEnabled);
306 			storedSettings.FindBool("recentDocsEnabled",
307 				&settings.recentDocsEnabled);
308 			storedSettings.FindBool("recentFoldersEnabled",
309 				&settings.recentFoldersEnabled);
310 		}
311 	}
312 
313 	fSettings = settings;
314 }
315 
316 
317 void
318 TBarApp::MessageReceived(BMessage* message)
319 {
320 	switch (message->what) {
321 		case 'gloc':
322 		case 'sloc':
323 		case 'gexp':
324 		case 'sexp':
325 		case 'info':
326 		case 'exst':
327 		case 'cwnt':
328 		case 'icon':
329 		case 'remv':
330 		case 'adon':
331 			// pass any BDeskbar originating messages on to the window
332 			fBarWindow->PostMessage(message);
333 			break;
334 
335 		case kConfigShow:
336 			ShowPreferencesWindow();
337 			break;
338 
339 		case kStateChanged:
340 			fPreferencesWindow->PostMessage(kStateChanged);
341 			break;
342 
343 		case kShowDeskbarMenu:
344 			if (fBarWindow->Lock()) {
345 				fBarWindow->ShowDeskbarMenu();
346 				fBarWindow->Unlock();
347 			}
348 			break;
349 
350 		case kShowTeamMenu:
351 			if (fBarWindow->Lock()) {
352 				fBarWindow->ShowTeamMenu();
353 				fBarWindow->Unlock();
354 			}
355 			break;
356 
357 		case kUpdateRecentCounts:
358 			int32 count;
359 			bool enabled;
360 
361 			if (message->FindInt32("applications", &count) == B_OK)
362 				fSettings.recentAppsCount = count;
363 			if (message->FindBool("applicationsEnabled", &enabled) == B_OK)
364 				fSettings.recentAppsEnabled = enabled && count > 0;
365 
366 			if (message->FindInt32("folders", &count) == B_OK)
367 				fSettings.recentFoldersCount = count;
368 			if (message->FindBool("foldersEnabled", &enabled) == B_OK)
369 				fSettings.recentFoldersEnabled = enabled && count > 0;
370 
371 			if (message->FindInt32("documents", &count) == B_OK)
372 				fSettings.recentDocsCount = count;
373 			if (message->FindBool("documentsEnabled", &enabled) == B_OK)
374 				fSettings.recentDocsEnabled = enabled && count > 0;
375 			break;
376 
377 		case kConfigClose:
378 			fPreferencesWindow = NULL;
379 			break;
380 
381 		case B_SOME_APP_LAUNCHED:
382 		{
383 			team_id team = -1;
384 			message->FindInt32("be:team", &team);
385 
386 			uint32 flags = 0;
387 			message->FindInt32("be:flags", (long*)&flags);
388 
389 			const char* sig = NULL;
390 			message->FindString("be:signature", &sig);
391 
392 			entry_ref ref;
393 			message->FindRef("be:ref", &ref);
394 
395 			AddTeam(team, flags, sig, &ref);
396 			break;
397 		}
398 
399 		case B_SOME_APP_QUIT:
400 		{
401 			team_id team = -1;
402 			message->FindInt32("be:team", &team);
403 			RemoveTeam(team);
404 			break;
405 		}
406 
407 		case B_ARCHIVED_OBJECT:
408 			// TODO: what's this???
409 			message->AddString("special", "Alex Osadzinski");
410 			fStatusViewMessenger.SendMessage(message);
411 			break;
412 
413 		case kToggleDraggers:
414 			if (BDragger::AreDraggersDrawn())
415 				BDragger::HideAllDraggers();
416 			else
417 				BDragger::ShowAllDraggers();
418 			break;
419 
420 		case kAlwaysTop:
421 			fSettings.alwaysOnTop = !fSettings.alwaysOnTop;
422 			fBarWindow->SetFeel(fSettings.alwaysOnTop ?
423 				B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL);
424 			fPreferencesWindow->PostMessage(kStateChanged);
425 			break;
426 
427 		case kAutoRaise:
428 			fSettings.autoRaise = fSettings.alwaysOnTop ? false :
429 				!fSettings.autoRaise;
430 
431 			fBarWindow->Lock();
432 			BarView()->UpdateEventMask();
433 			fBarWindow->Unlock();
434 			break;
435 
436 		case kAutoHide:
437 			fSettings.autoHide = !fSettings.autoHide;
438 
439 			fBarWindow->Lock();
440 			BarView()->UpdateEventMask();
441 			BarView()->HideDeskbar(fSettings.autoHide);
442 			fBarWindow->Unlock();
443 			break;
444 
445 		case kTrackerFirst:
446 			fSettings.trackerAlwaysFirst = !fSettings.trackerAlwaysFirst;
447 
448 			fBarWindow->Lock();
449 			BarView()->UpdatePlacement();
450 			fBarWindow->Unlock();
451 			break;
452 
453 		case kSortRunningApps:
454 			fSettings.sortRunningApps = !fSettings.sortRunningApps;
455 
456 			fBarWindow->Lock();
457 			BarView()->UpdatePlacement();
458 			fBarWindow->Unlock();
459 			break;
460 
461 		case kUnsubscribe:
462 		{
463 			BMessenger messenger;
464 			if (message->FindMessenger("messenger", &messenger) == B_OK)
465 				Unsubscribe(messenger);
466 			break;
467 		}
468 
469 		case kSuperExpando:
470 			fSettings.superExpando = !fSettings.superExpando;
471 
472 			fBarWindow->Lock();
473 			BarView()->UpdatePlacement();
474 			fBarWindow->Unlock();
475 			break;
476 
477 		case kExpandNewTeams:
478 			fSettings.expandNewTeams = !fSettings.expandNewTeams;
479 
480 			fBarWindow->Lock();
481 			BarView()->UpdatePlacement();
482 			fBarWindow->Unlock();
483 			break;
484 
485 		case 'TASK':
486 			fSwitcherMessenger.SendMessage(message);
487 			break;
488 
489 		case kSuspendSystem:
490 			// TODO: Call BRoster?
491 			break;
492 
493 		case kRebootSystem:
494 		case kShutdownSystem:
495 		{
496 			bool reboot = (message->what == kRebootSystem);
497 			bool confirm;
498 			message->FindBool("confirm", &confirm);
499 
500 			BRoster roster;
501 			BRoster::Private rosterPrivate(roster);
502 			status_t error = rosterPrivate.ShutDown(reboot, confirm, false);
503 			if (error != B_OK)
504 				fprintf(stderr, "Shutdown failed: %s\n", strerror(error));
505 
506 			break;
507 		}
508 
509 		case kShowSplash:
510 			run_be_about();
511 			break;
512 
513 		case kRestartTracker:
514 		{
515 			BRoster roster;
516 			roster.Launch(kTrackerSignature);
517 			break;
518 		}
519 
520 		case B_LOCALE_CHANGED:
521 		{
522 			BLocaleRoster::Default()->Refresh();
523 
524 			bool localize;
525 			if (message->FindBool("filesys", &localize) == B_OK)
526 				gLocalizedNamePreferred = localize;
527 
528 			BMessenger(fBarWindow->FindView("_deskbar_tv_")).SendMessage(
529 				message);
530 				// Notify the TimeView that the format has changed and it should
531 				// recompute its size
532 			break;
533 		}
534 
535 		default:
536 			BApplication::MessageReceived(message);
537 			break;
538 	}
539 }
540 
541 
542 void
543 TBarApp::RefsReceived(BMessage* refs)
544 {
545 	entry_ref ref;
546 	for (int32 i = 0; refs->FindRef("refs", i, &ref) == B_OK; i++) {
547 		BMessage refsReceived(B_REFS_RECEIVED);
548 		refsReceived.AddRef("refs", &ref);
549 
550 		BEntry entry(&ref);
551 		if (!entry.IsDirectory())
552 			TrackerLaunch(&refsReceived, false);
553 	}
554 }
555 
556 
557 void
558 TBarApp::Subscribe(const BMessenger &subscriber, BList* list)
559 {
560 	// called when ExpandoMenuBar, TeamMenu or Switcher are built/rebuilt
561 	list->MakeEmpty();
562 
563 	BAutolock autolock(sSubscriberLock);
564 	if (!autolock.IsLocked())
565 		return;
566 
567 	int32 numTeams = sBarTeamInfoList.CountItems();
568 	for (int32 i = 0; i < numTeams; i++) {
569 		BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
570 		BarTeamInfo* newBarInfo = new (std::nothrow) BarTeamInfo(*barInfo);
571 		if (newBarInfo != NULL)
572 			list->AddItem(newBarInfo);
573 	}
574 
575 	int32 subsCount = sSubscribers.CountItems();
576 	for (int32 i = 0; i < subsCount; i++) {
577 		BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
578 		if (*messenger == subscriber)
579 			return;
580 	}
581 
582 	sSubscribers.AddItem(new BMessenger(subscriber));
583 }
584 
585 
586 void
587 TBarApp::Unsubscribe(const BMessenger &subscriber)
588 {
589 	BAutolock autolock(sSubscriberLock);
590 	if (!autolock.IsLocked())
591 		return;
592 
593 	int32 count = sSubscribers.CountItems();
594 	for (int32 i = 0; i < count; i++) {
595 		BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
596 		if (*messenger == subscriber) {
597 			sSubscribers.RemoveItem(i);
598 			delete messenger;
599 			break;
600 		}
601 	}
602 }
603 
604 
605 void
606 TBarApp::AddTeam(team_id team, uint32 flags, const char* sig, entry_ref* ref)
607 {
608 	BAutolock autolock(sSubscriberLock);
609 	if (!autolock.IsLocked())
610 		return;
611 
612 	// have we already seen this team, is this another instance of
613 	// a known app?
614 	BarTeamInfo* multiLaunchTeam = NULL;
615 	int32 teamCount = sBarTeamInfoList.CountItems();
616 	for (int32 i = 0; i < teamCount; i++) {
617 		BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
618 		if (barInfo->teams->HasItem((void*)team))
619 			return;
620 		if (strcasecmp(barInfo->sig, sig) == 0)
621 			multiLaunchTeam = barInfo;
622 	}
623 
624 	if (multiLaunchTeam != NULL) {
625 		multiLaunchTeam->teams->AddItem((void*)team);
626 
627 		int32 subsCount = sSubscribers.CountItems();
628 		if (subsCount > 0) {
629 			BMessage message(kAddTeam);
630 			message.AddInt32("team", team);
631 			message.AddString("sig", multiLaunchTeam->sig);
632 
633 			for (int32 i = 0; i < subsCount; i++)
634 				((BMessenger*)sSubscribers.ItemAt(i))->SendMessage(&message);
635 		}
636 		return;
637 	}
638 
639 	BFile file(ref, B_READ_ONLY);
640 	BAppFileInfo appMime(&file);
641 
642 	BString name;
643 	if (!gLocalizedNamePreferred
644 		|| BLocaleRoster::Default()->GetLocalizedFileName(name, *ref) != B_OK)
645 		name = ref->name;
646 
647 	BarTeamInfo* barInfo = new BarTeamInfo(new BList(), flags, strdup(sig),
648 		new BBitmap(kIconRect, kIconFormat), strdup(name.String()));
649 
650 	barInfo->teams->AddItem((void*)team);
651 	if (appMime.GetIcon(barInfo->icon, B_MINI_ICON) != B_OK)
652 		appMime.GetTrackerIcon(barInfo->icon, B_MINI_ICON);
653 
654 	sBarTeamInfoList.AddItem(barInfo);
655 
656 	if (fSettings.expandNewTeams)
657 		BarView()->AddExpandedItem(sig);
658 
659 	int32 subsCount = sSubscribers.CountItems();
660 	if (subsCount > 0) {
661 		for (int32 i = 0; i < subsCount; i++) {
662 			BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
663 			BMessage message(B_SOME_APP_LAUNCHED);
664 
665 			BList* tList = new BList(*(barInfo->teams));
666 			message.AddPointer("teams", tList);
667 
668 			BBitmap* icon = new BBitmap(barInfo->icon);
669 			ASSERT(icon);
670 
671 			message.AddPointer("icon", icon);
672 
673 			message.AddInt32("flags", static_cast<int32>(barInfo->flags));
674 			message.AddString("name", barInfo->name);
675 			message.AddString("sig", barInfo->sig);
676 
677 			messenger->SendMessage(&message);
678 		}
679 	}
680 }
681 
682 
683 void
684 TBarApp::RemoveTeam(team_id team)
685 {
686 	BAutolock autolock(sSubscriberLock);
687 	if (!autolock.IsLocked())
688 		return;
689 
690 	int32 teamCount = sBarTeamInfoList.CountItems();
691 	for (int32 i = 0; i < teamCount; i++) {
692 		BarTeamInfo* barInfo = (BarTeamInfo*)sBarTeamInfoList.ItemAt(i);
693 		if (barInfo->teams->HasItem((void*)team)) {
694 			int32 subsCount = sSubscribers.CountItems();
695 			if (subsCount > 0) {
696 				BMessage message((barInfo->teams->CountItems() == 1) ?
697 					B_SOME_APP_QUIT : kRemoveTeam);
698 
699 				message.AddInt32("team", team);
700 				for (int32 i = 0; i < subsCount; i++) {
701 					BMessenger* messenger = (BMessenger*)sSubscribers.ItemAt(i);
702 					messenger->SendMessage(&message);
703 				}
704 			}
705 
706 			barInfo->teams->RemoveItem((void*)team);
707 			if (barInfo->teams->CountItems() < 1) {
708 				delete (BarTeamInfo*)sBarTeamInfoList.RemoveItem(i);
709 				return;
710 			}
711 		}
712 	}
713 }
714 
715 
716 void
717 TBarApp::ShowPreferencesWindow()
718 {
719 	if (fPreferencesWindow)
720 		fPreferencesWindow->Activate();
721 	else {
722 		fPreferencesWindow = new PreferencesWindow(BRect(0, 0, 320, 240));
723 		fPreferencesWindow->Show();
724 	}
725 }
726 
727 
728 //	#pragma mark -
729 
730 
731 BarTeamInfo::BarTeamInfo(BList* teams, uint32 flags, char* sig, BBitmap* icon,
732 	char* name)
733 	:	teams(teams),
734 		flags(flags),
735 		sig(sig),
736 		icon(icon),
737 		name(name)
738 {
739 }
740 
741 
742 BarTeamInfo::BarTeamInfo(const BarTeamInfo &info)
743 	:	teams(new BList(*info.teams)),
744 		flags(info.flags),
745 		sig(strdup(info.sig)),
746 		icon(new BBitmap(*info.icon)),
747 		name(strdup(info.name))
748 {
749 }
750 
751 
752 BarTeamInfo::~BarTeamInfo()
753 {
754 	delete teams;
755 	free(sig);
756 	delete icon;
757 	free(name);
758 }
759 
760