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