xref: /haiku/src/apps/deskbar/BarWindow.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
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 }
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  	if (!sBeMenu->LockLooper()) {
148  		// TODO: is this ok?
149  		return;
150  	}
151 
152 	BMenuItem *item = NULL;
153 	while ((item = sBeMenu->RemoveItem((int32)0)) != NULL)
154 		delete item;
155 
156 	sBeMenu->UnlockLooper();
157 }
158 
159 
160 void
161 TBarWindow::MessageReceived(BMessage *message)
162 {
163 	switch (message->what) {
164 		case kFindButton:
165 		{
166 			BMessenger tracker(kTrackerSignature);
167 			tracker.SendMessage(message);
168 			break;
169 		}
170 
171 		case 'gloc':
172 			GetLocation(message);
173 			break;
174 
175 		case 'sloc':
176 			SetLocation(message);
177 			break;
178 
179 		case 'gexp':
180 			IsExpanded(message);
181 			break;
182 
183 		case 'sexp':
184 			Expand(message);
185 			break;
186 
187 		case 'info':
188 			ItemInfo(message);
189 			break;
190 
191 		case 'exst':
192 			ItemExists(message);
193 			break;
194 
195 		case 'cwnt':
196 			CountItems(message);
197 			break;
198 
199 		case 'adon':
200 		case 'icon':
201 			AddItem(message);
202 			break;
203 
204 		case 'remv':
205 			RemoveItem(message);
206 			break;
207 
208 		case 'iloc':
209 			GetIconFrame(message);
210 			break;
211 
212 		default:
213 			BWindow::MessageReceived(message);
214 			break;
215 	}
216 }
217 
218 
219 void
220 TBarWindow::SaveSettings()
221 {
222 	fBarView->SaveSettings();
223 }
224 
225 
226 bool
227 TBarWindow::QuitRequested()
228 {
229 	be_app->PostMessage(B_QUIT_REQUESTED);
230 
231 	return BWindow::QuitRequested();
232 }
233 
234 
235 void
236 TBarWindow::WorkspaceActivated(int32 workspace, bool active)
237 {
238 	BWindow::WorkspaceActivated(workspace, active);
239 
240 	if (active && !(fBarView->Expando() && fBarView->Vertical()))
241 		fBarView->UpdatePlacement();
242 	else {
243 		BRect screenFrame = (BScreen(fBarView->Window())).Frame();
244 		fBarView->SizeWindow(screenFrame);
245 		fBarView->PositionWindow(screenFrame);
246 		fBarView->Invalidate();
247 	}
248 }
249 
250 
251 void
252 TBarWindow::ScreenChanged(BRect size, color_space depth)
253 {
254 	BWindow::ScreenChanged(size, depth);
255 
256 	fBarView->UpdatePlacement();
257 }
258 
259 
260 void
261 TBarWindow::SetBeMenu(TBeMenu *menu)
262 {
263 	sBeMenu = menu;
264 }
265 
266 
267 TBeMenu *
268 TBarWindow::BeMenu()
269 {
270 	return sBeMenu;
271 }
272 
273 
274 void
275 TBarWindow::ShowBeMenu()
276 {
277 	BMenuBar *menuBar = fBarView->BarMenuBar();
278 	if (menuBar == NULL)
279 		menuBar = KeyMenuBar();
280 
281 	if (menuBar == NULL)
282 		return;
283 
284 	BMenuBar_StartMenuBar_Hack(menuBar,0,true,true,NULL);
285 }
286 
287 
288 void
289 TBarWindow::ShowTeamMenu()
290 {
291 	int32 index = 0;
292 	if (fBarView->BarMenuBar() == NULL)
293 		index = 2;
294 
295 	if (KeyMenuBar() == NULL)
296 		return;
297 
298 	BMenuBar_StartMenuBar_Hack(KeyMenuBar(),index,true,true,NULL);
299 }
300 
301 
302 /**	determines the actual location of the window */
303 
304 deskbar_location
305 TBarWindow::DeskbarLocation() const
306 {
307 	bool left = fBarView->Left();
308 	bool top = fBarView->Top();
309 
310 	if (fBarView->AcrossTop())
311 		return B_DESKBAR_TOP;
312 
313 	if (fBarView->AcrossBottom())
314 		return B_DESKBAR_BOTTOM;
315 
316 	if (left && top)
317 		return B_DESKBAR_LEFT_TOP;
318 
319 	if (!left && top)
320 		return B_DESKBAR_RIGHT_TOP;
321 
322 	if (left && !top)
323 		return B_DESKBAR_LEFT_BOTTOM;
324 
325 	return B_DESKBAR_RIGHT_BOTTOM;
326 }
327 
328 
329 void
330 TBarWindow::GetLocation(BMessage *message)
331 {
332 	BMessage reply('rply');
333 	reply.AddInt32("location", (int32)DeskbarLocation());
334 	reply.AddBool("expanded", fBarView->Expando());
335 
336 	message->SendReply(&reply);
337 }
338 
339 
340 void
341 TBarWindow::SetDeskbarLocation(deskbar_location location, bool newExpandState)
342 {
343 	// left top and right top are the only two that
344 	// currently pay attention to expand, ignore for all others
345 
346 	bool left = false, top = true, vertical, expand;
347 
348 	switch (location) {
349 		case B_DESKBAR_TOP:
350 			left = true;
351 			top = true;
352 			vertical = false;
353 			expand = true;
354 			break;
355 
356 		case B_DESKBAR_BOTTOM:
357 			left = true;
358 			top = false;
359 			vertical = false;
360 			expand = true;
361 			break;
362 
363 		case B_DESKBAR_LEFT_TOP:
364 			left = true;
365 			top = true;
366 			vertical = true;
367 			expand = newExpandState;
368 			break;
369 
370 		case B_DESKBAR_RIGHT_TOP:
371 			left = false;
372 			top = true;
373 			vertical = true;
374 			expand = newExpandState;
375 			break;
376 
377 		case B_DESKBAR_LEFT_BOTTOM:
378 			left = true;
379 			top = false;
380 			vertical = true;
381 			expand = false;
382 			break;
383 
384 		case B_DESKBAR_RIGHT_BOTTOM:
385 			left = false;
386 			top = false;
387 			vertical = true;
388 			expand = false;
389 			break;
390 
391 		default:
392 			left = true;
393 			top = true;
394 			vertical = false;
395 			expand = true;
396 			break;
397 	}
398 
399 	fBarView->ChangeState(expand, vertical, left, top);
400 }
401 
402 void
403 TBarWindow::SetLocation(BMessage *message)
404 {
405 	deskbar_location location;
406 	bool expand;
407 	if (message->FindInt32("location", (int32 *)&location) == B_OK
408 		&& message->FindBool("expand", &expand) == B_OK)
409 		SetDeskbarLocation(location, expand);
410 }
411 
412 
413 void
414 TBarWindow::IsExpanded(BMessage *message)
415 {
416 	BMessage reply('rply');
417 	reply.AddBool("expanded", fBarView->Expando());
418 	message->SendReply(&reply);
419 }
420 
421 
422 void
423 TBarWindow::Expand(BMessage *message)
424 {
425 	bool expand;
426 	if (message->FindBool("expand", &expand) == B_OK) {
427 		bool vertical = fBarView->Vertical();
428 		bool left = fBarView->Left();
429 		bool top = fBarView->Top();
430 		fBarView->ChangeState(expand, vertical, left, top);
431 	}
432 }
433 
434 
435 void
436 TBarWindow::ItemInfo(BMessage *message)
437 {
438 	BMessage replyMsg;
439 	const char *name;
440 	int32 id;
441 	DeskbarShelf shelf;
442 	if (message->FindInt32("id", &id) == B_OK) {
443 		if (fBarView->ItemInfo(id, &name, &shelf) == B_OK) {
444 			replyMsg.AddString("name", name);
445 #if SHELF_AWARE
446 			replyMsg.AddInt32("shelf", (int32)shelf);
447 #endif
448 		}
449 	} else if (message->FindString("name", &name) == B_OK) {
450 		if (fBarView->ItemInfo(name, &id, &shelf) == B_OK) {
451 			replyMsg.AddInt32("id", id);
452 #if SHELF_AWARE
453 			replyMsg.AddInt32("shelf", (int32)shelf);
454 #endif
455 		}
456 	}
457 
458 	message->SendReply(&replyMsg);
459 }
460 
461 
462 void
463 TBarWindow::ItemExists(BMessage *message)
464 {
465 	BMessage replyMsg;
466 	const char *name;
467 	int32 id;
468 	DeskbarShelf shelf;
469 
470 #if SHELF_AWARE
471 	if (message->FindInt32("shelf", (int32 *)&shelf) != B_OK)
472 #endif
473 		shelf = B_DESKBAR_TRAY;
474 
475 	bool exists = false;
476 	if (message->FindInt32("id", &id) == B_OK)
477 		exists = fBarView->ItemExists(id, shelf);
478 	else if (message->FindString("name", &name) == B_OK)
479 		exists = fBarView->ItemExists(name, shelf);
480 
481 	replyMsg.AddBool("exists", exists);
482 	message->SendReply(&replyMsg);
483 }
484 
485 
486 void
487 TBarWindow::CountItems(BMessage *message)
488 {
489 	DeskbarShelf shelf;
490 
491 #if SHELF_AWARE
492 	if (message->FindInt32("shelf", (int32 *)&shelf) != B_OK)
493 #endif
494 		shelf = B_DESKBAR_TRAY;
495 
496 	BMessage reply('rply');
497 	reply.AddInt32("count", fBarView->CountItems(shelf));
498 	message->SendReply(&reply);
499 }
500 
501 
502 void
503 TBarWindow::AddItem(BMessage *message)
504 {
505 	DeskbarShelf shelf;
506 	entry_ref ref;
507 	int32 id = 999;
508 	BMessage reply;
509 	status_t err = B_ERROR;
510 
511 	BMessage archivedView;
512 	if (message->FindMessage("view", &archivedView) == B_OK) {
513 #if SHELF_AWARE
514 		if (message->FindInt32("shelf", (int32 *)&shelf) != B_OK)
515 #endif
516 			shelf = B_DESKBAR_TRAY;
517 
518 		err = fBarView->AddItem(new BMessage(archivedView), shelf, &id);
519 	} else if (message->FindRef("addon", &ref) == B_OK) {
520 		//
521 		//	exposing the name of the view here is not so great
522 		TReplicantTray *tray = dynamic_cast<TReplicantTray *>(FindView("Status"));
523 		if (tray) {
524 			// Force this into the deskbar even if the security code is wrong
525 			// This is OK because the user specifically asked for this replicant
526 			BEntry entry(&ref);
527 			err = tray->LoadAddOn(&entry, &id, true);
528 		}
529 	}
530 
531 	if (err == B_OK)
532 		reply.AddInt32("id", id);
533 	else
534 		reply.AddInt32("error", err);
535 
536 	message->SendReply(&reply);
537 }
538 
539 
540 void
541 TBarWindow::RemoveItem(BMessage *message)
542 {
543 	int32 id;
544 	const char *name;
545 
546 	// 	ids ought to be unique across all shelves, assuming, of course,
547 	//	that sometime in the future there may be more than one
548 #if SHELF_AWARE
549 	if (message->FindInt32("shelf", (int32 *)&shelf) == B_OK) {
550 		if (message->FindString("name", &name) == B_OK)
551 			fBarView->RemoveItem(name, shelf);
552 	} else {
553 #endif
554 		if (message->FindInt32("id", &id) == B_OK) {
555 			fBarView->RemoveItem(id);
556 		//	remove the following two lines if and when the
557 		//	shelf option returns
558 		} else if (message->FindString("name", &name) == B_OK)
559 			fBarView->RemoveItem(name, B_DESKBAR_TRAY);
560 
561 #if SHELF_AWARE
562 	}
563 #endif
564 }
565 
566 
567 void
568 TBarWindow::GetIconFrame(BMessage *message)
569 {
570 	BRect frame(0, 0, 0, 0);
571 
572 	const char *name;
573 	int32 id;
574 	if (message->FindInt32("id", &id) == B_OK)
575 		frame = fBarView->IconFrame(id);
576 	else if (message->FindString("name", &name) == B_OK)
577 		frame = fBarView->IconFrame(name);
578 
579 	BMessage reply('rply');
580 	reply.AddRect("frame", frame);
581 	message->SendReply(&reply);
582 }
583