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