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