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