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