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