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 <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> 54 55 #include <DeskbarPrivate.h> 56 #include <tracker_private.h> 57 58 #include "BarApp.h" 59 #include "BarMenuBar.h" 60 #include "BarView.h" 61 #include "DeskbarUtils.h" 62 #include "DeskbarMenu.h" 63 #include "ExpandoMenuBar.h" 64 #include "StatusView.h" 65 66 67 #undef B_TRANSLATION_CONTEXT 68 #define B_TRANSLATION_CONTEXT "MainWindow" 69 70 71 // This is a bit of a hack to be able to call BMenuBar::StartMenuBar(), which 72 // is private. Don't do this at home! 73 class TStartableMenuBar : public BMenuBar { 74 public: 75 TStartableMenuBar(); 76 void StartMenuBar(int32 menuIndex, bool sticky = true, bool showMenu = false, 77 BRect* special_rect = NULL) { BMenuBar::StartMenuBar(menuIndex, sticky, showMenu, 78 special_rect); } 79 }; 80 81 82 TDeskbarMenu* TBarWindow::sDeskbarMenu = NULL; 83 84 85 TBarWindow::TBarWindow() 86 : 87 BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f), 88 B_TRANSLATE_SYSTEM_NAME("Deskbar"), B_BORDERED_WINDOW, 89 B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE 90 | B_NOT_MINIMIZABLE | B_NOT_MOVABLE | B_NOT_V_RESIZABLE 91 | B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS, 92 B_ALL_WORKSPACES), 93 fShowingMenu(false) 94 { 95 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 96 if (settings->alwaysOnTop) 97 SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 98 99 fBarView = new TBarView(Bounds(), settings->vertical, settings->left, 100 settings->top, settings->state, settings->width); 101 AddChild(fBarView); 102 103 RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY); 104 AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton)); 105 } 106 107 108 void 109 TBarWindow::MenusBeginning() 110 { 111 BPath path; 112 entry_ref ref; 113 BEntry entry; 114 115 if (GetDeskbarSettingsDirectory(path) == B_OK 116 && path.Append(kDeskbarMenuEntriesFileName) == B_OK 117 && entry.SetTo(path.Path(), true) == B_OK 118 && entry.Exists() 119 && entry.GetRef(&ref) == B_OK) { 120 sDeskbarMenu->SetNavDir(&ref); 121 } else if (GetDeskbarDataDirectory(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 { 128 // this really should never happen 129 TRESPASS(); 130 return; 131 } 132 133 sDeskbarMenu->ResetTargets(); 134 135 fShowingMenu = true; 136 BWindow::MenusBeginning(); 137 } 138 139 140 void 141 TBarWindow::MenusEnded() 142 { 143 fShowingMenu = false; 144 BWindow::MenusEnded(); 145 146 if (sDeskbarMenu->LockLooper()) { 147 sDeskbarMenu->ForceRebuild(); 148 sDeskbarMenu->UnlockLooper(); 149 } 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 kMsgLocation: 165 GetLocation(message); 166 break; 167 168 case kMsgSetLocation: 169 SetLocation(message); 170 break; 171 172 case kMsgIsExpanded: 173 IsExpanded(message); 174 break; 175 176 case kMsgExpand: 177 Expand(message); 178 break; 179 180 case kMsgGetItemInfo: 181 ItemInfo(message); 182 break; 183 184 case kMsgHasItem: 185 ItemExists(message); 186 break; 187 188 case kMsgCountItems: 189 CountItems(message); 190 break; 191 192 case kMsgMaxItemSize: 193 MaxItemSize(message); 194 break; 195 196 case kMsgAddAddOn: 197 case kMsgAddView: 198 AddItem(message); 199 break; 200 201 case kMsgRemoveItem: 202 RemoveItem(message); 203 break; 204 205 case 'iloc': 206 GetIconFrame(message); 207 break; 208 209 default: 210 BWindow::MessageReceived(message); 211 break; 212 } 213 } 214 215 216 void 217 TBarWindow::Minimize(bool minimize) 218 { 219 // Don't allow the Deskbar to be minimized 220 if (!minimize) 221 BWindow::Minimize(false); 222 } 223 224 225 void 226 TBarWindow::FrameResized(float width, float height) 227 { 228 if (!fBarView->Vertical()) 229 return BWindow::FrameResized(width, height); 230 231 bool setToHiddenSize = static_cast<TBarApp*>(be_app)->Settings()->autoHide 232 && fBarView->IsHidden() && !fBarView->DragRegion()->IsDragging(); 233 if (!setToHiddenSize) { 234 // constrain within limits 235 float newWidth; 236 if (width < gMinimumWindowWidth) 237 newWidth = gMinimumWindowWidth; 238 else if (width > gMaximumWindowWidth) 239 newWidth = gMaximumWindowWidth; 240 else 241 newWidth = width; 242 243 float oldWidth = static_cast<TBarApp*>(be_app)->Settings()->width; 244 245 // update width setting 246 static_cast<TBarApp*>(be_app)->Settings()->width = newWidth; 247 248 if (oldWidth != newWidth) { 249 fBarView->ResizeTo(width, fBarView->Bounds().Height()); 250 if (fBarView->Vertical() && fBarView->ExpandoState()) 251 fBarView->ExpandoMenuBar()->SetMaxContentWidth(width); 252 253 fBarView->UpdatePlacement(); 254 } 255 } 256 } 257 258 259 void 260 TBarWindow::SaveSettings() 261 { 262 fBarView->SaveSettings(); 263 } 264 265 266 bool 267 TBarWindow::QuitRequested() 268 { 269 be_app->PostMessage(B_QUIT_REQUESTED); 270 271 return BWindow::QuitRequested(); 272 } 273 274 275 void 276 TBarWindow::WorkspaceActivated(int32 workspace, bool active) 277 { 278 BWindow::WorkspaceActivated(workspace, active); 279 280 if (active && !(fBarView->ExpandoState() && fBarView->Vertical())) 281 fBarView->UpdatePlacement(); 282 else { 283 BRect screenFrame = (BScreen(fBarView->Window())).Frame(); 284 fBarView->SizeWindow(screenFrame); 285 fBarView->PositionWindow(screenFrame); 286 fBarView->Invalidate(); 287 } 288 } 289 290 291 void 292 TBarWindow::ScreenChanged(BRect size, color_space depth) 293 { 294 BWindow::ScreenChanged(size, depth); 295 296 fBarView->UpdatePlacement(); 297 } 298 299 300 void 301 TBarWindow::SetDeskbarMenu(TDeskbarMenu* menu) 302 { 303 sDeskbarMenu = menu; 304 } 305 306 307 TDeskbarMenu* 308 TBarWindow::DeskbarMenu() 309 { 310 return sDeskbarMenu; 311 } 312 313 314 void 315 TBarWindow::ShowDeskbarMenu() 316 { 317 TStartableMenuBar* menuBar = (TStartableMenuBar*)fBarView->BarMenuBar(); 318 if (menuBar == NULL) 319 menuBar = (TStartableMenuBar*)KeyMenuBar(); 320 321 if (menuBar == NULL) 322 return; 323 324 menuBar->StartMenuBar(0, true, true, NULL); 325 } 326 327 328 void 329 TBarWindow::ShowTeamMenu() 330 { 331 int32 index = 0; 332 if (fBarView->BarMenuBar() == NULL) 333 index = 2; 334 335 if (KeyMenuBar() == NULL) 336 return; 337 338 ((TStartableMenuBar*)KeyMenuBar())->StartMenuBar(index, true, true, NULL); 339 } 340 341 342 // determines the actual location of the window 343 344 deskbar_location 345 TBarWindow::DeskbarLocation() const 346 { 347 bool left = fBarView->Left(); 348 bool top = fBarView->Top(); 349 350 if (fBarView->AcrossTop()) 351 return B_DESKBAR_TOP; 352 353 if (fBarView->AcrossBottom()) 354 return B_DESKBAR_BOTTOM; 355 356 if (left && top) 357 return B_DESKBAR_LEFT_TOP; 358 359 if (!left && top) 360 return B_DESKBAR_RIGHT_TOP; 361 362 if (left && !top) 363 return B_DESKBAR_LEFT_BOTTOM; 364 365 return B_DESKBAR_RIGHT_BOTTOM; 366 } 367 368 369 void 370 TBarWindow::GetLocation(BMessage* message) 371 { 372 BMessage reply('rply'); 373 reply.AddInt32("location", (int32)DeskbarLocation()); 374 reply.AddBool("expanded", fBarView->ExpandoState()); 375 376 message->SendReply(&reply); 377 } 378 379 380 void 381 TBarWindow::SetDeskbarLocation(deskbar_location location, bool newExpandState) 382 { 383 // left top and right top are the only two that 384 // currently pay attention to expand, ignore for all others 385 386 bool left = false, top = true, vertical, expand; 387 388 switch (location) { 389 case B_DESKBAR_TOP: 390 left = true; 391 top = true; 392 vertical = false; 393 expand = true; 394 break; 395 396 case B_DESKBAR_BOTTOM: 397 left = true; 398 top = false; 399 vertical = false; 400 expand = true; 401 break; 402 403 case B_DESKBAR_LEFT_TOP: 404 left = true; 405 top = true; 406 vertical = true; 407 expand = newExpandState; 408 break; 409 410 case B_DESKBAR_RIGHT_TOP: 411 left = false; 412 top = true; 413 vertical = true; 414 expand = newExpandState; 415 break; 416 417 case B_DESKBAR_LEFT_BOTTOM: 418 left = true; 419 top = false; 420 vertical = true; 421 expand = false; 422 break; 423 424 case B_DESKBAR_RIGHT_BOTTOM: 425 left = false; 426 top = false; 427 vertical = true; 428 expand = false; 429 break; 430 431 default: 432 left = true; 433 top = true; 434 vertical = false; 435 expand = true; 436 break; 437 } 438 439 fBarView->ChangeState(expand, vertical, left, top); 440 } 441 442 443 void 444 TBarWindow::SetLocation(BMessage* message) 445 { 446 deskbar_location location; 447 bool expand; 448 if (message->FindInt32("location", (int32*)&location) == B_OK 449 && message->FindBool("expand", &expand) == B_OK) 450 SetDeskbarLocation(location, expand); 451 } 452 453 454 void 455 TBarWindow::IsExpanded(BMessage* message) 456 { 457 BMessage reply('rply'); 458 reply.AddBool("expanded", fBarView->ExpandoState()); 459 message->SendReply(&reply); 460 } 461 462 463 void 464 TBarWindow::Expand(BMessage* message) 465 { 466 bool expand; 467 if (message->FindBool("expand", &expand) == B_OK) { 468 bool vertical = fBarView->Vertical(); 469 bool left = fBarView->Left(); 470 bool top = fBarView->Top(); 471 fBarView->ChangeState(expand, vertical, left, top); 472 } 473 } 474 475 476 void 477 TBarWindow::ItemInfo(BMessage* message) 478 { 479 BMessage replyMsg; 480 const char* name; 481 int32 id; 482 DeskbarShelf shelf; 483 if (message->FindInt32("id", &id) == B_OK) { 484 if (fBarView->ItemInfo(id, &name, &shelf) == B_OK) { 485 replyMsg.AddString("name", name); 486 #if SHELF_AWARE 487 replyMsg.AddInt32("shelf", (int32)shelf); 488 #endif 489 } 490 } else if (message->FindString("name", &name) == B_OK) { 491 if (fBarView->ItemInfo(name, &id, &shelf) == B_OK) { 492 replyMsg.AddInt32("id", id); 493 #if SHELF_AWARE 494 replyMsg.AddInt32("shelf", (int32)shelf); 495 #endif 496 } 497 } 498 499 message->SendReply(&replyMsg); 500 } 501 502 503 void 504 TBarWindow::ItemExists(BMessage* message) 505 { 506 BMessage replyMsg; 507 const char* name; 508 int32 id; 509 DeskbarShelf shelf; 510 511 #if SHELF_AWARE 512 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK) 513 #endif 514 shelf = B_DESKBAR_TRAY; 515 516 bool exists = false; 517 if (message->FindInt32("id", &id) == B_OK) 518 exists = fBarView->ItemExists(id, shelf); 519 else if (message->FindString("name", &name) == B_OK) 520 exists = fBarView->ItemExists(name, shelf); 521 522 replyMsg.AddBool("exists", exists); 523 message->SendReply(&replyMsg); 524 } 525 526 527 void 528 TBarWindow::CountItems(BMessage* message) 529 { 530 DeskbarShelf shelf; 531 532 #if SHELF_AWARE 533 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK) 534 #endif 535 shelf = B_DESKBAR_TRAY; 536 537 BMessage reply('rply'); 538 reply.AddInt32("count", fBarView->CountItems(shelf)); 539 message->SendReply(&reply); 540 } 541 542 543 void 544 TBarWindow::MaxItemSize(BMessage* message) 545 { 546 DeskbarShelf shelf; 547 #if SHELF_AWARE 548 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK) 549 #endif 550 shelf = B_DESKBAR_TRAY; 551 552 BSize size = fBarView->MaxItemSize(shelf); 553 554 BMessage reply('rply'); 555 reply.AddFloat("width", size.width); 556 reply.AddFloat("height", size.height); 557 message->SendReply(&reply); 558 } 559 560 561 void 562 TBarWindow::AddItem(BMessage* message) 563 { 564 DeskbarShelf shelf = B_DESKBAR_TRAY; 565 entry_ref ref; 566 int32 id = 999; 567 BMessage reply; 568 status_t err = B_ERROR; 569 570 BMessage* archivedView = new BMessage(); 571 ObjectDeleter<BMessage> deleter(archivedView); 572 if (message->FindMessage("view", archivedView) == B_OK) { 573 #if SHELF_AWARE 574 message->FindInt32("shelf", &shelf); 575 #endif 576 err = fBarView->AddItem(archivedView, shelf, &id); 577 if (err == B_OK) { 578 // Detach the deleter since AddReplicant is taking ownership 579 // on success. This should be changed on server side. 580 deleter.Detach(); 581 } 582 } else if (message->FindRef("addon", &ref) == B_OK) { 583 BEntry entry(&ref); 584 err = entry.InitCheck(); 585 if (err == B_OK) 586 err = fBarView->AddItem(&entry, shelf, &id); 587 } 588 589 if (err == B_OK) 590 reply.AddInt32("id", id); 591 else 592 reply.AddInt32("error", err); 593 594 message->SendReply(&reply); 595 } 596 597 598 void 599 TBarWindow::RemoveItem(BMessage* message) 600 { 601 int32 id; 602 const char* name; 603 604 // ids ought to be unique across all shelves, assuming, of course, 605 // that sometime in the future there may be more than one 606 #if SHELF_AWARE 607 if (message->FindInt32("shelf", (int32*)&shelf) == B_OK) { 608 if (message->FindString("name", &name) == B_OK) 609 fBarView->RemoveItem(name, shelf); 610 } else { 611 #endif 612 if (message->FindInt32("id", &id) == B_OK) { 613 fBarView->RemoveItem(id); 614 // remove the following two lines if and when the 615 // shelf option returns 616 } else if (message->FindString("name", &name) == B_OK) 617 fBarView->RemoveItem(name, B_DESKBAR_TRAY); 618 619 #if SHELF_AWARE 620 } 621 #endif 622 } 623 624 625 void 626 TBarWindow::GetIconFrame(BMessage* message) 627 { 628 BRect frame(0, 0, 0, 0); 629 630 const char* name; 631 int32 id; 632 if (message->FindInt32("id", &id) == B_OK) 633 frame = fBarView->IconFrame(id); 634 else if (message->FindString("name", &name) == B_OK) 635 frame = fBarView->IconFrame(name); 636 637 BMessage reply('rply'); 638 reply.AddRect("frame", frame); 639 message->SendReply(&reply); 640 } 641 642 643 bool 644 TBarWindow::IsShowingMenu() const 645 { 646 return fShowingMenu; 647 } 648 649 650 bool 651 TBarWindow::_IsFocusMessage(BMessage* message) 652 { 653 BMessage::Private messagePrivate(message); 654 if (!messagePrivate.UsePreferredTarget()) 655 return false; 656 657 bool feedFocus; 658 if (message->HasInt32("_token") 659 && (message->FindBool("_feed_focus", &feedFocus) != B_OK || !feedFocus)) 660 return false; 661 662 return true; 663 } 664