xref: /haiku/src/apps/deskbar/BarWindow.cpp (revision 41281cf362916855e6eb9ad1d728d919863a1e81)
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 <stdio.h>
36 #include <Application.h>
37 #include <Directory.h>
38 #include <FindDirectory.h>
39 #include <Path.h>
40 #include <Debug.h>
41 #include <File.h>
42 #include <MenuItem.h>
43 #include <MessageFilter.h>
44 #include <Screen.h>
45 
46 #include "BarWindow.h"
47 #include "BarApp.h"
48 #include "BarMenuBar.h"
49 #include "BarView.h"
50 #include "BeMenu.h"
51 #include "PublicCommands.h"
52 #include "StatusView.h"
53 #include "tracker_private.h"
54 
55 
56 // This is a very ugly hack to be able to call the private BMenuBar::StartMenuBar()
57 // method from the TBarWindow::ShowBeMenu() method.
58 // Don't do this at home -- but why the hell is this method private?
59 #if __MWERKS__
60 	extern "C" void StartMenuBar__8BMenuBarFlbbP5BRect(BMenuBar *,int32,bool,bool,BRect *);
61 #elif __GCC__ <= 2
62 	extern "C" void StartMenuBar__8BMenuBarlbT2P5BRect(BMenuBar *,int32,bool,bool,BRect *);
63 #else
64 #	error "You may want to port this ugly hack to your compiler ABI"
65 #endif
66 
67 
68 TBeMenu *TBarWindow::sBeMenu = NULL;
69 
70 
71 TBarWindow::TBarWindow()
72 	: BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f), "Deskbar",
73 		B_BORDERED_WINDOW,
74 		B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE
75 			| B_NOT_MOVABLE | B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS,
76 		B_ALL_WORKSPACES)
77 {
78 	desk_settings *settings = ((TBarApp *)be_app)->Settings();
79 	if (settings->alwaysOnTop)
80 		SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
81 	fBarView = new TBarView(Bounds(), settings->vertical,settings->left, settings->top,
82 		settings->ampmMode, settings->state, settings->width, settings->showTime);
83 	AddChild(fBarView);
84 
85 	AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton));
86 #if SA_CLOCK
87 	AddShortcut('H', B_COMMAND_KEY, new BMessage('clok'));
88 #endif
89 }
90 
91 
92 void
93 TBarWindow::DispatchMessage(BMessage *message, BHandler *handler)
94 {
95 	// ToDo: check if the two following lines are doing anything...
96 	if (message->what == B_MOUSE_DOWN)
97 		Activate(true);
98 
99 	BWindow::DispatchMessage(message, handler);
100 }
101 
102 
103 void
104 TBarWindow::MenusBeginning()
105 {
106 	BPath path;
107 	entry_ref ref;
108 
109 	find_directory (B_USER_DESKBAR_DIRECTORY, &path);
110 	get_ref_for_path(path.Path(), &ref);
111 
112 	BEntry entry(&ref, true);
113 	if (entry.InitCheck() == B_OK && entry.IsDirectory()) {
114 		//	need the entry_ref to the actual item
115 		entry.GetRef(&ref);
116 		//	set the nav directory to the be folder
117 		sBeMenu->SetNavDir(&ref);
118 	} else if (!entry.Exists()) {
119 		//	the Be folder does not exist
120 		//	create one now
121 		BDirectory dir;
122 		if (entry.GetParent(&dir) == B_OK) {
123 			BDirectory bedir;
124 			dir.CreateDirectory("be", &bedir);
125 			if (bedir.GetEntry(&entry) == B_OK
126 				&& entry.GetRef(&ref) == B_OK)
127 				sBeMenu->SetNavDir(&ref);
128 		}
129 	} else {
130 		//	this really should never happen
131 		TRESPASS();
132 		return;
133 	}
134 
135 	sBeMenu->NeedsToRebuild();
136 	sBeMenu->ResetTargets();
137 
138 	BWindow::MenusBeginning();
139 }
140 
141 
142 void
143 TBarWindow::MenusEnded()
144 {
145 	BWindow::MenusEnded();
146 
147 	BMenuItem *item = NULL;
148 	while ((item = sBeMenu->RemoveItem((int32)0)) != NULL)
149 		delete item;
150 }
151 
152 
153 void
154 TBarWindow::MessageReceived(BMessage *message)
155 {
156 	switch (message->what) {
157 		case kFindButton:
158 		{
159 			BMessenger tracker(kTrackerSignature);
160 			tracker.SendMessage(message);
161 			break;
162 		}
163 
164 #if SA_CLOCK
165 		case 'clok':
166 			fBarView->ToggleClock();
167 			break;
168 #endif
169 
170 		case 'gloc':
171 			GetLocation(message);
172 			break;
173 
174 		case 'sloc':
175 			SetLocation(message);
176 			break;
177 
178 		case 'gexp':
179 			IsExpanded(message);
180 			break;
181 
182 		case 'sexp':
183 			Expand(message);
184 			break;
185 
186 		case 'info':
187 			ItemInfo(message);
188 			break;
189 
190 		case 'exst':
191 			ItemExists(message);
192 			break;
193 
194 		case 'cwnt':
195 			CountItems(message);
196 			break;
197 
198 		case 'adon':
199 		case 'icon':
200 			AddItem(message);
201 			break;
202 
203 		case 'remv':
204 			RemoveItem(message);
205 			break;
206 
207 		case 'iloc':
208 			GetIconFrame(message);
209 			break;
210 
211 		default:
212 			BWindow::MessageReceived(message);
213 			break;
214 	}
215 }
216 
217 
218 void
219 TBarWindow::SaveSettings()
220 {
221 	fBarView->SaveSettings();
222 }
223 
224 
225 bool
226 TBarWindow::QuitRequested()
227 {
228 	be_app->PostMessage(B_QUIT_REQUESTED);
229 
230 	return BWindow::QuitRequested();
231 }
232 
233 
234 void
235 TBarWindow::WorkspaceActivated(int32 workspace, bool active)
236 {
237 	BWindow::WorkspaceActivated(workspace, active);
238 
239 	if (active && !(fBarView->Expando() && fBarView->Vertical()))
240 		fBarView->UpdatePlacement();
241 	else {
242 		BRect screenFrame = (BScreen(fBarView->Window())).Frame();
243 		fBarView->SizeWindow(screenFrame);
244 		fBarView->PositionWindow(screenFrame);
245 		fBarView->Invalidate();
246 	}
247 }
248 
249 
250 void
251 TBarWindow::ScreenChanged(BRect size, color_space depth)
252 {
253 	BWindow::ScreenChanged(size, depth);
254 
255 	fBarView->UpdatePlacement();
256 }
257 
258 
259 void
260 TBarWindow::SetBeMenu(TBeMenu *menu)
261 {
262 	sBeMenu = menu;
263 }
264 
265 
266 TBeMenu *
267 TBarWindow::BeMenu()
268 {
269 	return sBeMenu;
270 }
271 
272 
273 void
274 TBarWindow::ShowBeMenu()
275 {
276 	BMenuBar *menuBar = fBarView->BarMenuBar();
277 	if (menuBar == NULL)
278 		menuBar = KeyMenuBar();
279 
280 	if (menuBar == NULL)
281 		return;
282 
283 #if __MWERKS__
284 	StartMenuBar__8BMenuBarFlbbP5BRect(menuBar,0,true,true,NULL);
285 #elif __GCC__ <= 2
286 	StartMenuBar__8BMenuBarlbT2P5BRect(menuBar,0,true,true,NULL);
287 #endif
288 }
289 
290 
291 void
292 TBarWindow::ShowTeamMenu()
293 {
294 	int32 index = 0;
295 	if (fBarView->BarMenuBar() == NULL)
296 		index = 2;
297 
298 	if (KeyMenuBar() == NULL)
299 		return;
300 
301 #if __MWERKS__
302 	StartMenuBar__8BMenuBarFlbbP5BRect(KeyMenuBar(),index,true,true,NULL);
303 #elif __GCC__ <= 2
304 	StartMenuBar__8BMenuBarlbT2P5BRect(KeyMenuBar(),index,true,true,NULL);
305 #endif
306 }
307 
308 
309 /**	determines the actual location of the window */
310 
311 deskbar_location
312 TBarWindow::DeskbarLocation() const
313 {
314 	bool left = fBarView->Left();
315 	bool top = fBarView->Top();
316 
317 	if (fBarView->AcrossTop())
318 		return B_DESKBAR_TOP;
319 
320 	if (fBarView->AcrossBottom())
321 		return B_DESKBAR_BOTTOM;
322 
323 	if (left && top)
324 		return B_DESKBAR_LEFT_TOP;
325 
326 	if (!left && top)
327 		return B_DESKBAR_RIGHT_TOP;
328 
329 	if (left && !top)
330 		return B_DESKBAR_LEFT_BOTTOM;
331 
332 	return B_DESKBAR_RIGHT_BOTTOM;
333 }
334 
335 
336 void
337 TBarWindow::GetLocation(BMessage *message)
338 {
339 	BMessage reply('rply');
340 	reply.AddInt32("location", (int32)DeskbarLocation());
341 	reply.AddBool("expanded", fBarView->Expando());
342 
343 	message->SendReply(&reply);
344 }
345 
346 
347 void
348 TBarWindow::SetDeskbarLocation(deskbar_location location, bool newExpandState)
349 {
350 	// left top and right top are the only two that
351 	// currently pay attention to expand, ignore for all others
352 
353 	bool left = false, top = true, vertical, expand;
354 
355 	switch (location) {
356 		case B_DESKBAR_TOP:
357 			left = true;
358 			top = true;
359 			vertical = false;
360 			expand = true;
361 			break;
362 
363 		case B_DESKBAR_BOTTOM:
364 			left = true;
365 			top = false;
366 			vertical = false;
367 			expand = true;
368 			break;
369 
370 		case B_DESKBAR_LEFT_TOP:
371 			left = true;
372 			top = true;
373 			vertical = true;
374 			expand = newExpandState;
375 			break;
376 
377 		case B_DESKBAR_RIGHT_TOP:
378 			left = false;
379 			top = true;
380 			vertical = true;
381 			expand = newExpandState;
382 			break;
383 
384 		case B_DESKBAR_LEFT_BOTTOM:
385 			left = true;
386 			top = false;
387 			vertical = true;
388 			expand = false;
389 			break;
390 
391 		case B_DESKBAR_RIGHT_BOTTOM:
392 			left = false;
393 			top = false;
394 			vertical = true;
395 			expand = false;
396 			break;
397 
398 		default:
399 			left = true;
400 			top = true;
401 			vertical = false;
402 			expand = true;
403 			break;
404 	}
405 
406 	fBarView->ChangeState(expand, vertical, left, top);
407 }
408 
409 void
410 TBarWindow::SetLocation(BMessage *message)
411 {
412 	deskbar_location location;
413 	bool expand;
414 	if (message->FindInt32("location", (int32 *)&location) == B_OK
415 		&& message->FindBool("expand", &expand) == B_OK)
416 		SetDeskbarLocation(location, expand);
417 }
418 
419 
420 void
421 TBarWindow::IsExpanded(BMessage *message)
422 {
423 	BMessage reply('rply');
424 	reply.AddBool("expanded", fBarView->Expando());
425 	message->SendReply(&reply);
426 }
427 
428 
429 void
430 TBarWindow::Expand(BMessage *message)
431 {
432 	bool expand;
433 	if (message->FindBool("expand", &expand) == B_OK) {
434 		bool vertical = fBarView->Vertical();
435 		bool left = fBarView->Left();
436 		bool top = fBarView->Top();
437 		fBarView->ChangeState(expand, vertical, left, top);
438 	}
439 }
440 
441 
442 void
443 TBarWindow::ItemInfo(BMessage *message)
444 {
445 	BMessage replyMsg;
446 	const char *name;
447 	int32 id;
448 	DeskbarShelf shelf;
449 	if (message->FindInt32("id", &id) == B_OK) {
450 		if (fBarView->ItemInfo(id, &name, &shelf) == B_OK) {
451 			replyMsg.AddString("name", name);
452 #if SHELF_AWARE
453 			replyMsg.AddInt32("shelf", (int32)shelf);
454 #endif
455 		}
456 	} else if (message->FindString("name", &name) == B_OK) {
457 		if (fBarView->ItemInfo(name, &id, &shelf) == B_OK) {
458 			replyMsg.AddInt32("id", id);
459 #if SHELF_AWARE
460 			replyMsg.AddInt32("shelf", (int32)shelf);
461 #endif
462 		}
463 	}
464 
465 	message->SendReply(&replyMsg);
466 }
467 
468 
469 void
470 TBarWindow::ItemExists(BMessage *message)
471 {
472 	BMessage replyMsg;
473 	const char *name;
474 	int32 id;
475 	DeskbarShelf shelf;
476 
477 #if SHELF_AWARE
478 	if (message->FindInt32("shelf", (int32 *)&shelf) != B_OK)
479 #endif
480 		shelf = B_DESKBAR_TRAY;
481 
482 	bool exists = false;
483 	if (message->FindInt32("id", &id) == B_OK)
484 		exists = fBarView->ItemExists(id, shelf);
485 	else if (message->FindString("name", &name) == B_OK)
486 		exists = fBarView->ItemExists(name, shelf);
487 
488 	replyMsg.AddBool("exists", exists);
489 	message->SendReply(&replyMsg);
490 }
491 
492 
493 void
494 TBarWindow::CountItems(BMessage *message)
495 {
496 	DeskbarShelf shelf;
497 
498 #if SHELF_AWARE
499 	if (message->FindInt32("shelf", (int32 *)&shelf) != B_OK)
500 #endif
501 		shelf = B_DESKBAR_TRAY;
502 
503 	BMessage reply('rply');
504 	reply.AddInt32("count", fBarView->CountItems(shelf));
505 	message->SendReply(&reply);
506 }
507 
508 
509 void
510 TBarWindow::AddItem(BMessage *message)
511 {
512 	DeskbarShelf shelf;
513 	entry_ref ref;
514 	int32 id = 999;
515 	BMessage reply;
516 	status_t err = B_ERROR;
517 
518 	BMessage archivedView;
519 	if (message->FindMessage("view", &archivedView) == B_OK) {
520 #if SHELF_AWARE
521 		if (message->FindInt32("shelf", (int32 *)&shelf) != B_OK)
522 #endif
523 			shelf = B_DESKBAR_TRAY;
524 
525 		err = fBarView->AddItem(new BMessage(archivedView), shelf, &id);
526 	} else if (message->FindRef("addon", &ref) == B_OK) {
527 		//
528 		//	exposing the name of the view here is not so great
529 		TReplicantTray *tray = dynamic_cast<TReplicantTray *>(FindView("Status"));
530 		if (tray) {
531 			// Force this into the deskbar even if the security code is wrong
532 			// This is OK because the user specifically asked for this replicant
533 			BEntry entry(&ref);
534 			err = tray->LoadAddOn(&entry, &id, true);
535 		}
536 	}
537 
538 	if (err == B_OK)
539 		reply.AddInt32("id", id);
540 	else
541 		reply.AddInt32("error", err);
542 
543 	message->SendReply(&reply);
544 }
545 
546 
547 void
548 TBarWindow::RemoveItem(BMessage *message)
549 {
550 	int32 id;
551 	const char *name;
552 
553 	// 	ids ought to be unique across all shelves, assuming, of course,
554 	//	that sometime in the future there may be more than one
555 #if SHELF_AWARE
556 	if (message->FindInt32("shelf", (int32 *)&shelf) == B_OK) {
557 		if (message->FindString("name", &name) == B_OK)
558 			fBarView->RemoveItem(name, shelf);
559 	} else {
560 #endif
561 		if (message->FindInt32("id", &id) == B_OK) {
562 			fBarView->RemoveItem(id);
563 		//	remove the following two lines if and when the
564 		//	shelf option returns
565 		} else if (message->FindString("name", &name) == B_OK)
566 			fBarView->RemoveItem(name, B_DESKBAR_TRAY);
567 
568 #if SHELF_AWARE
569 	}
570 #endif
571 }
572 
573 
574 void
575 TBarWindow::GetIconFrame(BMessage *message)
576 {
577 	BRect frame(0, 0, 0, 0);
578 
579 	const char *name;
580 	int32 id;
581 	if (message->FindInt32("id", &id) == B_OK)
582 		frame = fBarView->IconFrame(id);
583 	else if (message->FindString("name", &name) == B_OK)
584 		frame = fBarView->IconFrame(name);
585 
586 	BMessage reply('rply');
587 	reply.AddRect("frame", frame);
588 	message->SendReply(&reply);
589 }
590