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