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