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