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 #include <Debug.h> 37 38 #include "BarView.h" 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include <AppFileInfo.h> 45 #include <Bitmap.h> 46 #include <Directory.h> 47 #include <NodeInfo.h> 48 #include <Roster.h> 49 #include <Screen.h> 50 #include <String.h> 51 52 #include "icons.h" 53 #include "BarApp.h" 54 #include "BarMenuBar.h" 55 #include "BarWindow.h" 56 #include "BeMenu.h" 57 #include "DeskBarUtils.h" 58 #include "ExpandoMenuBar.h" 59 #include "FSUtils.h" 60 #include "ResourceSet.h" 61 #include "StatusView.h" 62 #include "TeamMenuItem.h" 63 64 65 const int32 kDefaultRecentDocCount = 10; 66 const int32 kDefaultRecentFolderCount = 10; 67 const int32 kDefaultRecentAppCount = 10; 68 69 const int32 kMenuTrackMargin = 20; 70 71 72 TBarView::TBarView(BRect frame, bool vertical, bool left, bool top, 73 bool showInterval, uint32 state, float, bool showTime) 74 : BView(frame, "BarView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), 75 fBarMenuBar(NULL), 76 fExpando(NULL), 77 fTrayLocation(1), 78 fShowInterval(showInterval), 79 fShowClock(showTime), 80 fVertical(vertical), 81 fTop(top), 82 fLeft(left), 83 fState(static_cast<int32>(state)), 84 fRefsRcvdOnly(true), 85 fDragMessage(NULL), 86 fCachedTypesList(NULL), 87 fMaxRecentDocs(kDefaultRecentDocCount), 88 fMaxRecentApps(kDefaultRecentAppCount), 89 fLastDragItem(NULL) 90 { 91 fReplicantTray = new TReplicantTray(this, fVertical); 92 fDragRegion = new TDragRegion(this, fReplicantTray); 93 fDragRegion->AddChild(fReplicantTray); 94 if (fTrayLocation != 0) 95 AddChild(fDragRegion); 96 } 97 98 99 TBarView::~TBarView() 100 { 101 delete fDragMessage; 102 delete fCachedTypesList; 103 104 RemoveExpandedItems(); 105 } 106 107 108 void 109 TBarView::AttachedToWindow() 110 { 111 BView::AttachedToWindow(); 112 113 SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR)); 114 SetFont(be_plain_font); 115 116 UpdateEventMask(); 117 UpdatePlacement(); 118 119 fTrackingHookData.fTrackingHook = MenuTrackingHook; 120 fTrackingHookData.fTarget = BMessenger(this); 121 fTrackingHookData.fDragMessage = new BMessage(B_REFS_RECEIVED); 122 } 123 124 125 void 126 TBarView::DetachedFromWindow() 127 { 128 delete fTrackingHookData.fDragMessage; 129 fTrackingHookData.fDragMessage = NULL; 130 } 131 132 133 void 134 TBarView::Draw(BRect) 135 { 136 BRect bounds(Bounds()); 137 138 rgb_color hilite = tint_color(ViewColor(), B_DARKEN_1_TINT); 139 rgb_color light = tint_color(ViewColor(), B_LIGHTEN_2_TINT); 140 141 SetHighColor(hilite); 142 if (AcrossTop()) 143 StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); 144 else if (AcrossBottom()) 145 StrokeLine(bounds.LeftTop(), bounds.RightTop()); 146 147 if (Vertical() && Expando()) { 148 SetHighColor(hilite); 149 BRect frame(fExpando->Frame()); 150 StrokeLine(BPoint(frame.left, frame.top - 1), 151 BPoint(frame.right, frame.top -1)); 152 } 153 } 154 155 156 void 157 TBarView::MessageReceived(BMessage* message) 158 { 159 switch (message->what) { 160 case B_REFS_RECEIVED: 161 // received when an item is selected during DnD 162 // message is targeted here from Be menu 163 HandleBeMenu(message); 164 break; 165 166 case B_ARCHIVED_OBJECT: 167 { 168 // this message has been retargeted to here 169 // instead of directly to the replicant tray 170 // so that I can follow the common pathway 171 // for adding icons to the tray 172 int32 id; 173 AddItem(new BMessage(*message), B_DESKBAR_TRAY, &id); 174 break; 175 } 176 177 default: 178 BView::MessageReceived(message); 179 } 180 } 181 182 183 void 184 TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) 185 { 186 if (Window() == NULL || EventMask() == 0) 187 return; 188 189 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 190 bool alwaysOnTop = settings->alwaysOnTop; 191 bool autoRaise = settings->autoRaise; 192 bool autoHide = settings->autoHide; 193 194 if (!autoRaise && !autoHide) 195 return; 196 197 if (DragRegion()->IsDragging()) 198 return; 199 200 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL; 201 202 // Auto-Raise 203 where = ConvertToScreen(where); 204 BScreen screen(Window()); 205 BRect screenFrame = screen.Frame(); 206 if ((where.x == screenFrame.left || where.x == screenFrame.right 207 || where.y == screenFrame.top || where.y == screenFrame.bottom) 208 && Window()->Frame().Contains(where)) { 209 // cursor is on a screen edge within the window frame 210 211 if (!alwaysOnTop && autoRaise && !isTopMost) 212 RaiseDeskbar(true); 213 214 if (autoHide && IsHidden()) 215 HideDeskbar(false); 216 } else { 217 // cursor is not on screen edge 218 BRect preventHideArea = Window()->Frame().InsetByCopy( 219 -kMaxPreventHidingDist, -kMaxPreventHidingDist); 220 221 if (preventHideArea.Contains(where)) 222 return; 223 224 // cursor to bar distance above threshold 225 if (!alwaysOnTop && autoRaise && isTopMost) 226 RaiseDeskbar(false); 227 228 if (autoHide && !IsHidden()) 229 HideDeskbar(true); 230 } 231 } 232 233 234 void 235 TBarView::MouseDown(BPoint where) 236 { 237 where = ConvertToScreen(where); 238 239 if (Window()->Frame().Contains(where)) { 240 Window()->Activate(); 241 242 if ((modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY 243 | B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) { 244 // The window key was pressed - enter dragging code 245 DragRegion()->MouseDown( 246 DragRegion()->DragRegion().LeftTop()); 247 return; 248 } 249 } else { 250 // hide deskbar if required 251 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 252 bool alwaysOnTop = settings->alwaysOnTop; 253 bool autoRaise = settings->autoRaise; 254 bool autoHide = settings->autoHide; 255 bool isTopMost = Window()->Feel() == B_FLOATING_ALL_WINDOW_FEEL; 256 257 if (!alwaysOnTop && autoRaise && isTopMost) 258 RaiseDeskbar(false); 259 260 if (autoHide && !IsHidden()) 261 HideDeskbar(true); 262 } 263 } 264 265 266 void 267 TBarView::PlaceBeMenu() 268 { 269 // top or bottom, full 270 if (!fVertical && fBarMenuBar) { 271 fBarMenuBar->RemoveSelf(); 272 delete fBarMenuBar; 273 fBarMenuBar = NULL; 274 } 275 276 // top or bottom expando mode has Be menu built in for tracking 277 // only for vertical mini or expanded 278 // mini mode will have team menu added as part of BarMenuBar 279 if (fVertical && !fBarMenuBar) { 280 // create the Be menu 281 BRect mbarFrame(Bounds()); 282 mbarFrame.bottom = mbarFrame.top + kMenuBarHeight; 283 fBarMenuBar = new TBarMenuBar(this, mbarFrame, "BarMenuBar"); 284 AddChild(fBarMenuBar); 285 } 286 287 // if there isn't a bemenu at this point, 288 // DB should be in top/bottom mode, else error 289 if (!fBarMenuBar) 290 return; 291 292 float width = sMinimumWindowWidth; 293 BPoint loc(B_ORIGIN); 294 BRect menuFrame(fBarMenuBar->Frame()); 295 if (fState == kFullState) { 296 fBarMenuBar->RemoveTeamMenu(); 297 width = 8 + 16 + 8; 298 loc = Bounds().LeftTop(); 299 } else if (fState == kExpandoState) { 300 // shows apps below tray 301 fBarMenuBar->RemoveTeamMenu(); 302 if (fVertical) 303 width += 1; 304 else 305 width = floorf(width) / 2; 306 loc = Bounds().LeftTop(); 307 } else { 308 // mini mode, BeMenu next to team menu 309 fBarMenuBar->AddTeamMenu(); 310 } 311 312 fBarMenuBar->SmartResize(width, menuFrame.Height()); 313 fBarMenuBar->MoveTo(loc); 314 } 315 316 317 void 318 TBarView::PlaceTray(bool, bool, BRect screenFrame) 319 { 320 BPoint statusLoc; 321 if (fState == kFullState) { 322 fDragRegion->ResizeTo(fBarMenuBar->Frame().Width(), kMenuBarHeight); 323 statusLoc.y = fBarMenuBar->Frame().bottom + 1; 324 statusLoc.x = 0; 325 fDragRegion->MoveTo(statusLoc); 326 327 if (!fReplicantTray->IsHidden()) 328 fReplicantTray->Hide(); 329 330 return; 331 } 332 333 if (fReplicantTray->IsHidden()) 334 fReplicantTray->Show(); 335 336 if (fTrayLocation != 0) { 337 fReplicantTray->SetMultiRow(fVertical); 338 fReplicantTray->RealignReplicants(); 339 fDragRegion->ResizeToPreferred(); 340 341 if (fVertical) { 342 statusLoc.y = fBarMenuBar->Frame().bottom + 1; 343 statusLoc.x = 0; 344 if (Left() && Vertical()) 345 fReplicantTray->MoveTo(5, 2); 346 else 347 fReplicantTray->MoveTo(2, 2); 348 } else { 349 statusLoc.x = screenFrame.right - fDragRegion->Bounds().Width(); 350 statusLoc.y = -1; 351 } 352 353 fDragRegion->MoveTo(statusLoc); 354 } 355 } 356 357 358 void 359 TBarView::PlaceApplicationBar(BRect screenFrame) 360 { 361 if (fExpando != NULL) { 362 fExpando->RemoveSelf(); 363 delete fExpando; 364 fExpando = NULL; 365 } 366 if (fState == kMiniState) 367 return; 368 369 BRect expandoFrame(0, 0, 0, 0); 370 if (fVertical) { 371 // top left/right 372 if (fTrayLocation != 0) 373 expandoFrame.top = fDragRegion->Frame().bottom + 1; 374 else 375 expandoFrame.top = fBarMenuBar->Frame().bottom + 1; 376 377 expandoFrame.bottom = expandoFrame.top + 1; 378 if (fState == kFullState) 379 expandoFrame.right = fBarMenuBar->Frame().Width(); 380 else 381 expandoFrame.right = sMinimumWindowWidth; 382 } else { 383 // top or bottom 384 expandoFrame.top = 0; 385 expandoFrame.bottom = kHModeHeight; 386 if (fTrayLocation != 0) 387 expandoFrame.right = fDragRegion->Frame().left - 1; 388 else 389 expandoFrame.right = screenFrame.Width(); 390 } 391 392 fExpando = new TExpandoMenuBar(this, expandoFrame, "ExpandoMenuBar", 393 fVertical, fState != kFullState); 394 AddChild(fExpando); 395 } 396 397 398 void 399 TBarView::GetPreferredWindowSize(BRect screenFrame, float* width, float* height) 400 { 401 float windowHeight = 0; 402 float windowWidth = sMinimumWindowWidth; 403 bool calcHiddenSize = ((TBarApp*)be_app)->Settings()->autoHide 404 && IsHidden() && !DragRegion()->IsDragging(); 405 406 if (!calcHiddenSize) { 407 if (fState == kFullState) { 408 windowHeight = screenFrame.bottom; 409 windowWidth = fBarMenuBar->Frame().Width(); 410 } else if (fState == kExpandoState) { 411 if (fVertical) { 412 // top left or right 413 windowHeight = fExpando->Frame().bottom; 414 } else { 415 // top or bottom, full 416 fExpando->CheckItemSizes(0); 417 windowHeight = kHModeHeight; 418 windowWidth = screenFrame.Width(); 419 } 420 } else { 421 // four corners 422 if (fTrayLocation != 0) 423 windowHeight = fDragRegion->Frame().bottom; 424 else 425 windowHeight = fBarMenuBar->Frame().bottom; 426 } 427 } else { 428 windowHeight = kHModeHiddenHeight; 429 430 if (fState == kExpandoState && !fVertical) { 431 // top or bottom, full 432 fExpando->CheckItemSizes(0); 433 windowWidth = screenFrame.Width(); 434 } else 435 windowWidth = kHModeHiddenHeight; 436 } 437 438 *width = windowWidth; 439 *height = windowHeight; 440 } 441 442 443 void 444 TBarView::SizeWindow(BRect screenFrame) 445 { 446 float windowWidth, windowHeight; 447 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight); 448 Window()->ResizeTo(windowWidth, windowHeight); 449 if (fExpando) 450 fExpando->CheckForSizeOverrun(); 451 } 452 453 454 void 455 TBarView::PositionWindow(BRect screenFrame) 456 { 457 float windowWidth, windowHeight; 458 GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight); 459 460 BPoint moveLoc(0, 0); 461 // right, expanded 462 if (!fLeft && fVertical) { 463 if (fState == kFullState) 464 moveLoc.x = screenFrame.right - fBarMenuBar->Frame().Width(); 465 else 466 moveLoc.x = screenFrame.right - windowWidth; 467 } 468 469 // bottom, full or corners 470 if (!fTop) 471 moveLoc.y = screenFrame.bottom - windowHeight; 472 473 Window()->MoveTo(moveLoc); 474 } 475 476 477 void 478 TBarView::SaveSettings() 479 { 480 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 481 482 settings->vertical = Vertical(); 483 settings->left = Left(); 484 settings->top = Top(); 485 settings->ampmMode = MilTime(); 486 settings->state = (uint32)State(); 487 settings->width = 0; 488 settings->showTime = ShowingClock(); 489 490 fReplicantTray->RememberClockSettings(); 491 } 492 493 494 void 495 TBarView::UpdateEventMask() 496 { 497 if (((TBarApp*)be_app)->Settings()->autoRaise 498 || ((TBarApp*)be_app)->Settings()->autoHide) 499 SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); 500 else 501 SetEventMask(0); 502 } 503 504 505 void 506 TBarView::UpdatePlacement() 507 { 508 ChangeState(fState, fVertical, fLeft, fTop); 509 } 510 511 512 void 513 TBarView::ChangeState(int32 state, bool vertical, bool left, bool top) 514 { 515 bool vertSwap = (fVertical != vertical); 516 bool leftSwap = (fLeft != left); 517 bool stateChanged = (fState != state); 518 519 fState = state; 520 fVertical = vertical; 521 fLeft = left; 522 fTop = top; 523 524 // Send a message to the preferences window to let it know to enable 525 // or disable preference items 526 if (stateChanged || vertSwap) 527 be_app->PostMessage(kStateChanged); 528 529 BRect screenFrame = (BScreen(Window())).Frame(); 530 531 PlaceBeMenu(); 532 PlaceTray(vertSwap, leftSwap, screenFrame); 533 534 // Keep track of which apps are expanded 535 SaveExpandedItems(); 536 537 PlaceApplicationBar(screenFrame); 538 SizeWindow(screenFrame); 539 PositionWindow(screenFrame); 540 Window()->UpdateIfNeeded(); 541 542 // Re-expand apps 543 ExpandItems(); 544 Invalidate(); 545 } 546 547 548 void 549 TBarView::SaveExpandedItems() 550 { 551 if (fExpando == NULL || fExpando->CountItems() <= 0) 552 return; 553 554 // Get a list of the signatures of expanded apps. Can't use 555 // team_id because there can be more than one team per application 556 for (int32 i = 0; i < fExpando->CountItems(); i++) { 557 TTeamMenuItem* teamItem 558 = dynamic_cast<TTeamMenuItem*>(fExpando->ItemAt(i)); 559 560 if (teamItem != NULL && teamItem->IsExpanded()) 561 AddExpandedItem(teamItem->Signature()); 562 } 563 } 564 565 566 void 567 TBarView::RemoveExpandedItems() 568 { 569 while (!fExpandedItems.IsEmpty()) 570 delete static_cast<BString*>(fExpandedItems.RemoveItem((int32)0)); 571 fExpandedItems.MakeEmpty(); 572 } 573 574 575 void 576 TBarView::ExpandItems() 577 { 578 if (fExpando == NULL || !fVertical || !Expando() 579 || !static_cast<TBarApp*>(be_app)->Settings()->superExpando 580 || fExpandedItems.CountItems() <= 0) 581 return; 582 583 // Start at the 'bottom' of the list working up. 584 // Prevents being thrown off by expanding items. 585 for (int32 i = fExpando->CountItems() - 1; i >= 0; i--) { 586 TTeamMenuItem* teamItem 587 = dynamic_cast<TTeamMenuItem*>(fExpando->ItemAt(i)); 588 589 if (teamItem != NULL) { 590 // Start at the 'bottom' of the fExpandedItems list working up 591 // matching the order of the fExpando list in the outer loop. 592 for (int32 j = fExpandedItems.CountItems() - 1; j >= 0; j--) { 593 BString* itemSig = 594 static_cast<BString*>(fExpandedItems.ItemAt(j)); 595 596 if (itemSig->Compare(teamItem->Signature()) == 0) { 597 // Found it, expand the item and delete signature from 598 // the list so that we don't consider it for later items. 599 teamItem->ToggleExpandState(false); 600 fExpandedItems.RemoveItem(j); 601 delete itemSig; 602 break; 603 } 604 } 605 } 606 } 607 608 // Clean up the expanded items list 609 RemoveExpandedItems(); 610 611 fExpando->SizeWindow(); 612 } 613 614 615 void 616 TBarView::AddExpandedItem(const char* signature) 617 { 618 bool shouldAdd = true; 619 620 for (int32 i = 0; i < fExpandedItems.CountItems(); i++) { 621 BString *itemSig = static_cast<BString*>(fExpandedItems.ItemAt(i)); 622 if (itemSig->Compare(signature) == 0) { 623 // already in the list, don't add the signature 624 shouldAdd = false; 625 break; 626 } 627 } 628 629 if (shouldAdd) 630 fExpandedItems.AddItem(static_cast<void*>(new BString(signature))); 631 } 632 633 634 void 635 TBarView::RaiseDeskbar(bool raise) 636 { 637 if (raise) 638 Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 639 else 640 Window()->SetFeel(B_NORMAL_WINDOW_FEEL); 641 } 642 643 644 void 645 TBarView::HideDeskbar(bool hide) 646 { 647 BScreen screen(Window()); 648 BRect screenFrame = screen.Frame(); 649 650 if (hide) { 651 Hide(); 652 PositionWindow(screenFrame); 653 SizeWindow(screenFrame); 654 } else { 655 Show(); 656 SizeWindow(screenFrame); 657 PositionWindow(screenFrame); 658 } 659 } 660 661 662 // window placement functions 663 664 bool 665 TBarView::Vertical() const 666 { 667 return fVertical; 668 } 669 670 671 bool 672 TBarView::Left() const 673 { 674 return fLeft; 675 } 676 677 678 bool 679 TBarView::AcrossTop() const 680 { 681 return fTop && !fVertical; 682 } 683 684 685 bool 686 TBarView::AcrossBottom() const 687 { 688 return !fTop && !fVertical; 689 } 690 691 692 bool 693 TBarView::Expando() const 694 { 695 return fState == kExpandoState; 696 } 697 698 699 bool 700 TBarView::Top() const 701 { 702 return fTop; 703 } 704 705 706 int32 707 TBarView::State() const 708 { 709 return fState; 710 } 711 712 713 // optional functionality functions 714 715 bool 716 TBarView::MilTime() const 717 { 718 return fShowInterval; 719 } 720 721 722 void 723 TBarView::ShowClock(bool on) 724 { 725 fShowClock = on; 726 } 727 728 729 bool 730 TBarView::ShowingClock() const 731 { 732 return fShowClock; 733 } 734 735 736 // #pragma mark - Drag and Drop 737 738 739 void 740 TBarView::CacheDragData(const BMessage* incoming) 741 { 742 if (!incoming) 743 return; 744 745 if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage)) 746 return; 747 748 // disposes then fills cached drag message and 749 // mimetypes list 750 SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList); 751 } 752 753 754 static void 755 init_tracking_hook(BMenuItem* item, 756 bool (*hookFunction)(BMenu*, void*), void* state) 757 { 758 if (!item) 759 return; 760 761 BMenu* windowMenu = item->Submenu(); 762 if (windowMenu) { 763 // have a menu, set the tracking hook 764 windowMenu->SetTrackingHook(hookFunction, state); 765 } 766 } 767 768 769 status_t 770 TBarView::DragStart() 771 { 772 if (!Dragging()) 773 return B_OK; 774 775 BPoint loc; 776 uint32 buttons; 777 GetMouse(&loc, &buttons); 778 779 if (fExpando && fExpando->Frame().Contains(loc)) { 780 ConvertToScreen(&loc); 781 BPoint expandoLocation = fExpando->ConvertFromScreen(loc); 782 TTeamMenuItem* item = fExpando->TeamItemAtPoint(expandoLocation); 783 784 if (fLastDragItem) 785 init_tracking_hook(fLastDragItem, NULL, NULL); 786 787 if (item) { 788 if (item == fLastDragItem) 789 return B_OK; 790 791 fLastDragItem = item; 792 } 793 } 794 795 return B_OK; 796 } 797 798 799 bool 800 TBarView::MenuTrackingHook(BMenu* menu, void* castToThis) 801 { 802 // return true if the menu should go away 803 TrackingHookData* data = static_cast<TrackingHookData*>(castToThis); 804 if (!data) 805 return false; 806 807 TBarView* barview = dynamic_cast<TBarView*>(data->fTarget.Target(NULL)); 808 if (!barview || !menu->LockLooper()) 809 return false; 810 811 uint32 buttons; 812 BPoint location; 813 menu->GetMouse(&location, &buttons); 814 815 bool endMenu = true; 816 BRect frame(menu->Bounds()); 817 frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin); 818 819 if (frame.Contains(location)) { 820 // if current loc is still in the menu 821 // keep tracking 822 endMenu = false; 823 } else { 824 // see if the mouse is in the team/be menu item 825 menu->ConvertToScreen(&location); 826 if (barview->LockLooper()) { 827 TExpandoMenuBar* expando = barview->ExpandoMenuBar(); 828 TBeMenu* bemenu 829 = (dynamic_cast<TBarWindow*>(barview->Window()))->BeMenu(); 830 831 if (bemenu && bemenu->LockLooper()) { 832 bemenu->ConvertFromScreen(&location); 833 if (bemenu->Frame().Contains(location)) 834 endMenu = false; 835 836 bemenu->UnlockLooper(); 837 } 838 839 if (endMenu && expando) { 840 expando->ConvertFromScreen(&location); 841 BMenuItem* item = expando->TeamItemAtPoint(location); 842 if (item) 843 endMenu = false; 844 } 845 barview->UnlockLooper(); 846 } 847 } 848 849 menu->UnlockLooper(); 850 return endMenu; 851 } 852 853 854 // used by WindowMenu and TeamMenu to 855 // set the tracking hook for dragging 856 TrackingHookData* 857 TBarView::GetTrackingHookData() 858 { 859 // all tracking hook data is 860 // preset in AttachedToWindow 861 // data should never change 862 return &fTrackingHookData; 863 } 864 865 866 void 867 TBarView::DragStop(bool full) 868 { 869 if (!Dragging()) 870 return; 871 872 if (fExpando) { 873 if (fLastDragItem) { 874 init_tracking_hook(fLastDragItem, NULL, NULL); 875 fLastDragItem = NULL; 876 } 877 } 878 879 if (full) { 880 delete fDragMessage; 881 fDragMessage = NULL; 882 883 delete fCachedTypesList; 884 fCachedTypesList = NULL; 885 } 886 } 887 888 889 bool 890 TBarView::AppCanHandleTypes(const char* signature) 891 { 892 // used for filtering apps/teams in the ExpandoMenuBar and TeamMenu 893 894 if (modifiers() & B_CONTROL_KEY) { 895 // control key forces acceptance, just like drag&drop on icons 896 return true; 897 } 898 899 if (!signature || strlen(signature) == 0 900 || !fCachedTypesList || fCachedTypesList->CountItems() == 0) 901 return false; 902 903 if (strcmp(signature, kTrackerSignature) == 0) { 904 // tracker should support all types 905 // and should pass them on to the appropriate application 906 return true; 907 } 908 909 entry_ref hintref; 910 BMimeType appmime(signature); 911 if (appmime.GetAppHint(&hintref) != B_OK) 912 return false; 913 914 // an app was found, now see if it supports any of 915 // the refs in the message 916 BFile file(&hintref, O_RDONLY); 917 BAppFileInfo fileinfo(&file); 918 919 // scan the cached mimetype list and see if this app 920 // supports anything in the list 921 // only one item needs to match in the list of refs 922 923 int32 count = fCachedTypesList->CountItems(); 924 for (int32 i = 0 ; i < count ; i++) { 925 if (fileinfo.IsSupportedType(fCachedTypesList->ItemAt(i)->String())) 926 return true; 927 } 928 929 return false; 930 } 931 932 933 void 934 TBarView::SetDragOverride(bool on) 935 { 936 fRefsRcvdOnly = on; 937 } 938 939 940 bool 941 TBarView::DragOverride() 942 { 943 return fRefsRcvdOnly; 944 } 945 946 947 status_t 948 TBarView::SendDragMessage(const char* signature, entry_ref* ref) 949 { 950 status_t err = B_ERROR; 951 if (fDragMessage) { 952 if (fRefsRcvdOnly) { 953 // current message sent to apps is only B_REFS_RECEIVED 954 fDragMessage->what = B_REFS_RECEIVED; 955 } 956 957 BRoster roster; 958 if (signature && strlen(signature) > 0 && roster.IsRunning(signature)) { 959 BMessenger mess(signature); 960 // drag message is still owned by DB, copy is sent 961 // can toss it after send 962 err = mess.SendMessage(fDragMessage); 963 } else if (ref) { 964 FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage, 965 true, true); 966 } else if (signature && strlen(signature) > 0) { 967 roster.Launch(signature, fDragMessage); 968 } 969 } 970 return err; 971 } 972 973 974 bool 975 TBarView::InvokeItem(const char* signature) 976 { 977 // sent from TeamMenuItem 978 if (Dragging() && AppCanHandleTypes(signature)) { 979 SendDragMessage(signature); 980 // invoking okay to toss memory 981 DragStop(true); 982 return true; 983 } 984 985 return false; 986 } 987 988 989 void 990 TBarView::HandleBeMenu(BMessage* messagewithdestination) 991 { 992 if (!Dragging()) 993 return; 994 995 // in mini-mode 996 if (Vertical() && !Expando()) { 997 // if drop is in the team menu, bail 998 if (fBarMenuBar->CountItems() >= 2) { 999 uint32 buttons; 1000 BPoint location; 1001 GetMouse(&location, &buttons); 1002 if (fBarMenuBar->ItemAt(1)->Frame().Contains(location)) 1003 return; 1004 } 1005 } 1006 1007 if (messagewithdestination) { 1008 entry_ref ref; 1009 if (messagewithdestination->FindRef("refs", &ref) == B_OK) { 1010 BEntry entry(&ref, true); 1011 if (entry.IsDirectory()) { 1012 // if the ref received (should only be 1) is a directory 1013 // then add the drag refs to the directory 1014 AddRefsToBeMenu(DragMessage(), &ref); 1015 } else 1016 SendDragMessage(NULL, &ref); 1017 } 1018 } else { 1019 // adds drag refs to top level in be menu 1020 AddRefsToBeMenu(DragMessage(), NULL); 1021 } 1022 1023 // clean up drag message and types list 1024 DragStop(true); 1025 } 1026 1027 1028 // #pragma mark - Add-ons 1029 1030 1031 // shelf is ignored for now, 1032 // it exists in anticipation of having other 'shelves' for 1033 // storing items 1034 1035 status_t 1036 TBarView::ItemInfo(int32 id, const char** name, DeskbarShelf* shelf) 1037 { 1038 *shelf = B_DESKBAR_TRAY; 1039 return fReplicantTray->ItemInfo(id, name); 1040 } 1041 1042 1043 status_t 1044 TBarView::ItemInfo(const char* name, int32* id, DeskbarShelf* shelf) 1045 { 1046 *shelf = B_DESKBAR_TRAY; 1047 return fReplicantTray->ItemInfo(name, id); 1048 } 1049 1050 1051 bool 1052 TBarView::ItemExists(int32 id, DeskbarShelf) 1053 { 1054 return fReplicantTray->IconExists(id); 1055 } 1056 1057 1058 bool 1059 TBarView::ItemExists(const char* name, DeskbarShelf) 1060 { 1061 return fReplicantTray->IconExists(name); 1062 } 1063 1064 1065 int32 1066 TBarView::CountItems(DeskbarShelf) 1067 { 1068 return fReplicantTray->IconCount(); 1069 } 1070 1071 1072 status_t 1073 TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id) 1074 { 1075 return fReplicantTray->AddIcon(item, id); 1076 } 1077 1078 1079 status_t 1080 TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id) 1081 { 1082 return fReplicantTray->LoadAddOn(entry, id); 1083 } 1084 1085 1086 void 1087 TBarView::RemoveItem(int32 id) 1088 { 1089 fReplicantTray->RemoveIcon(id); 1090 } 1091 1092 1093 void 1094 TBarView::RemoveItem(const char* name, DeskbarShelf) 1095 { 1096 fReplicantTray->RemoveIcon(name); 1097 } 1098 1099 1100 BRect 1101 TBarView::OffsetIconFrame(BRect rect) const 1102 { 1103 BRect frame(Frame()); 1104 frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left 1105 + rect.left; 1106 frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top 1107 + rect.top; 1108 1109 frame.right = frame.left + rect.Width(); 1110 frame.bottom = frame.top + rect.Height(); 1111 1112 return frame; 1113 } 1114 1115 1116 BRect 1117 TBarView::IconFrame(int32 id) const 1118 { 1119 return OffsetIconFrame(fReplicantTray->IconFrame(id)); 1120 } 1121 1122 1123 BRect 1124 TBarView::IconFrame(const char* name) const 1125 { 1126 return OffsetIconFrame(fReplicantTray->IconFrame(name)); 1127 } 1128 1129