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