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 <Directory.h> 43 #include <FindDirectory.h> 44 #include <Path.h> 45 #include <Debug.h> 46 #include <File.h> 47 #include <Locale.h> 48 #include <MenuItem.h> 49 #include <MessageFilter.h> 50 #include <Screen.h> 51 52 #include "BarApp.h" 53 #include "BarMenuBar.h" 54 #include "BarView.h" 55 #include "BeMenu.h" 56 #include "PublicCommands.h" 57 #include "StatusView.h" 58 #include "tracker_private.h" 59 60 #include <MessagePrivate.h> 61 62 63 #undef B_TRANSLATE_CONTEXT 64 #define B_TRANSLATE_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 #define BMenuBar_StartMenuBar_Hack _ZN8BMenuBar12StartMenuBarElbbP5BRect 76 #else 77 # error "You may want to port this ugly hack to your compiler ABI" 78 #endif 79 extern "C" void 80 BMenuBar_StartMenuBar_Hack(BMenuBar*, int32, bool, bool, BRect*); 81 82 83 TBeMenu* TBarWindow::sBeMenu = NULL; 84 85 86 TBarWindow::TBarWindow() 87 : 88 BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f), 89 B_TRANSLATE_SYSTEM_NAME("Deskbar"), B_BORDERED_WINDOW, 90 B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE 91 | B_NOT_MINIMIZABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE 92 | B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS, 93 B_ALL_WORKSPACES) 94 { 95 desk_settings* settings = ((TBarApp*)be_app)->Settings(); 96 if (settings->alwaysOnTop) 97 SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 98 fBarView = new TBarView(Bounds(), settings->vertical, settings->left, 99 settings->top, settings->ampmMode, settings->state, settings->width, 100 settings->showTime); 101 AddChild(fBarView); 102 103 RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY); 104 AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton)); 105 } 106 107 108 void 109 TBarWindow::MenusBeginning() 110 { 111 BPath path; 112 entry_ref ref; 113 114 find_directory (B_USER_DESKBAR_DIRECTORY, &path); 115 get_ref_for_path(path.Path(), &ref); 116 117 BEntry entry(&ref, true); 118 if (entry.InitCheck() == B_OK && entry.IsDirectory()) { 119 // need the entry_ref to the actual item 120 entry.GetRef(&ref); 121 // set the nav directory to the be folder 122 sBeMenu->SetNavDir(&ref); 123 } else if (!entry.Exists()) { 124 // the Be folder does not exist 125 // create one now 126 BDirectory dir; 127 if (entry.GetParent(&dir) == B_OK) { 128 BDirectory bedir; 129 dir.CreateDirectory("be", &bedir); 130 if (bedir.GetEntry(&entry) == B_OK 131 && entry.GetRef(&ref) == B_OK) 132 sBeMenu->SetNavDir(&ref); 133 } 134 } else { 135 // this really should never happen 136 TRESPASS(); 137 return; 138 } 139 140 sBeMenu->NeedsToRebuild(); 141 sBeMenu->ResetTargets(); 142 143 fBarView->SetEventMask(0); 144 // This works around a BeOS bug - the menu is quit with every 145 // B_MOUSE_DOWN the window receives... 146 147 BWindow::MenusBeginning(); 148 } 149 150 151 void 152 TBarWindow::MenusEnded() 153 { 154 BWindow::MenusEnded(); 155 156 if (sBeMenu->LockLooper()) { 157 // TODO: is this ok? 158 sBeMenu->RemoveItems(0, sBeMenu->CountItems(), true); 159 sBeMenu->UnlockLooper(); 160 } 161 162 fBarView->UpdateEventMask(); 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->Expando() && 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::SetBeMenu(TBeMenu* menu) 277 { 278 sBeMenu = menu; 279 } 280 281 282 TBeMenu* 283 TBarWindow::BeMenu() 284 { 285 return sBeMenu; 286 } 287 288 289 void 290 TBarWindow::ShowBeMenu() 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->Expando()); 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->Expando()); 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::_IsFocusMessage(BMessage* message) 599 { 600 BMessage::Private messagePrivate(message); 601 if (!messagePrivate.UsePreferredTarget()) 602 return false; 603 604 bool feedFocus; 605 if (message->HasInt32("_token") 606 && (message->FindBool("_feed_focus", &feedFocus) != B_OK || !feedFocus)) 607 return false; 608 609 return true; 610 } 611 612