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