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