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 extern "C" void StartMenuBar__8BMenuBarFlbbP5BRect(BMenuBar *,int32,bool,bool,BRect *); 61 #elif __GCC__ <= 2 62 extern "C" void StartMenuBar__8BMenuBarlbT2P5BRect(BMenuBar *,int32,bool,bool,BRect *); 63 #else 64 # error "You may want to port this ugly hack to your compiler ABI" 65 #endif 66 67 68 TBeMenu *TBarWindow::sBeMenu = NULL; 69 70 71 TBarWindow::TBarWindow() 72 : BWindow(BRect(-1000.0f, -1000.0f, -1000.0f, -1000.0f), "Deskbar", 73 B_BORDERED_WINDOW, 74 B_WILL_ACCEPT_FIRST_CLICK | B_NOT_ZOOMABLE | B_NOT_CLOSABLE 75 | B_NOT_MOVABLE | B_AVOID_FRONT | B_ASYNCHRONOUS_CONTROLS, 76 B_ALL_WORKSPACES) 77 { 78 desk_settings *settings = ((TBarApp *)be_app)->Settings(); 79 if (settings->alwaysOnTop) 80 SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 81 fBarView = new TBarView(Bounds(), settings->vertical,settings->left, settings->top, 82 settings->ampmMode, settings->state, settings->width, settings->showTime); 83 AddChild(fBarView); 84 85 AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton)); 86 #if SA_CLOCK 87 AddShortcut('H', B_COMMAND_KEY, new BMessage('clok')); 88 #endif 89 } 90 91 92 void 93 TBarWindow::DispatchMessage(BMessage *message, BHandler *handler) 94 { 95 // ToDo: check if the two following lines are doing anything... 96 if (message->what == B_MOUSE_DOWN) 97 Activate(true); 98 99 BWindow::DispatchMessage(message, handler); 100 } 101 102 103 void 104 TBarWindow::MenusBeginning() 105 { 106 BPath path; 107 entry_ref ref; 108 109 find_directory (B_USER_DESKBAR_DIRECTORY, &path); 110 get_ref_for_path(path.Path(), &ref); 111 112 BEntry entry(&ref, true); 113 if (entry.InitCheck() == B_OK && entry.IsDirectory()) { 114 // need the entry_ref to the actual item 115 entry.GetRef(&ref); 116 // set the nav directory to the be folder 117 sBeMenu->SetNavDir(&ref); 118 } else if (!entry.Exists()) { 119 // the Be folder does not exist 120 // create one now 121 BDirectory dir; 122 if (entry.GetParent(&dir) == B_OK) { 123 BDirectory bedir; 124 dir.CreateDirectory("be", &bedir); 125 if (bedir.GetEntry(&entry) == B_OK 126 && entry.GetRef(&ref) == B_OK) 127 sBeMenu->SetNavDir(&ref); 128 } 129 } else { 130 // this really should never happen 131 TRESPASS(); 132 return; 133 } 134 135 sBeMenu->NeedsToRebuild(); 136 sBeMenu->ResetTargets(); 137 138 BWindow::MenusBeginning(); 139 } 140 141 142 void 143 TBarWindow::MenusEnded() 144 { 145 BWindow::MenusEnded(); 146 147 BMenuItem *item = NULL; 148 while ((item = sBeMenu->RemoveItem((int32)0)) != NULL) 149 delete item; 150 } 151 152 153 void 154 TBarWindow::MessageReceived(BMessage *message) 155 { 156 switch (message->what) { 157 case kFindButton: 158 { 159 BMessenger tracker(kTrackerSignature); 160 tracker.SendMessage(message); 161 break; 162 } 163 164 #if SA_CLOCK 165 case 'clok': 166 fBarView->ToggleClock(); 167 break; 168 #endif 169 170 case 'gloc': 171 GetLocation(message); 172 break; 173 174 case 'sloc': 175 SetLocation(message); 176 break; 177 178 case 'gexp': 179 IsExpanded(message); 180 break; 181 182 case 'sexp': 183 Expand(message); 184 break; 185 186 case 'info': 187 ItemInfo(message); 188 break; 189 190 case 'exst': 191 ItemExists(message); 192 break; 193 194 case 'cwnt': 195 CountItems(message); 196 break; 197 198 case 'adon': 199 case 'icon': 200 AddItem(message); 201 break; 202 203 case 'remv': 204 RemoveItem(message); 205 break; 206 207 case 'iloc': 208 GetIconFrame(message); 209 break; 210 211 default: 212 BWindow::MessageReceived(message); 213 break; 214 } 215 } 216 217 218 void 219 TBarWindow::SaveSettings() 220 { 221 fBarView->SaveSettings(); 222 } 223 224 225 bool 226 TBarWindow::QuitRequested() 227 { 228 be_app->PostMessage(B_QUIT_REQUESTED); 229 230 return BWindow::QuitRequested(); 231 } 232 233 234 void 235 TBarWindow::WorkspaceActivated(int32 workspace, bool active) 236 { 237 BWindow::WorkspaceActivated(workspace, active); 238 239 if (active && !(fBarView->Expando() && fBarView->Vertical())) 240 fBarView->UpdatePlacement(); 241 else { 242 BRect screenFrame = (BScreen(fBarView->Window())).Frame(); 243 fBarView->SizeWindow(screenFrame); 244 fBarView->PositionWindow(screenFrame); 245 fBarView->Invalidate(); 246 } 247 } 248 249 250 void 251 TBarWindow::ScreenChanged(BRect size, color_space depth) 252 { 253 BWindow::ScreenChanged(size, depth); 254 255 fBarView->UpdatePlacement(); 256 } 257 258 259 void 260 TBarWindow::SetBeMenu(TBeMenu *menu) 261 { 262 sBeMenu = menu; 263 } 264 265 266 TBeMenu * 267 TBarWindow::BeMenu() 268 { 269 return sBeMenu; 270 } 271 272 273 void 274 TBarWindow::ShowBeMenu() 275 { 276 BMenuBar *menuBar = fBarView->BarMenuBar(); 277 if (menuBar == NULL) 278 menuBar = KeyMenuBar(); 279 280 if (menuBar == NULL) 281 return; 282 283 #if __MWERKS__ 284 StartMenuBar__8BMenuBarFlbbP5BRect(menuBar,0,true,true,NULL); 285 #elif __GCC__ <= 2 286 StartMenuBar__8BMenuBarlbT2P5BRect(menuBar,0,true,true,NULL); 287 #endif 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 #if __MWERKS__ 302 StartMenuBar__8BMenuBarFlbbP5BRect(KeyMenuBar(),index,true,true,NULL); 303 #elif __GCC__ <= 2 304 StartMenuBar__8BMenuBarlbT2P5BRect(KeyMenuBar(),index,true,true,NULL); 305 #endif 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 err = fBarView->AddItem(new BMessage(archivedView), shelf, &id); 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