1 /* 2 * Copyright 2002-2008, Haiku, Inc. 3 * Copyright 2002, François Revol, revol@free.fr. 4 * This file is distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * François Revol, revol@free.fr 8 * Axel Dörfler, axeld@pinc-software.de 9 * Oliver "Madison" Kohl, 10 * Matt Madia 11 */ 12 13 14 #include <Alert.h> 15 #include <Application.h> 16 #include <Dragger.h> 17 #include <Entry.h> 18 #include <File.h> 19 #include <FindDirectory.h> 20 #include <MenuItem.h> 21 #include <Path.h> 22 #include <PopUpMenu.h> 23 #include <Roster.h> 24 #include <Screen.h> 25 #include <TextView.h> 26 #include <Window.h> 27 28 #include <ctype.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 33 #include <ViewPrivate.h> 34 #include <WindowPrivate.h> 35 36 37 static const char* kSignature = "application/x-vnd.Be-WORK"; 38 static const char* kOldSettingFile = "Workspace_data"; 39 static const char* kSettingsFile = "Workspaces_settings"; 40 41 static const uint32 kMsgChangeCount = 'chWC'; 42 static const uint32 kMsgToggleTitle = 'tgTt'; 43 static const uint32 kMsgToggleBorder = 'tgBd'; 44 static const uint32 kMsgToggleAutoRaise = 'tgAR'; 45 static const uint32 kMsgToggleAlwaysOnTop = 'tgAT'; 46 47 static const float kScreenBorderOffset = 10.0; 48 49 50 class WorkspacesSettings { 51 public: 52 WorkspacesSettings(); 53 virtual ~WorkspacesSettings(); 54 55 BRect WindowFrame() const { return fWindowFrame; } 56 BRect ScreenFrame() const { return fScreenFrame; } 57 58 bool AutoRaising() const { return fAutoRaising; } 59 bool AlwaysOnTop() const { return fAlwaysOnTop; } 60 bool HasTitle() const { return fHasTitle; } 61 bool HasBorder() const { return fHasBorder; } 62 63 void UpdateFramesForScreen(BRect screenFrame); 64 void UpdateScreenFrame(); 65 66 void SetWindowFrame(BRect); 67 void SetAutoRaising(bool enable) { fAutoRaising = enable; } 68 void SetAlwaysOnTop(bool enable) { fAlwaysOnTop = enable; } 69 void SetHasTitle(bool enable) { fHasTitle = enable; } 70 void SetHasBorder(bool enable) { fHasBorder = enable; } 71 72 private: 73 status_t _Open(BFile& file, int mode); 74 75 BRect fWindowFrame; 76 BRect fScreenFrame; 77 bool fAutoRaising; 78 bool fAlwaysOnTop; 79 bool fHasTitle; 80 bool fHasBorder; 81 }; 82 83 class WorkspacesView : public BView { 84 public: 85 WorkspacesView(BRect frame); 86 WorkspacesView(BMessage* archive); 87 ~WorkspacesView(); 88 89 static WorkspacesView* Instantiate(BMessage* archive); 90 virtual status_t Archive(BMessage* archive, bool deep = true) const; 91 92 virtual void AttachedToWindow(); 93 virtual void DetachedFromWindow(); 94 virtual void FrameMoved(BPoint newPosition); 95 virtual void FrameResized(float newWidth, float newHeight); 96 virtual void MessageReceived(BMessage* message); 97 virtual void MouseMoved(BPoint where, uint32 transit, 98 const BMessage* dragMessage); 99 virtual void MouseDown(BPoint where); 100 101 private: 102 void _AboutRequested(); 103 104 void _UpdateParentClipping(); 105 void _ExcludeFromParentClipping(); 106 void _CleanupParentClipping(); 107 108 BView* fParentWhichDrawsOnChildren; 109 BRect fCurrentFrame; 110 }; 111 112 class WorkspacesWindow : public BWindow { 113 public: 114 WorkspacesWindow(WorkspacesSettings *settings); 115 virtual ~WorkspacesWindow(); 116 117 virtual void ScreenChanged(BRect frame, color_space mode); 118 virtual void FrameMoved(BPoint origin); 119 virtual void FrameResized(float width, float height); 120 virtual void Zoom(BPoint origin, float width, float height); 121 122 virtual void MessageReceived(BMessage *msg); 123 virtual bool QuitRequested(); 124 125 void SetAutoRaise(bool enable); 126 bool IsAutoRaising() const { return fAutoRaising; } 127 128 private: 129 WorkspacesSettings *fSettings; 130 bool fAutoRaising; 131 }; 132 133 class WorkspacesApp : public BApplication { 134 public: 135 WorkspacesApp(); 136 virtual ~WorkspacesApp(); 137 138 virtual void AboutRequested(); 139 virtual void ArgvReceived(int32 argc, char **argv); 140 virtual void ReadyToRun(); 141 142 void Usage(const char *programName); 143 144 private: 145 WorkspacesWindow* fWindow; 146 }; 147 148 149 WorkspacesSettings::WorkspacesSettings() 150 : 151 fAutoRaising(false), 152 fAlwaysOnTop(false), 153 fHasTitle(true), 154 fHasBorder(true) 155 { 156 UpdateScreenFrame(); 157 158 bool loaded = false; 159 BScreen screen; 160 161 BFile file; 162 if (_Open(file, B_READ_ONLY) == B_OK) { 163 BMessage settings; 164 if (settings.Unflatten(&file) == B_OK) { 165 if (settings.FindRect("window", &fWindowFrame) == B_OK 166 && settings.FindRect("screen", &fScreenFrame) == B_OK) 167 loaded = true; 168 169 settings.FindBool("auto-raise", &fAutoRaising); 170 settings.FindBool("always on top", &fAlwaysOnTop); 171 172 if (settings.FindBool("has title", &fHasTitle) != B_OK) 173 fHasTitle = true; 174 if (settings.FindBool("has border", &fHasBorder) != B_OK) 175 fHasBorder = true; 176 } 177 } else { 178 // try reading BeOS compatible settings 179 BPath path; 180 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 181 path.Append(kOldSettingFile); 182 BFile file(path.Path(), B_READ_ONLY); 183 if (file.InitCheck() == B_OK 184 && file.Read(&fWindowFrame, sizeof(BRect)) == sizeof(BRect)) { 185 // we now also store the frame of the screen to know 186 // in which context the window frame has been chosen 187 BRect frame; 188 if (file.Read(&frame, sizeof(BRect)) == sizeof(BRect)) 189 fScreenFrame = frame; 190 else 191 fScreenFrame = screen.Frame(); 192 193 loaded = true; 194 } 195 } 196 } 197 198 if (loaded) { 199 // if the current screen frame is different from the one 200 // just loaded, we need to alter the window frame accordingly 201 if (fScreenFrame != screen.Frame()) 202 UpdateFramesForScreen(screen.Frame()); 203 } 204 205 if (!loaded 206 || !(screen.Frame().right + 5 >= fWindowFrame.right 207 && screen.Frame().bottom + 5 >= fWindowFrame.bottom 208 && screen.Frame().left - 5 <= fWindowFrame.left 209 && screen.Frame().top - 5 <= fWindowFrame.top)) { 210 // set to some usable defaults 211 fWindowFrame = fScreenFrame; 212 fWindowFrame.OffsetBy(-kScreenBorderOffset, -kScreenBorderOffset); 213 fWindowFrame.left = fWindowFrame.right - 160; 214 fWindowFrame.top = fWindowFrame.bottom - 140; 215 } 216 } 217 218 219 WorkspacesSettings::~WorkspacesSettings() 220 { 221 // write settings file 222 BFile file; 223 if (_Open(file, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) != B_OK) 224 return; 225 226 BMessage settings('wksp'); 227 228 if (settings.AddRect("window", fWindowFrame) == B_OK 229 && settings.AddRect("screen", fScreenFrame) == B_OK 230 && settings.AddBool("auto-raise", fAutoRaising) == B_OK 231 && settings.AddBool("always on top", fAlwaysOnTop) == B_OK 232 && settings.AddBool("has title", fHasTitle) == B_OK 233 && settings.AddBool("has border", fHasBorder) == B_OK) 234 settings.Flatten(&file); 235 } 236 237 238 status_t 239 WorkspacesSettings::_Open(BFile& file, int mode) 240 { 241 BPath path; 242 status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 243 if (status != B_OK) 244 status = find_directory(B_COMMON_SETTINGS_DIRECTORY, &path); 245 if (status != B_OK) 246 return status; 247 248 path.Append(kSettingsFile); 249 250 status = file.SetTo(path.Path(), mode); 251 if (mode == B_READ_ONLY && status == B_ENTRY_NOT_FOUND) { 252 if (find_directory(B_COMMON_SETTINGS_DIRECTORY, &path) == B_OK) { 253 path.Append(kSettingsFile); 254 status = file.SetTo(path.Path(), mode); 255 } 256 } 257 258 return status; 259 } 260 261 262 void 263 WorkspacesSettings::UpdateFramesForScreen(BRect newScreenFrame) 264 { 265 // don't change the position if the screen frame hasn't changed 266 if (newScreenFrame == fScreenFrame) 267 return; 268 269 // adjust horizontal position 270 if (fWindowFrame.right > fScreenFrame.right / 2) { 271 fWindowFrame.OffsetTo(newScreenFrame.right 272 - (fScreenFrame.right - fWindowFrame.left), fWindowFrame.top); 273 } 274 275 // adjust vertical position 276 if (fWindowFrame.bottom > fScreenFrame.bottom / 2) { 277 fWindowFrame.OffsetTo(fWindowFrame.left, 278 newScreenFrame.bottom - (fScreenFrame.bottom - fWindowFrame.top)); 279 } 280 281 fScreenFrame = newScreenFrame; 282 } 283 284 285 void 286 WorkspacesSettings::UpdateScreenFrame() 287 { 288 BScreen screen; 289 fScreenFrame = screen.Frame(); 290 } 291 292 293 void 294 WorkspacesSettings::SetWindowFrame(BRect frame) 295 { 296 fWindowFrame = frame; 297 } 298 299 300 // #pragma mark - 301 302 303 WorkspacesView::WorkspacesView(BRect frame) 304 : 305 BView(frame, "workspaces", B_FOLLOW_ALL, 306 kWorkspacesViewFlag | B_FRAME_EVENTS), 307 fParentWhichDrawsOnChildren(NULL), 308 fCurrentFrame(frame) 309 { 310 frame.OffsetTo(B_ORIGIN); 311 frame.top = frame.bottom - 7; 312 frame.left = frame.right - 7; 313 BDragger* dragger = new BDragger(frame, this, 314 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 315 AddChild(dragger); 316 } 317 318 319 WorkspacesView::WorkspacesView(BMessage* archive) 320 : 321 BView(archive), 322 fParentWhichDrawsOnChildren(NULL), 323 fCurrentFrame(Frame()) 324 { 325 // Just in case we are instantiated from an older archive... 326 SetFlags(Flags() | B_FRAME_EVENTS); 327 // Make sure the auto-raise feature didn't leave any artifacts - this is 328 // not a good idea to keep enabled for a replicant. 329 if (EventMask() != 0) 330 SetEventMask(0); 331 } 332 333 334 WorkspacesView::~WorkspacesView() 335 { 336 } 337 338 339 /*static*/ WorkspacesView* 340 WorkspacesView::Instantiate(BMessage* archive) 341 { 342 if (!validate_instantiation(archive, "WorkspacesView")) 343 return NULL; 344 345 return new WorkspacesView(archive); 346 } 347 348 349 status_t 350 WorkspacesView::Archive(BMessage* archive, bool deep) const 351 { 352 status_t status = BView::Archive(archive, deep); 353 if (status == B_OK) 354 status = archive->AddString("add_on", kSignature); 355 if (status == B_OK) 356 status = archive->AddString("class", "WorkspacesView"); 357 358 return status; 359 } 360 361 362 void 363 WorkspacesView::_AboutRequested() 364 { 365 BAlert *alert = new BAlert("about", "Workspaces\n" 366 "written by François Revol, Axel Dörfler, and Matt Madia.\n\n" 367 "Copyright 2002-2008, Haiku.\n\n" 368 "Send windows behind using the Option key. " 369 "Move windows to front using the Control key.\n", "Ok"); 370 BTextView *view = alert->TextView(); 371 BFont font; 372 373 view->SetStylable(true); 374 375 view->GetFont(&font); 376 font.SetSize(18); 377 font.SetFace(B_BOLD_FACE); 378 view->SetFontAndColor(0, 10, &font); 379 380 alert->Go(); 381 } 382 383 384 void 385 WorkspacesView::AttachedToWindow() 386 { 387 BView* parent = Parent(); 388 if (parent != NULL && (parent->Flags() & B_DRAW_ON_CHILDREN) != 0) { 389 fParentWhichDrawsOnChildren = parent; 390 _ExcludeFromParentClipping(); 391 } 392 } 393 394 395 void 396 WorkspacesView::DetachedFromWindow() 397 { 398 if (fParentWhichDrawsOnChildren != NULL) 399 _CleanupParentClipping(); 400 } 401 402 403 void 404 WorkspacesView::FrameMoved(BPoint newPosition) 405 { 406 _UpdateParentClipping(); 407 } 408 409 410 void 411 WorkspacesView::FrameResized(float newWidth, float newHeight) 412 { 413 _UpdateParentClipping(); 414 } 415 416 417 void 418 WorkspacesView::_UpdateParentClipping() 419 { 420 if (fParentWhichDrawsOnChildren != NULL) { 421 _CleanupParentClipping(); 422 _ExcludeFromParentClipping(); 423 fParentWhichDrawsOnChildren->Invalidate(fCurrentFrame); 424 fCurrentFrame = Frame(); 425 } 426 } 427 428 429 void 430 WorkspacesView::_ExcludeFromParentClipping() 431 { 432 // Prevent the parent view to draw over us. Do so in a way that allows 433 // restoring the parent to the previous state. 434 fParentWhichDrawsOnChildren->PushState(); 435 436 BRegion clipping(fParentWhichDrawsOnChildren->Bounds()); 437 clipping.Exclude(Frame()); 438 fParentWhichDrawsOnChildren->ConstrainClippingRegion(&clipping); 439 } 440 441 442 void 443 WorkspacesView::_CleanupParentClipping() 444 { 445 // Restore the previous parent state. NOTE: This relies on views 446 // being detached in exactly the opposite order as them being 447 // attached. Otherwise we would mess up states if a sibbling view did 448 // the same thing we did in AttachedToWindow()... 449 fParentWhichDrawsOnChildren->PopState(); 450 } 451 452 453 void 454 WorkspacesView::MessageReceived(BMessage* message) 455 { 456 switch (message->what) { 457 case B_ABOUT_REQUESTED: 458 _AboutRequested(); 459 break; 460 461 case kMsgChangeCount: 462 be_roster->Launch("application/x-vnd.Be-SCRN"); 463 break; 464 465 default: 466 BView::MessageReceived(message); 467 break; 468 } 469 } 470 471 472 void 473 WorkspacesView::MouseMoved(BPoint where, uint32 transit, 474 const BMessage* dragMessage) 475 { 476 WorkspacesWindow* window = dynamic_cast<WorkspacesWindow*>(Window()); 477 if (window == NULL || !window->IsAutoRaising()) 478 return; 479 480 // Auto-Raise 481 482 where = ConvertToScreen(where); 483 BScreen screen(window); 484 BRect frame = screen.Frame(); 485 if (where.x == frame.left || where.x == frame.right 486 || where.y == frame.top || where.y == frame.bottom) { 487 // cursor is on screen edge 488 if (window->Frame().Contains(where)) 489 window->Activate(); 490 } 491 } 492 493 494 void 495 WorkspacesView::MouseDown(BPoint where) 496 { 497 // With enabled auto-raise feature, we'll get mouse messages we don't 498 // want to handle here. 499 if (!Bounds().Contains(where)) 500 return; 501 502 int32 buttons = 0; 503 if (Window() != NULL && Window()->CurrentMessage() != NULL) 504 Window()->CurrentMessage()->FindInt32("buttons", &buttons); 505 506 if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0) 507 return; 508 509 // open context menu 510 511 BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 512 menu->SetFont(be_plain_font); 513 514 // TODO: alternatively change the count here directly? 515 BMenuItem* changeItem = new BMenuItem("Change Workspace Count" 516 B_UTF8_ELLIPSIS, new BMessage(kMsgChangeCount)); 517 menu->AddItem(changeItem); 518 519 WorkspacesWindow* window = dynamic_cast<WorkspacesWindow*>(Window()); 520 if (window != NULL) { 521 BMenuItem* item; 522 523 menu->AddSeparatorItem(); 524 menu->AddItem(item = new BMenuItem("No Window Title", 525 new BMessage(kMsgToggleTitle))); 526 if (window->Look() == B_MODAL_WINDOW_LOOK) 527 item->SetMarked(true); 528 menu->AddItem(item = new BMenuItem("No Window Border", 529 new BMessage(kMsgToggleBorder))); 530 if (window->Look() == B_NO_BORDER_WINDOW_LOOK) 531 item->SetMarked(true); 532 533 menu->AddSeparatorItem(); 534 menu->AddItem(item = new BMenuItem("Always On Top", 535 new BMessage(kMsgToggleAlwaysOnTop))); 536 if (window->Feel() == B_FLOATING_ALL_WINDOW_FEEL) 537 item->SetMarked(true); 538 menu->AddItem(item = new BMenuItem("Auto Raise", 539 new BMessage(kMsgToggleAutoRaise))); 540 if (window->IsAutoRaising()) 541 item->SetMarked(true); 542 543 menu->AddSeparatorItem(); 544 menu->AddItem(new BMenuItem("About" B_UTF8_ELLIPSIS, 545 new BMessage(B_ABOUT_REQUESTED))); 546 menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); 547 menu->SetTargetForItems(window); 548 } 549 550 changeItem->SetTarget(this); 551 ConvertToScreen(&where); 552 menu->Go(where, true, true, true); 553 } 554 555 556 // #pragma mark - 557 558 559 WorkspacesWindow::WorkspacesWindow(WorkspacesSettings *settings) 560 : BWindow(settings->WindowFrame(), "Workspaces", B_TITLED_WINDOW_LOOK, 561 B_NORMAL_WINDOW_FEEL, B_AVOID_FRONT | B_WILL_ACCEPT_FIRST_CLICK, 562 B_ALL_WORKSPACES), 563 fSettings(settings), 564 fAutoRaising(false) 565 { 566 AddChild(new WorkspacesView(Bounds())); 567 568 if (!fSettings->HasTitle()) 569 SetLook(B_MODAL_WINDOW_LOOK); 570 else if (!fSettings->HasBorder()) 571 SetLook(B_NO_BORDER_WINDOW_LOOK); 572 573 if (fSettings->AlwaysOnTop()) 574 SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 575 else 576 SetAutoRaise(fSettings->AutoRaising()); 577 } 578 579 580 WorkspacesWindow::~WorkspacesWindow() 581 { 582 delete fSettings; 583 } 584 585 586 void 587 WorkspacesWindow::ScreenChanged(BRect rect, color_space mode) 588 { 589 fSettings->UpdateFramesForScreen(rect); 590 MoveTo(fSettings->WindowFrame().LeftTop()); 591 } 592 593 594 void 595 WorkspacesWindow::FrameMoved(BPoint origin) 596 { 597 fSettings->SetWindowFrame(Frame()); 598 } 599 600 601 void 602 WorkspacesWindow::FrameResized(float width, float height) 603 { 604 fSettings->SetWindowFrame(Frame()); 605 } 606 607 608 void 609 WorkspacesWindow::Zoom(BPoint origin, float width, float height) 610 { 611 BScreen screen; 612 origin = screen.Frame().RightBottom(); 613 origin.x -= kScreenBorderOffset + fSettings->WindowFrame().Width(); 614 origin.y -= kScreenBorderOffset + fSettings->WindowFrame().Height(); 615 616 MoveTo(origin); 617 } 618 619 620 void 621 WorkspacesWindow::MessageReceived(BMessage *message) 622 { 623 switch (message->what) { 624 case B_SIMPLE_DATA: 625 { 626 // Drop from Tracker 627 entry_ref ref; 628 for (int i = 0; (message->FindRef("refs", i, &ref) == B_OK); i++) 629 be_roster->Launch(&ref); 630 break; 631 } 632 633 case B_ABOUT_REQUESTED: 634 PostMessage(message, ChildAt(0)); 635 break; 636 637 case kMsgToggleBorder: 638 { 639 bool enable = false; 640 if (Look() == B_NO_BORDER_WINDOW_LOOK) 641 enable = true; 642 643 if (enable) 644 SetLook(B_TITLED_WINDOW_LOOK); 645 else { 646 SetLook(B_NO_BORDER_WINDOW_LOOK); 647 fSettings->SetHasTitle(true); 648 } 649 650 fSettings->SetHasBorder(enable); 651 break; 652 } 653 654 case kMsgToggleTitle: 655 { 656 bool enable = false; 657 if (Look() == B_MODAL_WINDOW_LOOK) 658 enable = true; 659 660 if (enable) 661 SetLook(B_TITLED_WINDOW_LOOK); 662 else { 663 SetLook(B_MODAL_WINDOW_LOOK); 664 fSettings->SetHasBorder(true); 665 } 666 667 fSettings->SetHasTitle(enable); 668 break; 669 } 670 671 case kMsgToggleAutoRaise: 672 SetAutoRaise(!IsAutoRaising()); 673 SetFeel(B_NORMAL_WINDOW_FEEL); 674 break; 675 676 case kMsgToggleAlwaysOnTop: 677 { 678 bool enable = false; 679 if (Feel() != B_FLOATING_ALL_WINDOW_FEEL) 680 enable = true; 681 682 if (enable) 683 SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 684 else 685 SetFeel(B_NORMAL_WINDOW_FEEL); 686 687 fSettings->SetAlwaysOnTop(enable); 688 break; 689 } 690 691 default: 692 BWindow::MessageReceived(message); 693 break; 694 } 695 } 696 697 698 bool 699 WorkspacesWindow::QuitRequested() 700 { 701 be_app->PostMessage(B_QUIT_REQUESTED); 702 return true; 703 } 704 705 706 void 707 WorkspacesWindow::SetAutoRaise(bool enable) 708 { 709 if (enable == fAutoRaising) 710 return; 711 712 fAutoRaising = enable; 713 fSettings->SetAutoRaising(enable); 714 715 if (enable) 716 ChildAt(0)->SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); 717 else 718 ChildAt(0)->SetEventMask(0); 719 } 720 721 722 // #pragma mark - 723 724 725 WorkspacesApp::WorkspacesApp() 726 : BApplication(kSignature) 727 { 728 fWindow = new WorkspacesWindow(new WorkspacesSettings()); 729 } 730 731 732 WorkspacesApp::~WorkspacesApp() 733 { 734 } 735 736 737 void 738 WorkspacesApp::AboutRequested() 739 { 740 fWindow->PostMessage(B_ABOUT_REQUESTED); 741 } 742 743 744 void 745 WorkspacesApp::Usage(const char *programName) 746 { 747 printf("Usage: %s [options] [workspace]\n" 748 "where \"options\" is one of:\n" 749 " --notitle\t\ttitle bar removed. border and resize kept.\n" 750 " --noborder\t\ttitle, border, and resize removed.\n" 751 " --avoidfocus\t\tprevents the window from being the target of keyboard events.\n" 752 " --alwaysontop\t\tkeeps window on top\n" 753 " --notmovable\t\twindow can't be moved around\n" 754 " --autoraise\t\tauto-raise the workspace window when it's at the screen corner\n" 755 " --help\t\tdisplay this help and exit\n" 756 "and \"workspace\" is the number of the Workspace to which to switch (0-31)\n", 757 programName); 758 759 // quit only if we aren't running already 760 if (IsLaunching()) 761 Quit(); 762 } 763 764 765 void 766 WorkspacesApp::ArgvReceived(int32 argc, char **argv) 767 { 768 for (int i = 1; i < argc; i++) { 769 if (argv[i][0] == '-' && argv[i][1] == '-') { 770 // evaluate --arguments 771 if (!strcmp(argv[i], "--notitle")) 772 fWindow->SetLook(B_MODAL_WINDOW_LOOK); 773 else if (!strcmp(argv[i], "--noborder")) 774 fWindow->SetLook(B_NO_BORDER_WINDOW_LOOK); 775 else if (!strcmp(argv[i], "--avoidfocus")) 776 fWindow->SetFlags(fWindow->Flags() | B_AVOID_FOCUS); 777 else if (!strcmp(argv[i], "--notmovable")) 778 fWindow->SetFlags(fWindow->Flags() | B_NOT_MOVABLE); 779 else if (!strcmp(argv[i], "--alwaysontop")) 780 fWindow->SetFeel(B_FLOATING_ALL_WINDOW_FEEL); 781 else if (!strcmp(argv[i], "--autoraise")) 782 fWindow->SetAutoRaise(true); 783 else { 784 const char *programName = strrchr(argv[0], '/'); 785 programName = programName ? programName + 1 : argv[0]; 786 787 Usage(programName); 788 } 789 } else if (isdigit(*argv[i])) { 790 // check for a numeric arg, if not already given 791 activate_workspace(atoi(argv[i])); 792 793 // if the app is running, don't quit 794 // but if it isn't, cancel the complete run, so it doesn't 795 // open any window 796 if (IsLaunching()) 797 Quit(); 798 } else if (!strcmp(argv[i], "-")) { 799 activate_workspace(current_workspace() - 1); 800 801 if (IsLaunching()) 802 Quit(); 803 } else if (!strcmp(argv[i], "+")) { 804 activate_workspace(current_workspace() + 1); 805 806 if (IsLaunching()) 807 Quit(); 808 } else { 809 // some unknown arguments were specified 810 fprintf(stderr, "Invalid argument: %s\n", argv[i]); 811 812 if (IsLaunching()) 813 Quit(); 814 } 815 } 816 } 817 818 819 void 820 WorkspacesApp::ReadyToRun() 821 { 822 fWindow->Show(); 823 } 824 825 826 // #pragma mark - 827 828 829 int 830 main(int argc, char **argv) 831 { 832 WorkspacesApp app; 833 app.Run(); 834 835 return 0; 836 } 837