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 <Directory.h> 43 #include <FindDirectory.h> 44 #include <Path.h> 45 #include <Debug.h> 46 #include <File.h> 47 #include <Locale.h> 48 #include <MenuItem.h> 49 #include <MessageFilter.h> 50 #include <Screen.h> 51 52 #include "BarApp.h" 53 #include "BarMenuBar.h" 54 #include "BarView.h" 55 #include "BeMenu.h" 56 #include "PublicCommands.h" 57 #include "StatusView.h" 58 #include "tracker_private.h" 59 60 #include <MessagePrivate.h> 61 62 63 #undef B_TRANSLATE_CONTEXT 64 #define B_TRANSLATE_CONTEXT "MainWindow" 65 66 67 // This is a very ugly hack to be able to call the private 68 // BMenuBar::StartMenuBar() method from the TBarWindow::ShowBeMenu() method. 69 // Don't do this at home -- but why the hell is this method private? 70 #if __MWERKS__ 71 #define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarFlbbP5BRect 72 #elif __GNUC__ <= 2 73 #define BMenuBar_StartMenuBar_Hack StartMenuBar__8BMenuBarlbT2P5BRect 74 #elif __GNUC__ > 2 75 #define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarElbbP5BRect 76 #else 77 # error "You may want to port this ugly hack to your compiler ABI" 78 #endif 79 extern "C" void 80 BMenuBar_StartMenuBar_Hack(BMenuBar*, int32, bool, bool, BRect*); 81 82 83 TBeMenu* TBarWindow::sBeMenu = NULL; 84 85 86 TBarWindow::TBarWindow() 87 : 88 BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f), 89 B_TRANSLATE_SYSTEM_NAME("Deskbar"), B_BORDERED_WINDOW, 90 B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE 91 | B_NOT_MINIMIZABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE 92 | B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS, 93 B_ALL_WORKSPACES) 94 { 95 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 96 if (settings->alwaysOnTop) 97 SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 98 fBarView = new TBarView(Bounds(), settings->vertical, settings->left, 99 settings->top, settings->ampmMode, settings->state, settings->width, 100 settings->showTime); 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::DispatchMessage(BMessage* message, BHandler* handler) 110 { 111 // Activate the window when you click on it (ie. on the tray area, 112 // the menu part will do this automatically) 113 if (message->what == B_MOUSE_DOWN) { 114 if (!((TBarApp*)be_app)->Settings()->autoRaise) 115 Activate(true); 116 117 if (_IsFocusMessage(message) 118 && (modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY 119 | B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) { 120 // The window key was pressed - enter dragging code 121 fBarView->DragRegion()->MouseDown( 122 fBarView->DragRegion()->DragRegion().LeftTop()); 123 return; 124 } 125 } 126 127 BWindow::DispatchMessage(message, handler); 128 } 129 130 131 void 132 TBarWindow::MenusBeginning() 133 { 134 BPath path; 135 entry_ref ref; 136 137 find_directory (B_USER_DESKBAR_DIRECTORY, &path); 138 get_ref_for_path(path.Path(), &ref); 139 140 BEntry entry(&ref, true); 141 if (entry.InitCheck() == B_OK && entry.IsDirectory()) { 142 // need the entry_ref to the actual item 143 entry.GetRef(&ref); 144 // set the nav directory to the be folder 145 sBeMenu->SetNavDir(&ref); 146 } else if (!entry.Exists()) { 147 // the Be folder does not exist 148 // create one now 149 BDirectory dir; 150 if (entry.GetParent(&dir) == B_OK) { 151 BDirectory bedir; 152 dir.CreateDirectory("be", &bedir); 153 if (bedir.GetEntry(&entry) == B_OK 154 && entry.GetRef(&ref) == B_OK) 155 sBeMenu->SetNavDir(&ref); 156 } 157 } else { 158 // this really should never happen 159 TRESPASS(); 160 return; 161 } 162 163 sBeMenu->NeedsToRebuild(); 164 sBeMenu->ResetTargets(); 165 166 fBarView->SetEventMask(0); 167 // This works around a BeOS bug - the menu is quit with every 168 // B_MOUSE_DOWN the window receives... 169 170 BWindow::MenusBeginning(); 171 } 172 173 174 void 175 TBarWindow::MenusEnded() 176 { 177 BWindow::MenusEnded(); 178 179 if (sBeMenu->LockLooper()) { 180 // TODO: is this ok? 181 sBeMenu->RemoveItems(0, sBeMenu->CountItems(), true); 182 sBeMenu->UnlockLooper(); 183 } 184 185 fBarView->UpdateAutoRaise(); 186 } 187 188 189 void 190 TBarWindow::MessageReceived(BMessage* message) 191 { 192 switch (message->what) { 193 case kFindButton: 194 { 195 BMessenger tracker(kTrackerSignature); 196 tracker.SendMessage(message); 197 break; 198 } 199 200 case 'gloc': 201 GetLocation(message); 202 break; 203 204 case 'sloc': 205 SetLocation(message); 206 break; 207 208 case 'gexp': 209 IsExpanded(message); 210 break; 211 212 case 'sexp': 213 Expand(message); 214 break; 215 216 case 'info': 217 ItemInfo(message); 218 break; 219 220 case 'exst': 221 ItemExists(message); 222 break; 223 224 case 'cwnt': 225 CountItems(message); 226 break; 227 228 case 'adon': 229 case 'icon': 230 AddItem(message); 231 break; 232 233 case 'remv': 234 RemoveItem(message); 235 break; 236 237 case 'iloc': 238 GetIconFrame(message); 239 break; 240 241 default: 242 BWindow::MessageReceived(message); 243 break; 244 } 245 } 246 247 248 void 249 TBarWindow::Minimize(bool minimize) 250 { 251 // Don't allow the Deskbar to be minimized 252 if (!minimize) 253 BWindow::Minimize(false); 254 } 255 256 257 void 258 TBarWindow::SaveSettings() 259 { 260 fBarView->SaveSettings(); 261 } 262 263 264 bool 265 TBarWindow::QuitRequested() 266 { 267 be_app->PostMessage(B_QUIT_REQUESTED); 268 269 return BWindow::QuitRequested(); 270 } 271 272 273 void 274 TBarWindow::WorkspaceActivated(int32 workspace, bool active) 275 { 276 BWindow::WorkspaceActivated(workspace, active); 277 278 if (active && !(fBarView->Expando() && fBarView->Vertical())) 279 fBarView->UpdatePlacement(); 280 else { 281 BRect screenFrame = (BScreen(fBarView->Window())).Frame(); 282 fBarView->SizeWindow(screenFrame); 283 fBarView->PositionWindow(screenFrame); 284 fBarView->Invalidate(); 285 } 286 } 287 288 289 void 290 TBarWindow::ScreenChanged(BRect size, color_space depth) 291 { 292 BWindow::ScreenChanged(size, depth); 293 294 fBarView->UpdatePlacement(); 295 } 296 297 298 void 299 TBarWindow::SetBeMenu(TBeMenu* menu) 300 { 301 sBeMenu = menu; 302 } 303 304 305 TBeMenu* 306 TBarWindow::BeMenu() 307 { 308 return sBeMenu; 309 } 310 311 312 void 313 TBarWindow::ShowBeMenu() 314 { 315 BMenuBar* menuBar = fBarView->BarMenuBar(); 316 if (menuBar == NULL) 317 menuBar = KeyMenuBar(); 318 319 if (menuBar == NULL) 320 return; 321 322 BMenuBar_StartMenuBar_Hack(menuBar, 0, true, true, NULL); 323 } 324 325 326 void 327 TBarWindow::ShowTeamMenu() 328 { 329 int32 index = 0; 330 if (fBarView->BarMenuBar() == NULL) 331 index = 2; 332 333 if (KeyMenuBar() == NULL) 334 return; 335 336 BMenuBar_StartMenuBar_Hack(KeyMenuBar(), index, true, true, NULL); 337 } 338 339 340 // determines the actual location of the window 341 342 deskbar_location 343 TBarWindow::DeskbarLocation() const 344 { 345 bool left = fBarView->Left(); 346 bool top = fBarView->Top(); 347 348 if (fBarView->AcrossTop()) 349 return B_DESKBAR_TOP; 350 351 if (fBarView->AcrossBottom()) 352 return B_DESKBAR_BOTTOM; 353 354 if (left && top) 355 return B_DESKBAR_LEFT_TOP; 356 357 if (!left && top) 358 return B_DESKBAR_RIGHT_TOP; 359 360 if (left && !top) 361 return B_DESKBAR_LEFT_BOTTOM; 362 363 return B_DESKBAR_RIGHT_BOTTOM; 364 } 365 366 367 void 368 TBarWindow::GetLocation(BMessage* message) 369 { 370 BMessage reply('rply'); 371 reply.AddInt32("location", (int32)DeskbarLocation()); 372 reply.AddBool("expanded", fBarView->Expando()); 373 374 message->SendReply(&reply); 375 } 376 377 378 void 379 TBarWindow::SetDeskbarLocation(deskbar_location location, bool newExpandState) 380 { 381 // left top and right top are the only two that 382 // currently pay attention to expand, ignore for all others 383 384 bool left = false, top = true, vertical, expand; 385 386 switch (location) { 387 case B_DESKBAR_TOP: 388 left = true; 389 top = true; 390 vertical = false; 391 expand = true; 392 break; 393 394 case B_DESKBAR_BOTTOM: 395 left = true; 396 top = false; 397 vertical = false; 398 expand = true; 399 break; 400 401 case B_DESKBAR_LEFT_TOP: 402 left = true; 403 top = true; 404 vertical = true; 405 expand = newExpandState; 406 break; 407 408 case B_DESKBAR_RIGHT_TOP: 409 left = false; 410 top = true; 411 vertical = true; 412 expand = newExpandState; 413 break; 414 415 case B_DESKBAR_LEFT_BOTTOM: 416 left = true; 417 top = false; 418 vertical = true; 419 expand = false; 420 break; 421 422 case B_DESKBAR_RIGHT_BOTTOM: 423 left = false; 424 top = false; 425 vertical = true; 426 expand = false; 427 break; 428 429 default: 430 left = true; 431 top = true; 432 vertical = false; 433 expand = true; 434 break; 435 } 436 437 fBarView->ChangeState(expand, vertical, left, top); 438 } 439 440 441 void 442 TBarWindow::SetLocation(BMessage* message) 443 { 444 deskbar_location location; 445 bool expand; 446 if (message->FindInt32("location", (int32*)&location) == B_OK 447 && message->FindBool("expand", &expand) == B_OK) 448 SetDeskbarLocation(location, expand); 449 } 450 451 452 void 453 TBarWindow::IsExpanded(BMessage* message) 454 { 455 BMessage reply('rply'); 456 reply.AddBool("expanded", fBarView->Expando()); 457 message->SendReply(&reply); 458 } 459 460 461 void 462 TBarWindow::Expand(BMessage* message) 463 { 464 bool expand; 465 if (message->FindBool("expand", &expand) == B_OK) { 466 bool vertical = fBarView->Vertical(); 467 bool left = fBarView->Left(); 468 bool top = fBarView->Top(); 469 fBarView->ChangeState(expand, vertical, left, top); 470 } 471 } 472 473 474 void 475 TBarWindow::ItemInfo(BMessage* message) 476 { 477 BMessage replyMsg; 478 const char* name; 479 int32 id; 480 DeskbarShelf shelf; 481 if (message->FindInt32("id", &id) == B_OK) { 482 if (fBarView->ItemInfo(id, &name, &shelf) == B_OK) { 483 replyMsg.AddString("name", name); 484 #if SHELF_AWARE 485 replyMsg.AddInt32("shelf", (int32)shelf); 486 #endif 487 } 488 } else if (message->FindString("name", &name) == B_OK) { 489 if (fBarView->ItemInfo(name, &id, &shelf) == B_OK) { 490 replyMsg.AddInt32("id", id); 491 #if SHELF_AWARE 492 replyMsg.AddInt32("shelf", (int32)shelf); 493 #endif 494 } 495 } 496 497 message->SendReply(&replyMsg); 498 } 499 500 501 void 502 TBarWindow::ItemExists(BMessage* message) 503 { 504 BMessage replyMsg; 505 const char* name; 506 int32 id; 507 DeskbarShelf shelf; 508 509 #if SHELF_AWARE 510 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK) 511 #endif 512 shelf = B_DESKBAR_TRAY; 513 514 bool exists = false; 515 if (message->FindInt32("id", &id) == B_OK) 516 exists = fBarView->ItemExists(id, shelf); 517 else if (message->FindString("name", &name) == B_OK) 518 exists = fBarView->ItemExists(name, shelf); 519 520 replyMsg.AddBool("exists", exists); 521 message->SendReply(&replyMsg); 522 } 523 524 525 void 526 TBarWindow::CountItems(BMessage* message) 527 { 528 DeskbarShelf shelf; 529 530 #if SHELF_AWARE 531 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK) 532 #endif 533 shelf = B_DESKBAR_TRAY; 534 535 BMessage reply('rply'); 536 reply.AddInt32("count", fBarView->CountItems(shelf)); 537 message->SendReply(&reply); 538 } 539 540 541 void 542 TBarWindow::AddItem(BMessage* message) 543 { 544 DeskbarShelf shelf; 545 entry_ref ref; 546 int32 id = 999; 547 BMessage reply; 548 status_t err = B_ERROR; 549 550 BMessage archivedView; 551 if (message->FindMessage("view", &archivedView) == B_OK) { 552 #if SHELF_AWARE 553 if (message->FindInt32("shelf", (int32*)&shelf) != B_OK) 554 #endif 555 shelf = B_DESKBAR_TRAY; 556 557 BMessage* archive = new BMessage(archivedView); 558 err = fBarView->AddItem(archive, shelf, &id); 559 if (err < B_OK) 560 delete archive; 561 } else if (message->FindRef("addon", &ref) == B_OK) { 562 // exposing the name of the view here is not so great 563 TReplicantTray* tray 564 = dynamic_cast<TReplicantTray*>(FindView("Status")); 565 if (tray) { 566 // Force this into the deskbar even if the security code is wrong 567 // This is OK because the user specifically asked for this replicant 568 BEntry entry(&ref); 569 err = tray->LoadAddOn(&entry, &id, true); 570 } 571 } 572 573 if (err == B_OK) 574 reply.AddInt32("id", id); 575 else 576 reply.AddInt32("error", err); 577 578 message->SendReply(&reply); 579 } 580 581 582 void 583 TBarWindow::RemoveItem(BMessage* message) 584 { 585 int32 id; 586 const char* name; 587 588 // ids ought to be unique across all shelves, assuming, of course, 589 // that sometime in the future there may be more than one 590 #if SHELF_AWARE 591 if (message->FindInt32("shelf", (int32*)&shelf) == B_OK) { 592 if (message->FindString("name", &name) == B_OK) 593 fBarView->RemoveItem(name, shelf); 594 } else { 595 #endif 596 if (message->FindInt32("id", &id) == B_OK) { 597 fBarView->RemoveItem(id); 598 // remove the following two lines if and when the 599 // shelf option returns 600 } else if (message->FindString("name", &name) == B_OK) 601 fBarView->RemoveItem(name, B_DESKBAR_TRAY); 602 603 #if SHELF_AWARE 604 } 605 #endif 606 } 607 608 609 void 610 TBarWindow::GetIconFrame(BMessage* message) 611 { 612 BRect frame(0, 0, 0, 0); 613 614 const char* name; 615 int32 id; 616 if (message->FindInt32("id", &id) == B_OK) 617 frame = fBarView->IconFrame(id); 618 else if (message->FindString("name", &name) == B_OK) 619 frame = fBarView->IconFrame(name); 620 621 BMessage reply('rply'); 622 reply.AddRect("frame", frame); 623 message->SendReply(&reply); 624 } 625 626 627 bool 628 TBarWindow::_IsFocusMessage(BMessage* message) 629 { 630 BMessage::Private messagePrivate(message); 631 if (!messagePrivate.UsePreferredTarget()) 632 return false; 633 634 bool feedFocus; 635 if (message->HasInt32("_token") 636 && (message->FindBool("_feed_focus", &feedFocus) != B_OK || !feedFocus)) 637 return false; 638 639 return true; 640 } 641 642