xref: /haiku/src/apps/deskbar/BarWindow.cpp (revision e688bf23d48bfd1216a0cacbdbda5e35a1bcd779)
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
30 trademarks of Be Incorporated in the United States and other countries. Other
31 brand product names are registered trademarks or trademarks of their respective
32 holders.
33 All rights reserved.
34 */
35 
36 
37 #include "BarWindow.h"
38 
39 #include <stdio.h>
40 
41 #include <Application.h>
42 #include <Catalog.h>
43 #include <Directory.h>
44 #include <FindDirectory.h>
45 #include <Path.h>
46 #include <Debug.h>
47 #include <File.h>
48 #include <Locale.h>
49 #include <MenuItem.h>
50 #include <MessageFilter.h>
51 #include <MessagePrivate.h>
52 #include <Screen.h>
53 
54 #include "BarApp.h"
55 #include "BarMenuBar.h"
56 #include "BarView.h"
57 #include "DeskbarMenu.h"
58 #include "PublicCommands.h"
59 #include "StatusView.h"
60 #include "tracker_private.h"
61 
62 
63 #undef B_TRANSLATION_CONTEXT
64 #define B_TRANSLATION_CONTEXT "MainWindow"
65 
66 
67 // This is a very ugly hack to be able to call the private
68 // BMenuBar::StartMenuBar() method from the TBarWindow::ShowBeMenu() method.
69 // Don't do this at home -- but why the hell is this method private?
70 #if __MWERKS__
71 	#define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarFlbbP5BRect
72 #elif __GNUC__ <= 2
73 	#define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarlbT2P5BRect
74 #elif __GNUC__ > 2
75 	#if B_HAIKU_64_BIT
76 		#define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarEibbP5BRect
77 	#else
78 		#define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarElbbP5BRect
79 	#endif
80 #else
81 #	error "You may want to port this ugly hack to your compiler ABI"
82 #endif
83 extern "C" void
84 	BMenuBar_StartMenuBar_Hack(BMenuBar*, int32, bool, bool, BRect*);
85 
86 
87 TDeskbarMenu* TBarWindow::sDeskbarMenu = NULL;
88 
89 
90 TBarWindow::TBarWindow()
91 	:
92 	BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f),
93 		B_TRANSLATE_SYSTEM_NAME("Deskbar"), B_BORDERED_WINDOW,
94 		B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE
95 		| B_NOT_MINIMIZABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE
96 		| B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS,
97 		B_ALL_WORKSPACES),
98 	fShowingMenu(false)
99 {
100 	desk_settings* settings = ((TBarApp*)be_app)->Settings();
101 	if (settings->alwaysOnTop)
102 		SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
103 	fBarView = new TBarView(Bounds(), settings->vertical, settings->left,
104 		settings->top, settings->state, settings->width);
105 	AddChild(fBarView);
106 
107 	RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
108 	AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton));
109 }
110 
111 
112 void
113 TBarWindow::MenusBeginning()
114 {
115 	BPath path;
116 	entry_ref ref;
117 
118 	find_directory (B_USER_DESKBAR_DIRECTORY, &path);
119 	get_ref_for_path(path.Path(), &ref);
120 
121 	BEntry entry(&ref, true);
122 	if (entry.InitCheck() == B_OK && entry.IsDirectory()) {
123 		//	need the entry_ref to the actual item
124 		entry.GetRef(&ref);
125 		//	set the nav directory to the deskbar folder
126 		sDeskbarMenu->SetNavDir(&ref);
127 	} else if (!entry.Exists()) {
128 		//	the deskbar folder does not exist
129 		//	create one now
130 		BDirectory dir;
131 		if (entry.GetParent(&dir) == B_OK) {
132 			BDirectory deskbarDir;
133 			dir.CreateDirectory("deskbar", &deskbarDir);
134 			if (deskbarDir.GetEntry(&entry) == B_OK
135 				&& entry.GetRef(&ref) == B_OK)
136 				sDeskbarMenu->SetNavDir(&ref);
137 		}
138 	} else {
139 		//	this really should never happen
140 		TRESPASS();
141 		return;
142 	}
143 
144 	sDeskbarMenu->NeedsToRebuild();
145 	sDeskbarMenu->ResetTargets();
146 
147 	fShowingMenu = true;
148 	BWindow::MenusBeginning();
149 }
150 
151 
152 void
153 TBarWindow::MenusEnded()
154 {
155 	fShowingMenu = false;
156 	BWindow::MenusEnded();
157 
158 	if (sDeskbarMenu->LockLooper()) {
159 		// TODO: is this ok?
160 		sDeskbarMenu->RemoveItems(0, sDeskbarMenu->CountItems(), true);
161 		sDeskbarMenu->UnlockLooper();
162 	}
163 }
164 
165 
166 void
167 TBarWindow::MessageReceived(BMessage* message)
168 {
169 	switch (message->what) {
170 		case kFindButton:
171 		{
172 			BMessenger tracker(kTrackerSignature);
173 			tracker.SendMessage(message);
174 			break;
175 		}
176 
177 		case 'gloc':
178 			GetLocation(message);
179 			break;
180 
181 		case 'sloc':
182 			SetLocation(message);
183 			break;
184 
185 		case 'gexp':
186 			IsExpanded(message);
187 			break;
188 
189 		case 'sexp':
190 			Expand(message);
191 			break;
192 
193 		case 'info':
194 			ItemInfo(message);
195 			break;
196 
197 		case 'exst':
198 			ItemExists(message);
199 			break;
200 
201 		case 'cwnt':
202 			CountItems(message);
203 			break;
204 
205 		case 'adon':
206 		case 'icon':
207 			AddItem(message);
208 			break;
209 
210 		case 'remv':
211 			RemoveItem(message);
212 			break;
213 
214 		case 'iloc':
215 			GetIconFrame(message);
216 			break;
217 
218 		default:
219 			BWindow::MessageReceived(message);
220 			break;
221 	}
222 }
223 
224 
225 void
226 TBarWindow::Minimize(bool minimize)
227 {
228 	// Don't allow the Deskbar to be minimized
229 	if (!minimize)
230 		BWindow::Minimize(false);
231 }
232 
233 
234 void
235 TBarWindow::SaveSettings()
236 {
237 	fBarView->SaveSettings();
238 }
239 
240 
241 bool
242 TBarWindow::QuitRequested()
243 {
244 	be_app->PostMessage(B_QUIT_REQUESTED);
245 
246 	return BWindow::QuitRequested();
247 }
248 
249 
250 void
251 TBarWindow::WorkspaceActivated(int32 workspace, bool active)
252 {
253 	BWindow::WorkspaceActivated(workspace, active);
254 
255 	if (active && !(fBarView->ExpandoState() && fBarView->Vertical()))
256 		fBarView->UpdatePlacement();
257 	else {
258 		BRect screenFrame = (BScreen(fBarView->Window())).Frame();
259 		fBarView->SizeWindow(screenFrame);
260 		fBarView->PositionWindow(screenFrame);
261 		fBarView->Invalidate();
262 	}
263 }
264 
265 
266 void
267 TBarWindow::ScreenChanged(BRect size, color_space depth)
268 {
269 	BWindow::ScreenChanged(size, depth);
270 
271 	fBarView->UpdatePlacement();
272 }
273 
274 
275 void
276 TBarWindow::SetDeskbarMenu(TDeskbarMenu* menu)
277 {
278 	sDeskbarMenu = menu;
279 }
280 
281 
282 TDeskbarMenu*
283 TBarWindow::DeskbarMenu()
284 {
285 	return sDeskbarMenu;
286 }
287 
288 
289 void
290 TBarWindow::ShowDeskbarMenu()
291 {
292 	BMenuBar* menuBar = fBarView->BarMenuBar();
293 	if (menuBar == NULL)
294 		menuBar = KeyMenuBar();
295 
296 	if (menuBar == NULL)
297 		return;
298 
299 	BMenuBar_StartMenuBar_Hack(menuBar, 0, true, true, NULL);
300 }
301 
302 
303 void
304 TBarWindow::ShowTeamMenu()
305 {
306 	int32 index = 0;
307 	if (fBarView->BarMenuBar() == NULL)
308 		index = 2;
309 
310 	if (KeyMenuBar() == NULL)
311 		return;
312 
313 	BMenuBar_StartMenuBar_Hack(KeyMenuBar(), index, true, true, NULL);
314 }
315 
316 
317 // determines the actual location of the window
318 
319 deskbar_location
320 TBarWindow::DeskbarLocation() const
321 {
322 	bool left = fBarView->Left();
323 	bool top = fBarView->Top();
324 
325 	if (fBarView->AcrossTop())
326 		return B_DESKBAR_TOP;
327 
328 	if (fBarView->AcrossBottom())
329 		return B_DESKBAR_BOTTOM;
330 
331 	if (left && top)
332 		return B_DESKBAR_LEFT_TOP;
333 
334 	if (!left && top)
335 		return B_DESKBAR_RIGHT_TOP;
336 
337 	if (left && !top)
338 		return B_DESKBAR_LEFT_BOTTOM;
339 
340 	return B_DESKBAR_RIGHT_BOTTOM;
341 }
342 
343 
344 void
345 TBarWindow::GetLocation(BMessage* message)
346 {
347 	BMessage reply('rply');
348 	reply.AddInt32("location", (int32)DeskbarLocation());
349 	reply.AddBool("expanded", fBarView->ExpandoState());
350 
351 	message->SendReply(&reply);
352 }
353 
354 
355 void
356 TBarWindow::SetDeskbarLocation(deskbar_location location, bool newExpandState)
357 {
358 	// left top and right top are the only two that
359 	// currently pay attention to expand, ignore for all others
360 
361 	bool left = false, top = true, vertical, expand;
362 
363 	switch (location) {
364 		case B_DESKBAR_TOP:
365 			left = true;
366 			top = true;
367 			vertical = false;
368 			expand = true;
369 			break;
370 
371 		case B_DESKBAR_BOTTOM:
372 			left = true;
373 			top = false;
374 			vertical = false;
375 			expand = true;
376 			break;
377 
378 		case B_DESKBAR_LEFT_TOP:
379 			left = true;
380 			top = true;
381 			vertical = true;
382 			expand = newExpandState;
383 			break;
384 
385 		case B_DESKBAR_RIGHT_TOP:
386 			left = false;
387 			top = true;
388 			vertical = true;
389 			expand = newExpandState;
390 			break;
391 
392 		case B_DESKBAR_LEFT_BOTTOM:
393 			left = true;
394 			top = false;
395 			vertical = true;
396 			expand = false;
397 			break;
398 
399 		case B_DESKBAR_RIGHT_BOTTOM:
400 			left = false;
401 			top = false;
402 			vertical = true;
403 			expand = false;
404 			break;
405 
406 		default:
407 			left = true;
408 			top = true;
409 			vertical = false;
410 			expand = true;
411 			break;
412 	}
413 
414 	fBarView->ChangeState(expand, vertical, left, top);
415 }
416 
417 
418 void
419 TBarWindow::SetLocation(BMessage* message)
420 {
421 	deskbar_location location;
422 	bool expand;
423 	if (message->FindInt32("location", (int32*)&location) == B_OK
424 		&& message->FindBool("expand", &expand) == B_OK)
425 		SetDeskbarLocation(location, expand);
426 }
427 
428 
429 void
430 TBarWindow::IsExpanded(BMessage* message)
431 {
432 	BMessage reply('rply');
433 	reply.AddBool("expanded", fBarView->ExpandoState());
434 	message->SendReply(&reply);
435 }
436 
437 
438 void
439 TBarWindow::Expand(BMessage* message)
440 {
441 	bool expand;
442 	if (message->FindBool("expand", &expand) == B_OK) {
443 		bool vertical = fBarView->Vertical();
444 		bool left = fBarView->Left();
445 		bool top = fBarView->Top();
446 		fBarView->ChangeState(expand, vertical, left, top);
447 	}
448 }
449 
450 
451 void
452 TBarWindow::ItemInfo(BMessage* message)
453 {
454 	BMessage replyMsg;
455 	const char* name;
456 	int32 id;
457 	DeskbarShelf shelf;
458 	if (message->FindInt32("id", &id) == B_OK) {
459 		if (fBarView->ItemInfo(id, &name, &shelf) == B_OK) {
460 			replyMsg.AddString("name", name);
461 #if SHELF_AWARE
462 			replyMsg.AddInt32("shelf", (int32)shelf);
463 #endif
464 		}
465 	} else if (message->FindString("name", &name) == B_OK) {
466 		if (fBarView->ItemInfo(name, &id, &shelf) == B_OK) {
467 			replyMsg.AddInt32("id", id);
468 #if SHELF_AWARE
469 			replyMsg.AddInt32("shelf", (int32)shelf);
470 #endif
471 		}
472 	}
473 
474 	message->SendReply(&replyMsg);
475 }
476 
477 
478 void
479 TBarWindow::ItemExists(BMessage* message)
480 {
481 	BMessage replyMsg;
482 	const char* name;
483 	int32 id;
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 	bool exists = false;
492 	if (message->FindInt32("id", &id) == B_OK)
493 		exists = fBarView->ItemExists(id, shelf);
494 	else if (message->FindString("name", &name) == B_OK)
495 		exists = fBarView->ItemExists(name, shelf);
496 
497 	replyMsg.AddBool("exists", exists);
498 	message->SendReply(&replyMsg);
499 }
500 
501 
502 void
503 TBarWindow::CountItems(BMessage* message)
504 {
505 	DeskbarShelf shelf;
506 
507 #if SHELF_AWARE
508 	if (message->FindInt32("shelf", (int32*)&shelf) != B_OK)
509 #endif
510 		shelf = B_DESKBAR_TRAY;
511 
512 	BMessage reply('rply');
513 	reply.AddInt32("count", fBarView->CountItems(shelf));
514 	message->SendReply(&reply);
515 }
516 
517 
518 void
519 TBarWindow::AddItem(BMessage* message)
520 {
521 	DeskbarShelf shelf = B_DESKBAR_TRAY;
522 	entry_ref ref;
523 	int32 id = 999;
524 	BMessage reply;
525 	status_t err = B_ERROR;
526 
527 	BMessage archivedView;
528 	if (message->FindMessage("view", &archivedView) == B_OK) {
529 #if SHELF_AWARE
530 		message->FindInt32("shelf", &shelf);
531 #endif
532 		BMessage* archive = new BMessage(archivedView);
533 		err = fBarView->AddItem(archive, shelf, &id);
534 		if (err < B_OK)
535 			delete archive;
536 	} else if (message->FindRef("addon", &ref) == B_OK) {
537 		BEntry entry(&ref);
538 		err = entry.InitCheck();
539 		if (err == B_OK)
540 			err = fBarView->AddItem(&entry, shelf, &id);
541 	}
542 
543 	if (err == B_OK)
544 		reply.AddInt32("id", id);
545 	else
546 		reply.AddInt32("error", err);
547 
548 	message->SendReply(&reply);
549 }
550 
551 
552 void
553 TBarWindow::RemoveItem(BMessage* message)
554 {
555 	int32 id;
556 	const char* name;
557 
558 	// ids ought to be unique across all shelves, assuming, of course,
559 	// that sometime in the future there may be more than one
560 #if SHELF_AWARE
561 	if (message->FindInt32("shelf", (int32*)&shelf) == B_OK) {
562 		if (message->FindString("name", &name) == B_OK)
563 			fBarView->RemoveItem(name, shelf);
564 	} else {
565 #endif
566 		if (message->FindInt32("id", &id) == B_OK) {
567 			fBarView->RemoveItem(id);
568 		// remove the following two lines if and when the
569 		// shelf option returns
570 		} else if (message->FindString("name", &name) == B_OK)
571 			fBarView->RemoveItem(name, B_DESKBAR_TRAY);
572 
573 #if SHELF_AWARE
574 	}
575 #endif
576 }
577 
578 
579 void
580 TBarWindow::GetIconFrame(BMessage* message)
581 {
582 	BRect frame(0, 0, 0, 0);
583 
584 	const char* name;
585 	int32 id;
586 	if (message->FindInt32("id", &id) == B_OK)
587 		frame = fBarView->IconFrame(id);
588 	else if (message->FindString("name", &name) == B_OK)
589 		frame = fBarView->IconFrame(name);
590 
591 	BMessage reply('rply');
592 	reply.AddRect("frame", frame);
593 	message->SendReply(&reply);
594 }
595 
596 
597 bool
598 TBarWindow::IsShowingMenu() const
599 {
600 	return fShowingMenu;
601 }
602 
603 
604 bool
605 TBarWindow::_IsFocusMessage(BMessage* message)
606 {
607 	BMessage::Private messagePrivate(message);
608 	if (!messagePrivate.UsePreferredTarget())
609 		return false;
610 
611 	bool feedFocus;
612 	if (message->HasInt32("_token")
613 		&& (message->FindBool("_feed_focus", &feedFocus) != B_OK || !feedFocus))
614 		return false;
615 
616 	return true;
617 }
618