repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / deskbar / BarWindow.cpp
blobcfae6e089152a340f3140eaa5572dd5223e8c148
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
37 #include "BarWindow.h"
39 #include <stdio.h>
41 #include <Application.h>
42 #include <AutoDeleter.h>
43 #include <Catalog.h>
44 #include <Directory.h>
45 #include <FindDirectory.h>
46 #include <Path.h>
47 #include <Debug.h>
48 #include <File.h>
49 #include <Locale.h>
50 #include <MenuItem.h>
51 #include <MessageFilter.h>
52 #include <MessagePrivate.h>
53 #include <Screen.h>
55 #include "BarApp.h"
56 #include "BarMenuBar.h"
57 #include "BarView.h"
58 #include "DeskbarUtils.h"
59 #include "DeskbarMenu.h"
60 #include "ExpandoMenuBar.h"
61 #include "StatusView.h"
63 #include "tracker_private.h"
65 #undef B_TRANSLATION_CONTEXT
66 #define B_TRANSLATION_CONTEXT "MainWindow"
69 // This is a very ugly hack to be able to call the private
70 // BMenuBar::StartMenuBar() method from the TBarWindow::ShowBeMenu() method.
71 // Don't do this at home -- but why the hell is this method private?
72 #if __MWERKS__
73 #define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarFlbbP5BRect
74 #elif __GNUC__ <= 2
75 #define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarlbT2P5BRect
76 #elif __GNUC__ > 2
77 #if B_HAIKU_64_BIT
78 #define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarEibbP5BRect
79 #else
80 #define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarElbbP5BRect
81 #endif
82 #else
83 # error "You may want to port this ugly hack to your compiler ABI"
84 #endif
85 extern "C" void
86 BMenuBar_StartMenuBar_Hack(BMenuBar*, int32, bool, bool, BRect*);
89 TDeskbarMenu* TBarWindow::sDeskbarMenu = NULL;
92 TBarWindow::TBarWindow()
94 BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f),
95 B_TRANSLATE_SYSTEM_NAME("Deskbar"), B_BORDERED_WINDOW,
96 B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE
97 | B_NOT_MINIMIZABLE | B_NOT_MOVABLE | B_NOT_V_RESIZABLE
98 | B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS,
99 B_ALL_WORKSPACES),
100 fShowingMenu(false)
102 desk_settings* settings = ((TBarApp*)be_app)->Settings();
103 if (settings->alwaysOnTop)
104 SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
106 fBarView = new TBarView(Bounds(), settings->vertical, settings->left,
107 settings->top, settings->state, settings->width);
108 AddChild(fBarView);
110 RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
111 AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton));
115 void
116 TBarWindow::MenusBeginning()
118 BPath path;
119 entry_ref ref;
120 BEntry entry;
122 if (GetDeskbarSettingsDirectory(path) == B_OK
123 && path.Append(kDeskbarMenuEntriesFileName) == B_OK
124 && entry.SetTo(path.Path(), true) == B_OK
125 && entry.Exists()
126 && entry.GetRef(&ref) == B_OK) {
127 sDeskbarMenu->SetNavDir(&ref);
128 } else if (GetDeskbarDataDirectory(path) == B_OK
129 && path.Append(kDeskbarMenuEntriesFileName) == B_OK
130 && entry.SetTo(path.Path(), true) == B_OK
131 && entry.Exists()
132 && entry.GetRef(&ref) == B_OK) {
133 sDeskbarMenu->SetNavDir(&ref);
134 } else {
135 // this really should never happen
136 TRESPASS();
137 return;
140 sDeskbarMenu->ResetTargets();
142 fShowingMenu = true;
143 BWindow::MenusBeginning();
147 void
148 TBarWindow::MenusEnded()
150 fShowingMenu = false;
151 BWindow::MenusEnded();
153 if (sDeskbarMenu->LockLooper()) {
154 sDeskbarMenu->ForceRebuild();
155 sDeskbarMenu->UnlockLooper();
160 void
161 TBarWindow::MessageReceived(BMessage* message)
163 switch (message->what) {
164 case kFindButton:
166 BMessenger tracker(kTrackerSignature);
167 tracker.SendMessage(message);
168 break;
171 case kMsgLocation:
172 GetLocation(message);
173 break;
175 case kMsgSetLocation:
176 SetLocation(message);
177 break;
179 case kMsgIsExpanded:
180 IsExpanded(message);
181 break;
183 case kMsgExpand:
184 Expand(message);
185 break;
187 case kMsgGetItemInfo:
188 ItemInfo(message);
189 break;
191 case kMsgHasItem:
192 ItemExists(message);
193 break;
195 case kMsgCountItems:
196 CountItems(message);
197 break;
199 case kMsgAddAddOn:
200 case kMsgAddView:
201 AddItem(message);
202 break;
204 case kMsgRemoveItem:
205 RemoveItem(message);
206 break;
208 case 'iloc':
209 GetIconFrame(message);
210 break;
212 default:
213 BWindow::MessageReceived(message);
214 break;
219 void
220 TBarWindow::Minimize(bool minimize)
222 // Don't allow the Deskbar to be minimized
223 if (!minimize)
224 BWindow::Minimize(false);
228 void
229 TBarWindow::FrameResized(float width, float height)
231 if (!fBarView->Vertical())
232 return BWindow::FrameResized(width, height);
234 bool setToHiddenSize = static_cast<TBarApp*>(be_app)->Settings()->autoHide
235 && fBarView->IsHidden() && !fBarView->DragRegion()->IsDragging();
236 if (!setToHiddenSize) {
237 // constrain within limits
238 float newWidth;
239 if (width < gMinimumWindowWidth)
240 newWidth = gMinimumWindowWidth;
241 else if (width > gMaximumWindowWidth)
242 newWidth = gMaximumWindowWidth;
243 else
244 newWidth = width;
246 float oldWidth = static_cast<TBarApp*>(be_app)->Settings()->width;
248 // update width setting
249 static_cast<TBarApp*>(be_app)->Settings()->width = newWidth;
251 if (oldWidth != newWidth) {
252 fBarView->ResizeTo(width, fBarView->Bounds().Height());
253 if (fBarView->Vertical() && fBarView->ExpandoState())
254 fBarView->ExpandoMenuBar()->SetMaxContentWidth(width);
256 fBarView->UpdatePlacement();
262 void
263 TBarWindow::SaveSettings()
265 fBarView->SaveSettings();
269 bool
270 TBarWindow::QuitRequested()
272 be_app->PostMessage(B_QUIT_REQUESTED);
274 return BWindow::QuitRequested();
278 void
279 TBarWindow::WorkspaceActivated(int32 workspace, bool active)
281 BWindow::WorkspaceActivated(workspace, active);
283 if (active && !(fBarView->ExpandoState() && fBarView->Vertical()))
284 fBarView->UpdatePlacement();
285 else {
286 BRect screenFrame = (BScreen(fBarView->Window())).Frame();
287 fBarView->SizeWindow(screenFrame);
288 fBarView->PositionWindow(screenFrame);
289 fBarView->Invalidate();
294 void
295 TBarWindow::ScreenChanged(BRect size, color_space depth)
297 BWindow::ScreenChanged(size, depth);
299 fBarView->UpdatePlacement();
303 void
304 TBarWindow::SetDeskbarMenu(TDeskbarMenu* menu)
306 sDeskbarMenu = menu;
310 TDeskbarMenu*
311 TBarWindow::DeskbarMenu()
313 return sDeskbarMenu;
317 void
318 TBarWindow::ShowDeskbarMenu()
320 BMenuBar* menuBar = fBarView->BarMenuBar();
321 if (menuBar == NULL)
322 menuBar = KeyMenuBar();
324 if (menuBar == NULL)
325 return;
327 BMenuBar_StartMenuBar_Hack(menuBar, 0, true, true, NULL);
331 void
332 TBarWindow::ShowTeamMenu()
334 int32 index = 0;
335 if (fBarView->BarMenuBar() == NULL)
336 index = 2;
338 if (KeyMenuBar() == NULL)
339 return;
341 BMenuBar_StartMenuBar_Hack(KeyMenuBar(), index, true, true, NULL);
345 // determines the actual location of the window
347 deskbar_location
348 TBarWindow::DeskbarLocation() const
350 bool left = fBarView->Left();
351 bool top = fBarView->Top();
353 if (fBarView->AcrossTop())
354 return B_DESKBAR_TOP;
356 if (fBarView->AcrossBottom())
357 return B_DESKBAR_BOTTOM;
359 if (left && top)
360 return B_DESKBAR_LEFT_TOP;
362 if (!left && top)
363 return B_DESKBAR_RIGHT_TOP;
365 if (left && !top)
366 return B_DESKBAR_LEFT_BOTTOM;
368 return B_DESKBAR_RIGHT_BOTTOM;
372 void
373 TBarWindow::GetLocation(BMessage* message)
375 BMessage reply('rply');
376 reply.AddInt32("location", (int32)DeskbarLocation());
377 reply.AddBool("expanded", fBarView->ExpandoState());
379 message->SendReply(&reply);
383 void
384 TBarWindow::SetDeskbarLocation(deskbar_location location, bool newExpandState)
386 // left top and right top are the only two that
387 // currently pay attention to expand, ignore for all others
389 bool left = false, top = true, vertical, expand;
391 switch (location) {
392 case B_DESKBAR_TOP:
393 left = true;
394 top = true;
395 vertical = false;
396 expand = true;
397 break;
399 case B_DESKBAR_BOTTOM:
400 left = true;
401 top = false;
402 vertical = false;
403 expand = true;
404 break;
406 case B_DESKBAR_LEFT_TOP:
407 left = true;
408 top = true;
409 vertical = true;
410 expand = newExpandState;
411 break;
413 case B_DESKBAR_RIGHT_TOP:
414 left = false;
415 top = true;
416 vertical = true;
417 expand = newExpandState;
418 break;
420 case B_DESKBAR_LEFT_BOTTOM:
421 left = true;
422 top = false;
423 vertical = true;
424 expand = false;
425 break;
427 case B_DESKBAR_RIGHT_BOTTOM:
428 left = false;
429 top = false;
430 vertical = true;
431 expand = false;
432 break;
434 default:
435 left = true;
436 top = true;
437 vertical = false;
438 expand = true;
439 break;
442 fBarView->ChangeState(expand, vertical, left, top);
446 void
447 TBarWindow::SetLocation(BMessage* message)
449 deskbar_location location;
450 bool expand;
451 if (message->FindInt32("location", (int32*)&location) == B_OK
452 && message->FindBool("expand", &expand) == B_OK)
453 SetDeskbarLocation(location, expand);
457 void
458 TBarWindow::IsExpanded(BMessage* message)
460 BMessage reply('rply');
461 reply.AddBool("expanded", fBarView->ExpandoState());
462 message->SendReply(&reply);
466 void
467 TBarWindow::Expand(BMessage* message)
469 bool expand;
470 if (message->FindBool("expand", &expand) == B_OK) {
471 bool vertical = fBarView->Vertical();
472 bool left = fBarView->Left();
473 bool top = fBarView->Top();
474 fBarView->ChangeState(expand, vertical, left, top);
479 void
480 TBarWindow::ItemInfo(BMessage* message)
482 BMessage replyMsg;
483 const char* name;
484 int32 id;
485 DeskbarShelf shelf;
486 if (message->FindInt32("id", &id) == B_OK) {
487 if (fBarView->ItemInfo(id, &name, &shelf) == B_OK) {
488 replyMsg.AddString("name", name);
489 #if SHELF_AWARE
490 replyMsg.AddInt32("shelf", (int32)shelf);
491 #endif
493 } else if (message->FindString("name", &name) == B_OK) {
494 if (fBarView->ItemInfo(name, &id, &shelf) == B_OK) {
495 replyMsg.AddInt32("id", id);
496 #if SHELF_AWARE
497 replyMsg.AddInt32("shelf", (int32)shelf);
498 #endif
502 message->SendReply(&replyMsg);
506 void
507 TBarWindow::ItemExists(BMessage* message)
509 BMessage replyMsg;
510 const char* name;
511 int32 id;
512 DeskbarShelf shelf;
514 #if SHELF_AWARE
515 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK)
516 #endif
517 shelf = B_DESKBAR_TRAY;
519 bool exists = false;
520 if (message->FindInt32("id", &id) == B_OK)
521 exists = fBarView->ItemExists(id, shelf);
522 else if (message->FindString("name", &name) == B_OK)
523 exists = fBarView->ItemExists(name, shelf);
525 replyMsg.AddBool("exists", exists);
526 message->SendReply(&replyMsg);
530 void
531 TBarWindow::CountItems(BMessage* message)
533 DeskbarShelf shelf;
535 #if SHELF_AWARE
536 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK)
537 #endif
538 shelf = B_DESKBAR_TRAY;
540 BMessage reply('rply');
541 reply.AddInt32("count", fBarView->CountItems(shelf));
542 message->SendReply(&reply);
546 void
547 TBarWindow::AddItem(BMessage* message)
549 DeskbarShelf shelf = B_DESKBAR_TRAY;
550 entry_ref ref;
551 int32 id = 999;
552 BMessage reply;
553 status_t err = B_ERROR;
555 BMessage* archivedView = new BMessage();
556 ObjectDeleter<BMessage> deleter(archivedView);
557 if (message->FindMessage("view", archivedView) == B_OK) {
558 #if SHELF_AWARE
559 message->FindInt32("shelf", &shelf);
560 #endif
561 err = fBarView->AddItem(archivedView, shelf, &id);
562 if (err == B_OK) {
563 // Detach the deleter since AddReplicant is taking ownership
564 // on success. This should be changed on server side.
565 deleter.Detach();
567 } else if (message->FindRef("addon", &ref) == B_OK) {
568 BEntry entry(&ref);
569 err = entry.InitCheck();
570 if (err == B_OK)
571 err = fBarView->AddItem(&entry, shelf, &id);
574 if (err == B_OK)
575 reply.AddInt32("id", id);
576 else
577 reply.AddInt32("error", err);
579 message->SendReply(&reply);
583 void
584 TBarWindow::RemoveItem(BMessage* message)
586 int32 id;
587 const char* name;
589 // ids ought to be unique across all shelves, assuming, of course,
590 // that sometime in the future there may be more than one
591 #if SHELF_AWARE
592 if (message->FindInt32("shelf", (int32*)&shelf) == B_OK) {
593 if (message->FindString("name", &name) == B_OK)
594 fBarView->RemoveItem(name, shelf);
595 } else {
596 #endif
597 if (message->FindInt32("id", &id) == B_OK) {
598 fBarView->RemoveItem(id);
599 // remove the following two lines if and when the
600 // shelf option returns
601 } else if (message->FindString("name", &name) == B_OK)
602 fBarView->RemoveItem(name, B_DESKBAR_TRAY);
604 #if SHELF_AWARE
606 #endif
610 void
611 TBarWindow::GetIconFrame(BMessage* message)
613 BRect frame(0, 0, 0, 0);
615 const char* name;
616 int32 id;
617 if (message->FindInt32("id", &id) == B_OK)
618 frame = fBarView->IconFrame(id);
619 else if (message->FindString("name", &name) == B_OK)
620 frame = fBarView->IconFrame(name);
622 BMessage reply('rply');
623 reply.AddRect("frame", frame);
624 message->SendReply(&reply);
628 bool
629 TBarWindow::IsShowingMenu() const
631 return fShowingMenu;
635 bool
636 TBarWindow::_IsFocusMessage(BMessage* message)
638 BMessage::Private messagePrivate(message);
639 if (!messagePrivate.UsePreferredTarget())
640 return false;
642 bool feedFocus;
643 if (message->HasInt32("_token")
644 && (message->FindBool("_feed_focus", &feedFocus) != B_OK || !feedFocus))
645 return false;
647 return true;