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