BPicture: Fix archive constructor.
[haiku.git] / src / apps / deskbar / BarWindow.cpp
blob2ca730154e273a92a567a5ce604619d845f846d9
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 "StatusView.h"
62 #include "tracker_private.h"
64 #undef B_TRANSLATION_CONTEXT
65 #define B_TRANSLATION_CONTEXT "MainWindow"
68 // This is a very ugly hack to be able to call the private
69 // BMenuBar::StartMenuBar() method from the TBarWindow::ShowBeMenu() method.
70 // Don't do this at home -- but why the hell is this method private?
71 #if __MWERKS__
72 #define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarFlbbP5BRect
73 #elif __GNUC__ <= 2
74 #define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarlbT2P5BRect
75 #elif __GNUC__ > 2
76 #if B_HAIKU_64_BIT
77 #define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarEibbP5BRect
78 #else
79 #define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarElbbP5BRect
80 #endif
81 #else
82 # error "You may want to port this ugly hack to your compiler ABI"
83 #endif
84 extern "C" void
85 BMenuBar_StartMenuBar_Hack(BMenuBar*, int32, bool, bool, BRect*);
88 TDeskbarMenu* TBarWindow::sDeskbarMenu = NULL;
91 TBarWindow::TBarWindow()
93 BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f),
94 B_TRANSLATE_SYSTEM_NAME("Deskbar"), B_BORDERED_WINDOW,
95 B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE
96 | B_NOT_MINIMIZABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE
97 | B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS,
98 B_ALL_WORKSPACES),
99 fShowingMenu(false)
101 desk_settings* settings = ((TBarApp*)be_app)->Settings();
102 if (settings->alwaysOnTop)
103 SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
105 fBarView = new TBarView(Bounds(), settings->vertical, settings->left,
106 settings->top, settings->state, settings->width);
107 AddChild(fBarView);
109 RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
110 AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton));
114 void
115 TBarWindow::MenusBeginning()
117 BPath path;
118 entry_ref ref;
119 BEntry entry;
121 if (GetDeskbarSettingsDirectory(path) == B_OK
122 && path.Append(kDeskbarMenuEntriesFileName) == B_OK
123 && entry.SetTo(path.Path(), true) == B_OK
124 && entry.Exists()
125 && entry.GetRef(&ref) == B_OK) {
126 sDeskbarMenu->SetNavDir(&ref);
127 } else if (GetDeskbarDataDirectory(path) == B_OK
128 && path.Append(kDeskbarMenuEntriesFileName) == B_OK
129 && entry.SetTo(path.Path(), true) == B_OK
130 && entry.Exists()
131 && entry.GetRef(&ref) == B_OK) {
132 sDeskbarMenu->SetNavDir(&ref);
133 } else {
134 // this really should never happen
135 TRESPASS();
136 return;
139 sDeskbarMenu->ResetTargets();
141 fShowingMenu = true;
142 BWindow::MenusBeginning();
146 void
147 TBarWindow::MenusEnded()
149 fShowingMenu = false;
150 BWindow::MenusEnded();
152 if (sDeskbarMenu->LockLooper()) {
153 sDeskbarMenu->ForceRebuild();
154 sDeskbarMenu->UnlockLooper();
159 void
160 TBarWindow::MessageReceived(BMessage* message)
162 switch (message->what) {
163 case kFindButton:
165 BMessenger tracker(kTrackerSignature);
166 tracker.SendMessage(message);
167 break;
170 case 'gloc':
171 GetLocation(message);
172 break;
174 case 'sloc':
175 SetLocation(message);
176 break;
178 case 'gexp':
179 IsExpanded(message);
180 break;
182 case 'sexp':
183 Expand(message);
184 break;
186 case 'info':
187 ItemInfo(message);
188 break;
190 case 'exst':
191 ItemExists(message);
192 break;
194 case 'cwnt':
195 CountItems(message);
196 break;
198 case 'adon':
199 case 'icon':
200 AddItem(message);
201 break;
203 case 'remv':
204 RemoveItem(message);
205 break;
207 case 'iloc':
208 GetIconFrame(message);
209 break;
211 default:
212 BWindow::MessageReceived(message);
213 break;
218 void
219 TBarWindow::Minimize(bool minimize)
221 // Don't allow the Deskbar to be minimized
222 if (!minimize)
223 BWindow::Minimize(false);
227 void
228 TBarWindow::SaveSettings()
230 fBarView->SaveSettings();
234 bool
235 TBarWindow::QuitRequested()
237 be_app->PostMessage(B_QUIT_REQUESTED);
239 return BWindow::QuitRequested();
243 void
244 TBarWindow::WorkspaceActivated(int32 workspace, bool active)
246 BWindow::WorkspaceActivated(workspace, active);
248 if (active && !(fBarView->ExpandoState() && fBarView->Vertical()))
249 fBarView->UpdatePlacement();
250 else {
251 BRect screenFrame = (BScreen(fBarView->Window())).Frame();
252 fBarView->SizeWindow(screenFrame);
253 fBarView->PositionWindow(screenFrame);
254 fBarView->Invalidate();
259 void
260 TBarWindow::ScreenChanged(BRect size, color_space depth)
262 BWindow::ScreenChanged(size, depth);
264 fBarView->UpdatePlacement();
268 void
269 TBarWindow::SetDeskbarMenu(TDeskbarMenu* menu)
271 sDeskbarMenu = menu;
275 TDeskbarMenu*
276 TBarWindow::DeskbarMenu()
278 return sDeskbarMenu;
282 void
283 TBarWindow::ShowDeskbarMenu()
285 BMenuBar* menuBar = fBarView->BarMenuBar();
286 if (menuBar == NULL)
287 menuBar = KeyMenuBar();
289 if (menuBar == NULL)
290 return;
292 BMenuBar_StartMenuBar_Hack(menuBar, 0, true, true, NULL);
296 void
297 TBarWindow::ShowTeamMenu()
299 int32 index = 0;
300 if (fBarView->BarMenuBar() == NULL)
301 index = 2;
303 if (KeyMenuBar() == NULL)
304 return;
306 BMenuBar_StartMenuBar_Hack(KeyMenuBar(), index, true, true, NULL);
310 // determines the actual location of the window
312 deskbar_location
313 TBarWindow::DeskbarLocation() const
315 bool left = fBarView->Left();
316 bool top = fBarView->Top();
318 if (fBarView->AcrossTop())
319 return B_DESKBAR_TOP;
321 if (fBarView->AcrossBottom())
322 return B_DESKBAR_BOTTOM;
324 if (left && top)
325 return B_DESKBAR_LEFT_TOP;
327 if (!left && top)
328 return B_DESKBAR_RIGHT_TOP;
330 if (left && !top)
331 return B_DESKBAR_LEFT_BOTTOM;
333 return B_DESKBAR_RIGHT_BOTTOM;
337 void
338 TBarWindow::GetLocation(BMessage* message)
340 BMessage reply('rply');
341 reply.AddInt32("location", (int32)DeskbarLocation());
342 reply.AddBool("expanded", fBarView->ExpandoState());
344 message->SendReply(&reply);
348 void
349 TBarWindow::SetDeskbarLocation(deskbar_location location, bool newExpandState)
351 // left top and right top are the only two that
352 // currently pay attention to expand, ignore for all others
354 bool left = false, top = true, vertical, expand;
356 switch (location) {
357 case B_DESKBAR_TOP:
358 left = true;
359 top = true;
360 vertical = false;
361 expand = true;
362 break;
364 case B_DESKBAR_BOTTOM:
365 left = true;
366 top = false;
367 vertical = false;
368 expand = true;
369 break;
371 case B_DESKBAR_LEFT_TOP:
372 left = true;
373 top = true;
374 vertical = true;
375 expand = newExpandState;
376 break;
378 case B_DESKBAR_RIGHT_TOP:
379 left = false;
380 top = true;
381 vertical = true;
382 expand = newExpandState;
383 break;
385 case B_DESKBAR_LEFT_BOTTOM:
386 left = true;
387 top = false;
388 vertical = true;
389 expand = false;
390 break;
392 case B_DESKBAR_RIGHT_BOTTOM:
393 left = false;
394 top = false;
395 vertical = true;
396 expand = false;
397 break;
399 default:
400 left = true;
401 top = true;
402 vertical = false;
403 expand = true;
404 break;
407 fBarView->ChangeState(expand, vertical, left, top);
411 void
412 TBarWindow::SetLocation(BMessage* message)
414 deskbar_location location;
415 bool expand;
416 if (message->FindInt32("location", (int32*)&location) == B_OK
417 && message->FindBool("expand", &expand) == B_OK)
418 SetDeskbarLocation(location, expand);
422 void
423 TBarWindow::IsExpanded(BMessage* message)
425 BMessage reply('rply');
426 reply.AddBool("expanded", fBarView->ExpandoState());
427 message->SendReply(&reply);
431 void
432 TBarWindow::Expand(BMessage* message)
434 bool expand;
435 if (message->FindBool("expand", &expand) == B_OK) {
436 bool vertical = fBarView->Vertical();
437 bool left = fBarView->Left();
438 bool top = fBarView->Top();
439 fBarView->ChangeState(expand, vertical, left, top);
444 void
445 TBarWindow::ItemInfo(BMessage* message)
447 BMessage replyMsg;
448 const char* name;
449 int32 id;
450 DeskbarShelf shelf;
451 if (message->FindInt32("id", &id) == B_OK) {
452 if (fBarView->ItemInfo(id, &name, &shelf) == B_OK) {
453 replyMsg.AddString("name", name);
454 #if SHELF_AWARE
455 replyMsg.AddInt32("shelf", (int32)shelf);
456 #endif
458 } else if (message->FindString("name", &name) == B_OK) {
459 if (fBarView->ItemInfo(name, &id, &shelf) == B_OK) {
460 replyMsg.AddInt32("id", id);
461 #if SHELF_AWARE
462 replyMsg.AddInt32("shelf", (int32)shelf);
463 #endif
467 message->SendReply(&replyMsg);
471 void
472 TBarWindow::ItemExists(BMessage* message)
474 BMessage replyMsg;
475 const char* name;
476 int32 id;
477 DeskbarShelf shelf;
479 #if SHELF_AWARE
480 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK)
481 #endif
482 shelf = B_DESKBAR_TRAY;
484 bool exists = false;
485 if (message->FindInt32("id", &id) == B_OK)
486 exists = fBarView->ItemExists(id, shelf);
487 else if (message->FindString("name", &name) == B_OK)
488 exists = fBarView->ItemExists(name, shelf);
490 replyMsg.AddBool("exists", exists);
491 message->SendReply(&replyMsg);
495 void
496 TBarWindow::CountItems(BMessage* message)
498 DeskbarShelf shelf;
500 #if SHELF_AWARE
501 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK)
502 #endif
503 shelf = B_DESKBAR_TRAY;
505 BMessage reply('rply');
506 reply.AddInt32("count", fBarView->CountItems(shelf));
507 message->SendReply(&reply);
511 void
512 TBarWindow::AddItem(BMessage* message)
514 DeskbarShelf shelf = B_DESKBAR_TRAY;
515 entry_ref ref;
516 int32 id = 999;
517 BMessage reply;
518 status_t err = B_ERROR;
520 BMessage* archivedView = new BMessage();
521 ObjectDeleter<BMessage> deleter(archivedView);
522 if (message->FindMessage("view", archivedView) == B_OK) {
523 #if SHELF_AWARE
524 message->FindInt32("shelf", &shelf);
525 #endif
526 err = fBarView->AddItem(archivedView, shelf, &id);
527 if (err == B_OK) {
528 // Detach the deleter since AddReplicant is taking ownership
529 // on success. This should be changed on server side.
530 deleter.Detach();
532 } else if (message->FindRef("addon", &ref) == B_OK) {
533 BEntry entry(&ref);
534 err = entry.InitCheck();
535 if (err == B_OK)
536 err = fBarView->AddItem(&entry, shelf, &id);
539 if (err == B_OK)
540 reply.AddInt32("id", id);
541 else
542 reply.AddInt32("error", err);
544 message->SendReply(&reply);
548 void
549 TBarWindow::RemoveItem(BMessage* message)
551 int32 id;
552 const char* name;
554 // ids ought to be unique across all shelves, assuming, of course,
555 // that sometime in the future there may be more than one
556 #if SHELF_AWARE
557 if (message->FindInt32("shelf", (int32*)&shelf) == B_OK) {
558 if (message->FindString("name", &name) == B_OK)
559 fBarView->RemoveItem(name, shelf);
560 } else {
561 #endif
562 if (message->FindInt32("id", &id) == B_OK) {
563 fBarView->RemoveItem(id);
564 // remove the following two lines if and when the
565 // shelf option returns
566 } else if (message->FindString("name", &name) == B_OK)
567 fBarView->RemoveItem(name, B_DESKBAR_TRAY);
569 #if SHELF_AWARE
571 #endif
575 void
576 TBarWindow::GetIconFrame(BMessage* message)
578 BRect frame(0, 0, 0, 0);
580 const char* name;
581 int32 id;
582 if (message->FindInt32("id", &id) == B_OK)
583 frame = fBarView->IconFrame(id);
584 else if (message->FindString("name", &name) == B_OK)
585 frame = fBarView->IconFrame(name);
587 BMessage reply('rply');
588 reply.AddRect("frame", frame);
589 message->SendReply(&reply);
593 bool
594 TBarWindow::IsShowingMenu() const
596 return fShowingMenu;
600 bool
601 TBarWindow::_IsFocusMessage(BMessage* message)
603 BMessage::Private messagePrivate(message);
604 if (!messagePrivate.UsePreferredTarget())
605 return false;
607 bool feedFocus;
608 if (message->HasInt32("_token")
609 && (message->FindBool("_feed_focus", &feedFocus) != B_OK || !feedFocus))
610 return false;
612 return true;