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