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