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