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