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