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