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