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