1 /* 2 * Copyright 2003-2007, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Phipps 7 * Jérôme Duval, jerome.duval@free.fr 8 * Axel Dörfler, axeld@pinc-software.de 9 */ 10 11 12 #include "ScreenSaverWindow.h" 13 14 #include <stdio.h> 15 16 #include <Application.h> 17 #include <Box.h> 18 #include <Button.h> 19 #include <Directory.h> 20 #include <Entry.h> 21 #include <File.h> 22 #include <FindDirectory.h> 23 #include <Font.h> 24 #include <ListView.h> 25 #include <Path.h> 26 #include <Roster.h> 27 #include <Screen.h> 28 #include <ScreenSaver.h> 29 #include <ScrollView.h> 30 #include <Slider.h> 31 #include <StringView.h> 32 #include <TabView.h> 33 34 #include <BuildScreenSaverDefaultSettingsView.h> 35 36 #include "PreviewView.h" 37 #include "ScreenCornerSelector.h" 38 #include "ScreenSaverItem.h" 39 40 41 const uint32 kPreviewMonitorGap = 16; 42 const uint32 kMinSettingsWidth = 230; 43 const uint32 kMinSettingsHeight = 120; 44 45 const int32 kMsgSaverSelected = 'SSEL'; 46 const int32 kMsgTestSaver = 'TEST'; 47 const int32 kMsgAddSaver = 'ADD '; 48 const int32 kMsgPasswordCheckBox = 'PWCB'; 49 const int32 kMsgRunSliderChanged = 'RSch'; 50 const int32 kMsgRunSliderUpdate = 'RSup'; 51 const int32 kMsgPasswordSliderChanged = 'PWch'; 52 const int32 kMsgPasswordSliderUpdate = 'PWup'; 53 const int32 kMsgChangePassword = 'PWBT'; 54 const int32 kMsgEnableScreenSaverBox = 'ESCH'; 55 56 const int32 kMsgTurnOffCheckBox = 'TUOF'; 57 const int32 kMsgTurnOffSliderChanged = 'TUch'; 58 const int32 kMsgTurnOffSliderUpdate = 'TUup'; 59 60 const int32 kMsgFadeCornerChanged = 'fdcc'; 61 const int32 kMsgNeverFadeCornerChanged = 'nfcc'; 62 63 64 class TimeSlider : public BSlider { 65 public: 66 TimeSlider(BRect frame, const char* name, uint32 changedMessage, 67 uint32 updateMessage); 68 virtual ~TimeSlider(); 69 70 virtual void AttachedToWindow(); 71 virtual void SetValue(int32 value); 72 73 void SetTime(bigtime_t useconds); 74 bigtime_t Time(); 75 76 private: 77 void _TimeToString(bigtime_t useconds, BString& string); 78 }; 79 80 class FadeView : public BView { 81 public: 82 FadeView(BRect frame, const char* name, ScreenSaverSettings& settings); 83 84 virtual void AttachedToWindow(); 85 }; 86 87 class ModulesView : public BView { 88 public: 89 ModulesView(BRect frame, const char* name, ScreenSaverSettings& settings); 90 virtual ~ModulesView(); 91 92 virtual void DetachedFromWindow(); 93 virtual void AttachedToWindow(); 94 virtual void AllAttached(); 95 virtual void MessageReceived(BMessage* message); 96 97 void PopulateScreenSaverList(); 98 void SaveState(); 99 100 private: 101 static int _CompareScreenSaverItems(const void* left, const void* right); 102 BScreenSaver* _ScreenSaver(); 103 void _CloseSaver(); 104 void _OpenSaver(); 105 106 BFilePanel* fFilePanel; 107 BListView* fListView; 108 BButton* fTestButton; 109 BButton* fAddButton; 110 111 ScreenSaverSettings& fSettings; 112 ScreenSaverRunner* fSaverRunner; 113 BString fCurrentName; 114 115 BBox* fSettingsBox; 116 BView* fSettingsView; 117 118 PreviewView* fPreviewView; 119 120 team_id fScreenSaverTestTeamId; 121 }; 122 123 static const int32 kTimeInUnits[] = { 124 30, 60, 90, 125 120, 150, 180, 126 240, 300, 360, 127 420, 480, 540, 128 600, 900, 1200, 129 1500, 1800, 2400, 130 3000, 3600, 5400, 131 7200, 9000, 10800, 132 14400, 18000 133 }; 134 static const int32 kTimeUnitCount = sizeof(kTimeInUnits) / sizeof(kTimeInUnits[0]); 135 136 137 TimeSlider::TimeSlider(BRect frame, const char* name, uint32 changedMessage, 138 uint32 updateMessage) 139 : BSlider(frame, name, "30 seconds", new BMessage(changedMessage), 140 0, kTimeUnitCount - 1, B_TRIANGLE_THUMB, B_FOLLOW_LEFT_RIGHT) 141 { 142 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 143 SetModificationMessage(new BMessage(updateMessage)); 144 SetBarThickness(10); 145 } 146 147 148 TimeSlider::~TimeSlider() 149 { 150 } 151 152 153 void 154 TimeSlider::AttachedToWindow() 155 { 156 BSlider::AttachedToWindow(); 157 SetTarget(Window()); 158 } 159 160 161 void 162 TimeSlider::SetValue(int32 value) 163 { 164 int32 oldValue = Value(); 165 BSlider::SetValue(value); 166 167 if (oldValue != Value()) { 168 BString label; 169 _TimeToString(kTimeInUnits[Value()] * 1000000LL, label); 170 SetLabel(label.String()); 171 } 172 } 173 174 175 void 176 TimeSlider::SetTime(bigtime_t useconds) 177 { 178 for (int t = 0; t < kTimeUnitCount; t++) { 179 if (kTimeInUnits[t] * 1000000LL == useconds) { 180 SetValue(t); 181 break; 182 } 183 } 184 } 185 186 187 bigtime_t 188 TimeSlider::Time() 189 { 190 return 1000000LL * kTimeInUnits[Value()]; 191 } 192 193 194 void 195 TimeSlider::_TimeToString(bigtime_t useconds, BString& string) 196 { 197 useconds /= 1000000LL; 198 // convert to seconds 199 200 string = ""; 201 202 // hours 203 uint32 hours = useconds / 3600; 204 if (hours != 0) 205 string << hours << " hours"; 206 207 useconds %= 3600; 208 209 // minutes 210 uint32 minutes = useconds / 60; 211 if (hours != 0) 212 string << " "; 213 if (minutes != 0) 214 string << minutes << " minutes"; 215 216 useconds %= 60; 217 218 // seconds 219 uint32 seconds = useconds; 220 if (hours != 0 || minutes != 0) 221 string << " "; 222 if (seconds != 0) 223 string << seconds << " seconds"; 224 } 225 226 227 // #pragma mark - 228 229 230 FadeView::FadeView(BRect rect, const char* name, ScreenSaverSettings& settings) 231 : BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW) 232 { 233 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 234 } 235 236 237 void 238 FadeView::AttachedToWindow() 239 { 240 if (Parent() != NULL) { 241 // We adopt the size of our parent view (in case the window 242 // was resized during our absence (BTabView...) 243 ResizeTo(Parent()->Bounds().Width(), Parent()->Bounds().Height()); 244 } 245 } 246 247 248 // #pragma mark - 249 250 251 ModulesView::ModulesView(BRect rect, const char* name, ScreenSaverSettings& settings) 252 : BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW), 253 fSettings(settings), 254 fSaverRunner(NULL), 255 fSettingsView(NULL) 256 { 257 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 258 259 fTestButton = new BButton(rect, "TestButton", "Test", new BMessage(kMsgTestSaver), 260 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 261 float width, height; 262 fTestButton->GetPreferredSize(&width, &height); 263 fTestButton->ResizeTo(width + 16, height); 264 fTestButton->MoveTo(8, rect.bottom - 8 - height); 265 AddChild(fTestButton); 266 267 rect = fTestButton->Frame(); 268 rect.OffsetBy(fTestButton->Bounds().Width() + 8, 0); 269 fAddButton = new BButton(rect, "AddButton", "Add" B_UTF8_ELLIPSIS, 270 new BMessage(kMsgAddSaver), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 271 AddChild(fAddButton); 272 273 rect = Bounds().InsetByCopy(8 + kPreviewMonitorGap, 12); 274 rect.right = fAddButton->Frame().right - kPreviewMonitorGap; 275 rect.bottom = rect.top + 3 * rect.Width() / 4; 276 // 4:3 monitor 277 278 fPreviewView = new PreviewView(rect, "preview"); 279 AddChild(fPreviewView); 280 281 rect.left = 8; 282 rect.right -= B_V_SCROLL_BAR_WIDTH + 2 - kPreviewMonitorGap; 283 // scroll view border 284 rect.top = rect.bottom + 14; 285 rect.bottom = fTestButton->Frame().top - 10; 286 fListView = new BListView(rect, "SaversListView", B_SINGLE_SELECTION_LIST, 287 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM); 288 fListView->SetSelectionMessage(new BMessage(kMsgSaverSelected)); 289 AddChild(new BScrollView("scroll_list", fListView, 290 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 0, false, true)); 291 292 rect = Bounds().InsetByCopy(8, 8); 293 rect.left = fAddButton->Frame().right + 8; 294 AddChild(fSettingsBox = new BBox(rect, "SettingsBox", B_FOLLOW_ALL, B_WILL_DRAW)); 295 fSettingsBox->SetLabel("Module settings"); 296 297 PopulateScreenSaverList(); 298 fFilePanel = new BFilePanel(); 299 } 300 301 302 ModulesView::~ModulesView() 303 { 304 delete fFilePanel; 305 } 306 307 308 void 309 ModulesView::DetachedFromWindow() 310 { 311 _CloseSaver(); 312 } 313 314 315 void 316 ModulesView::AttachedToWindow() 317 { 318 if (Parent() != NULL) { 319 // We adopt the size of our parent view (in case the window 320 // was resized during our absence (BTabView...) 321 ResizeTo(Parent()->Bounds().Width(), Parent()->Bounds().Height()); 322 } 323 324 _OpenSaver(); 325 326 fListView->SetTarget(this); 327 fTestButton->SetTarget(this); 328 fAddButton->SetTarget(this); 329 } 330 331 332 void 333 ModulesView::AllAttached() 334 { 335 // This only works after the view has been attached 336 fListView->ScrollToSelection(); 337 } 338 339 340 void 341 ModulesView::MessageReceived(BMessage* message) 342 { 343 switch (message->what) { 344 case kMsgSaverSelected: 345 { 346 int selection = fListView->CurrentSelection(); 347 if (selection < 0) 348 break; 349 350 ScreenSaverItem* item = (ScreenSaverItem *)fListView->ItemAt(selection); 351 if (item == NULL) 352 break; 353 354 if (!strcmp(item->Text(), "Blackness")) 355 fSettings.SetModuleName(""); 356 else 357 fSettings.SetModuleName(item->Text()); 358 359 SaveState(); 360 _CloseSaver(); 361 _OpenSaver(); 362 fSettings.Save(); 363 break; 364 } 365 366 case kMsgTestSaver: 367 SaveState(); 368 fSettings.Save(); 369 370 _CloseSaver(); 371 372 be_roster->StartWatching(BMessenger(this, this->Looper()), 373 B_REQUEST_QUIT); 374 be_roster->Launch(SCREEN_BLANKER_SIG, &fSettings.Message(), 375 &fScreenSaverTestTeamId); 376 break; 377 378 case kMsgAddSaver: 379 fFilePanel->Show(); 380 break; 381 382 case B_SOME_APP_QUIT: { 383 team_id team; 384 if (message->FindInt32("be:team", &team) == B_OK) { 385 if (team == fScreenSaverTestTeamId) { 386 be_roster->StopWatching(this); 387 _OpenSaver(); 388 } 389 } 390 } 391 break; 392 393 default: 394 BView::MessageReceived(message); 395 } 396 } 397 398 399 void 400 ModulesView::SaveState() 401 { 402 BScreenSaver* saver = _ScreenSaver(); 403 if (saver == NULL) 404 return; 405 406 BMessage state; 407 if (saver->SaveState(&state) == B_OK) 408 fSettings.SetModuleState(fCurrentName.String(), &state); 409 } 410 411 412 void 413 ModulesView::PopulateScreenSaverList() 414 { 415 fListView->DeselectAll(); 416 while (ScreenSaverItem* item = (ScreenSaverItem *)fListView->RemoveItem((int32)0)) { 417 delete item; 418 } 419 420 // Blackness is a built-in screen saver 421 fListView->AddItem(new ScreenSaverItem("Blackness", "")); 422 423 // Iterate over add-on directories, and add their files to the list view 424 425 directory_which which[] = {B_BEOS_ADDONS_DIRECTORY, B_USER_ADDONS_DIRECTORY}; 426 ScreenSaverItem* selectItem = NULL; 427 428 for (uint32 i = 0; i < sizeof(which) / sizeof(which[0]); i++) { 429 BPath basePath; 430 find_directory(which[i], &basePath); 431 basePath.Append("Screen Savers", true); 432 433 BDirectory dir(basePath.Path()); 434 BEntry entry; 435 while (dir.GetNextEntry(&entry, true) == B_OK) { 436 char name[B_FILE_NAME_LENGTH]; 437 if (entry.GetName(name) != B_OK) 438 continue; 439 440 BPath path = basePath; 441 path.Append(name); 442 443 ScreenSaverItem* item = new ScreenSaverItem(name, path.Path()); 444 fListView->AddItem(item); 445 446 if (!strcmp(fSettings.ModuleName(), item->Text()) 447 || (!strcmp(fSettings.ModuleName(), "") 448 && !strcmp(item->Text(), "Blackness"))) 449 selectItem = item; 450 } 451 } 452 453 fListView->SortItems(_CompareScreenSaverItems); 454 455 fListView->Select(fListView->IndexOf(selectItem)); 456 fListView->ScrollToSelection(); 457 } 458 459 460 //! sorting function for ScreenSaverItems 461 int 462 ModulesView::_CompareScreenSaverItems(const void* left, const void* right) 463 { 464 ScreenSaverItem* leftItem = *(ScreenSaverItem **)left; 465 ScreenSaverItem* rightItem = *(ScreenSaverItem **)right; 466 467 return strcasecmp(leftItem->Text(), rightItem->Text()); 468 } 469 470 471 BScreenSaver* 472 ModulesView::_ScreenSaver() 473 { 474 if (fSaverRunner != NULL) 475 return fSaverRunner->ScreenSaver(); 476 477 return NULL; 478 } 479 480 481 void 482 ModulesView::_CloseSaver() 483 { 484 // remove old screen saver preview & config 485 486 BScreenSaver* saver = _ScreenSaver(); 487 BView* view = fPreviewView->RemovePreview(); 488 if (fSettingsView != NULL) 489 fSettingsBox->RemoveChild(fSettingsView); 490 491 if (fSaverRunner != NULL) 492 fSaverRunner->Quit(); 493 if (saver != NULL) 494 saver->StopConfig(); 495 496 delete view; 497 delete fSettingsView; 498 delete fSaverRunner; 499 // the saver runner also unloads the add-on, so it must 500 // be deleted last 501 502 fSettingsView = NULL; 503 fSaverRunner = NULL; 504 } 505 506 507 void 508 ModulesView::_OpenSaver() 509 { 510 // create new screen saver preview & config 511 512 BView* view = fPreviewView->AddPreview(); 513 fCurrentName = fSettings.ModuleName(); 514 fSaverRunner = new ScreenSaverRunner(Window(), view, true, fSettings); 515 BScreenSaver* saver = _ScreenSaver(); 516 517 #ifdef __HAIKU__ 518 BRect rect = fSettingsBox->InnerFrame().InsetByCopy(4, 4); 519 #else 520 BRect rect = fSettingsBox->Bounds().InsetByCopy(4, 4); 521 rect.top += 14; 522 #endif 523 fSettingsView = new BView(rect, "SettingsView", B_FOLLOW_ALL, B_WILL_DRAW); 524 fSettingsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 525 fSettingsBox->AddChild(fSettingsView); 526 527 if (saver != NULL) { 528 fSaverRunner->Run(); 529 saver->StartConfig(fSettingsView); 530 } 531 532 if (fSettingsView->ChildAt(0) == NULL) { 533 // There are no settings at all, we add the module name here to 534 // let it look a bit better at least. 535 BPrivate::BuildScreenSaverDefaultSettingsView(fSettingsView, 536 fSettings.ModuleName()[0] ? fSettings.ModuleName() : "Blackness", 537 saver || !fSettings.ModuleName()[0] 538 ? "No options available" : "Could not load screen saver"); 539 } 540 541 ScreenSaverWindow* window = dynamic_cast<ScreenSaverWindow*>(Window()); 542 if (window == NULL) 543 return; 544 545 // find the minimal size of the settings view 546 547 float right = 0, bottom = 0; 548 int32 i = 0; 549 while ((view = fSettingsView->ChildAt(i++)) != NULL) { 550 // very simple heuristic... 551 float viewRight = view->Frame().right; 552 if ((view->ResizingMode() & _rule_(0, 0xf, 0, 0xf)) == B_FOLLOW_LEFT_RIGHT) { 553 float width, height; 554 view->GetPreferredSize(&width, &height); 555 viewRight = view->Frame().left + width / 2; 556 } else if ((view->ResizingMode() & _rule_(0, 0xf, 0, 0xf)) == B_FOLLOW_RIGHT) 557 viewRight = 8 + view->Frame().Width(); 558 559 float viewBottom = view->Frame().bottom; 560 if ((view->ResizingMode() & _rule_(0xf, 0, 0xf, 0)) == B_FOLLOW_TOP_BOTTOM) { 561 float width, height; 562 view->GetPreferredSize(&width, &height); 563 viewBottom = view->Frame().top + height; 564 } else if ((view->ResizingMode() & _rule_(0xf, 0, 0xf, 0)) == B_FOLLOW_BOTTOM) 565 viewBottom = 8 + view->Frame().Height(); 566 567 if (viewRight > right) 568 right = viewRight; 569 if (viewBottom > bottom) 570 bottom = viewBottom; 571 } 572 573 if (right < kMinSettingsWidth) 574 right = kMinSettingsWidth; 575 if (bottom < kMinSettingsHeight) 576 bottom = kMinSettingsHeight; 577 578 BPoint leftTop = fSettingsView->LeftTop(); 579 fSettingsView->ConvertToScreen(&leftTop); 580 window->ConvertFromScreen(&leftTop); 581 window->SetMinimalSizeLimit(leftTop.x + right + 16, 582 leftTop.y + bottom + 16); 583 } 584 585 586 // #pragma mark - 587 588 589 ScreenSaverWindow::ScreenSaverWindow() 590 : BWindow(BRect(50, 50, 496, 375), "ScreenSaver", 591 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS /*| B_NOT_ZOOMABLE | B_NOT_RESIZABLE*/) 592 { 593 fSettings.Load(); 594 595 BRect rect = Bounds(); 596 fMinWidth = 430; 597 fMinHeight = 325; 598 599 // Create a background view 600 BView *background = new BView(rect, "background", B_FOLLOW_ALL, 0); 601 background->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 602 AddChild(background); 603 604 // Add the tab view to the background 605 rect.top += 4; 606 fTabView = new BTabView(rect, "tab_view"); 607 608 // Create the controls inside the tabs 609 rect = fTabView->ContainerView()->Bounds(); 610 _SetupFadeTab(rect); 611 fModulesView = new ModulesView(rect, "Modules", fSettings); 612 613 fTabView->AddTab(fFadeView); 614 fTabView->AddTab(fModulesView); 615 background->AddChild(fTabView); 616 617 // Create the password editing window 618 fPasswordWindow = new PasswordWindow(fSettings); 619 fPasswordWindow->Run(); 620 621 SetMinimalSizeLimit(fMinWidth, fMinHeight); 622 MoveTo(fSettings.WindowFrame().left, fSettings.WindowFrame().top); 623 ResizeTo(fSettings.WindowFrame().Width(), fSettings.WindowFrame().Height()); 624 625 fEnableCheckBox->SetValue(fSettings.TimeFlags() & ENABLE_SAVER ? B_CONTROL_ON : B_CONTROL_OFF); 626 fRunSlider->SetTime(fSettings.BlankTime()); 627 fTurnOffSlider->SetTime(fSettings.OffTime() + fSettings.BlankTime()); 628 fFadeNow->SetCorner(fSettings.BlankCorner()); 629 fFadeNever->SetCorner(fSettings.NeverBlankCorner()); 630 fPasswordCheckBox->SetValue(fSettings.LockEnable()); 631 fPasswordSlider->SetTime(fSettings.PasswordTime()); 632 633 fTabView->Select(fSettings.WindowTab()); 634 635 _UpdateTurnOffScreen(); 636 _UpdateStatus(); 637 } 638 639 640 ScreenSaverWindow::~ScreenSaverWindow() 641 { 642 } 643 644 645 //! Create the controls for the fade tab 646 void 647 ScreenSaverWindow::_SetupFadeTab(BRect rect) 648 { 649 fFadeView = new FadeView(rect, "Fade", fSettings); 650 651 float labelWidth = be_plain_font->StringWidth("Turn off screen") + 20.0f; 652 653 font_height fontHeight; 654 be_plain_font->GetHeight(&fontHeight); 655 float textHeight = ceilf(fontHeight.ascent + fontHeight.descent); 656 657 // taken from BRadioButton: 658 float radioButtonOffset = 2 * floorf(textHeight / 2 - 2) + floorf(textHeight / 2); 659 660 fEnableCheckBox = new BCheckBox(BRect(0, 0, 1, 1), "EnableCheckBox", 661 "Enable Screen Saver", new BMessage(kMsgEnableScreenSaverBox)); 662 fEnableCheckBox->ResizeToPreferred(); 663 664 rect.InsetBy(8, 8); 665 BBox* box = new BBox(rect, "EnableScreenSaverBox", B_FOLLOW_ALL); 666 box->SetLabel(fEnableCheckBox); 667 fFadeView->AddChild(box); 668 669 // Run Module 670 rect.left += radioButtonOffset; 671 rect.top = fEnableCheckBox->Bounds().bottom + 8.0f; 672 rect.right = box->Bounds().right - 8; 673 BStringView* stringView = new BStringView(rect, NULL, "Run module"); 674 stringView->ResizeToPreferred(); 675 box->AddChild(stringView); 676 677 rect.left += labelWidth; 678 fRunSlider = new TimeSlider(rect, "RunSlider", kMsgRunSliderChanged, 679 kMsgRunSliderUpdate); 680 float width, height; 681 fRunSlider->GetPreferredSize(&width, &height); 682 fRunSlider->ResizeTo(fRunSlider->Bounds().Width(), height); 683 box->AddChild(fRunSlider); 684 685 // Turn Off 686 rect.left = 8; 687 rect.OffsetBy(0, fRunSlider->Bounds().Height() + 4.0f); 688 fTurnOffCheckBox = new BCheckBox(rect, "TurnOffScreenCheckBox", 689 "Turn off screen", new BMessage(kMsgTurnOffCheckBox)); 690 fTurnOffCheckBox->ResizeToPreferred(); 691 box->AddChild(fTurnOffCheckBox); 692 693 rect.left += radioButtonOffset + labelWidth; 694 fTurnOffSlider = new TimeSlider(rect, "TurnOffSlider", 695 kMsgTurnOffSliderChanged, kMsgTurnOffSliderUpdate); 696 fTurnOffSlider->ResizeTo(fTurnOffSlider->Bounds().Width(), height); 697 box->AddChild(fTurnOffSlider); 698 699 // Password 700 rect.left = 8; 701 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 702 fPasswordCheckBox = new BCheckBox(rect, "PasswordCheckbox", 703 "Password lock", new BMessage(kMsgPasswordCheckBox)); 704 fPasswordCheckBox->ResizeToPreferred(); 705 box->AddChild(fPasswordCheckBox); 706 707 rect.left += radioButtonOffset + labelWidth; 708 fPasswordSlider = new TimeSlider(rect, "PasswordSlider", 709 kMsgPasswordSliderChanged, kMsgPasswordSliderUpdate); 710 fPasswordSlider->ResizeTo(fPasswordSlider->Bounds().Width(), height); 711 box->AddChild(fPasswordSlider); 712 713 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 714 rect.left = rect.right; 715 fPasswordButton = new BButton(rect, "PasswordButton", "Password" B_UTF8_ELLIPSIS, 716 new BMessage(kMsgChangePassword), B_FOLLOW_TOP | B_FOLLOW_RIGHT); 717 fPasswordButton->ResizeToPreferred(); 718 fPasswordButton->MoveBy(-fPasswordButton->Bounds().Width(), 0); 719 box->AddChild(fPasswordButton); 720 721 // Bottom 722 723 float monitorHeight = 10 + textHeight * 3; 724 float monitorWidth = monitorHeight * 4 / 3; 725 rect.left = 15; 726 rect.top = box->Bounds().Height() - 15 - monitorHeight; 727 rect.right = rect.left + monitorWidth; 728 rect.bottom = rect.top + monitorHeight; 729 box->AddChild(fFadeNow = new ScreenCornerSelector(rect, "FadeNow", 730 new BMessage(kMsgFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 731 732 rect.OffsetBy(monitorWidth + 10, 0); 733 stringView = new BStringView(rect, NULL, "Fade now when", 734 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 735 stringView->ResizeToPreferred(); 736 float maxWidth = stringView->Bounds().Width(); 737 box->AddChild(stringView); 738 739 rect.OffsetBy(0, stringView->Bounds().Height()); 740 stringView = new BStringView(rect, NULL, "mouse is here", 741 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 742 stringView->ResizeToPreferred(); 743 if (maxWidth < stringView->Bounds().Width()) 744 maxWidth = stringView->Bounds().Width(); 745 box->AddChild(stringView); 746 747 rect.left += maxWidth + 20; 748 rect.top = box->Bounds().Height() - 15 - monitorHeight; 749 rect.right = rect.left + monitorWidth; 750 rect.bottom = rect.top + monitorHeight; 751 box->AddChild(fFadeNever = new ScreenCornerSelector(rect, "FadeNever", 752 new BMessage(kMsgNeverFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 753 754 rect.OffsetBy(monitorWidth + 10, 0); 755 stringView = new BStringView(rect, NULL,"Don't fade when", 756 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 757 stringView->ResizeToPreferred(); 758 if (maxWidth < stringView->Bounds().Width()) 759 maxWidth = stringView->Bounds().Width(); 760 box->AddChild(stringView); 761 762 rect.OffsetBy(0, stringView->Bounds().Height()); 763 stringView = new BStringView(rect, NULL, "mouse is here", 764 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 765 stringView->ResizeToPreferred(); 766 if (maxWidth < stringView->Bounds().Width()) 767 maxWidth = stringView->Bounds().Width(); 768 box->AddChild(stringView); 769 770 float size = rect.left + maxWidth + 40; 771 if (fMinWidth < size) 772 fMinWidth = size; 773 size = fPasswordButton->Frame().bottom + box->Frame().top 774 + monitorHeight + 40 + textHeight * 2; 775 if (fMinHeight < size) 776 fMinHeight = size; 777 } 778 779 780 void 781 ScreenSaverWindow::_UpdateTurnOffScreen() 782 { 783 bool enabled = (fSettings.TimeFlags() & ENABLE_DPMS_MASK) != 0; 784 785 BScreen screen(this); 786 uint32 dpmsCapabilities = screen.DPMSCapabilites(); 787 788 fTurnOffScreenFlags = 0; 789 if (dpmsCapabilities & B_DPMS_OFF) 790 fTurnOffScreenFlags |= ENABLE_DPMS_OFF; 791 if (dpmsCapabilities & B_DPMS_STAND_BY) 792 fTurnOffScreenFlags |= ENABLE_DPMS_STAND_BY; 793 if (dpmsCapabilities & B_DPMS_SUSPEND) 794 fTurnOffScreenFlags |= ENABLE_DPMS_SUSPEND; 795 796 fTurnOffCheckBox->SetValue(enabled && fTurnOffScreenFlags != 0 797 ? B_CONTROL_ON : B_CONTROL_OFF); 798 } 799 800 801 void 802 ScreenSaverWindow::_UpdateStatus() 803 { 804 DisableUpdates(); 805 806 bool enabled = fEnableCheckBox->Value() == B_CONTROL_ON; 807 fPasswordCheckBox->SetEnabled(enabled); 808 fTurnOffCheckBox->SetEnabled(enabled && fTurnOffScreenFlags != 0); 809 fRunSlider->SetEnabled(enabled); 810 fTurnOffSlider->SetEnabled(enabled && fTurnOffCheckBox->Value()); 811 fPasswordSlider->SetEnabled(enabled && fPasswordCheckBox->Value()); 812 fPasswordButton->SetEnabled(enabled && fPasswordCheckBox->Value()); 813 814 EnableUpdates(); 815 816 // Update the saved preferences 817 fSettings.SetWindowFrame(Frame()); 818 fSettings.SetWindowTab(fTabView->Selection()); 819 fSettings.SetTimeFlags((enabled ? ENABLE_SAVER : 0) 820 | (fTurnOffCheckBox->Value() ? fTurnOffScreenFlags : 0)); 821 fSettings.SetBlankTime(fRunSlider->Time()); 822 bigtime_t offTime = fTurnOffSlider->Time() - fSettings.BlankTime(); 823 fSettings.SetOffTime(offTime); 824 fSettings.SetSuspendTime(offTime); 825 fSettings.SetStandByTime(offTime); 826 fSettings.SetBlankCorner(fFadeNow->Corner()); 827 fSettings.SetNeverBlankCorner(fFadeNever->Corner()); 828 fSettings.SetLockEnable(fPasswordCheckBox->Value()); 829 fSettings.SetPasswordTime(fPasswordSlider->Time()); 830 831 // TODO - Tell the password window to update its stuff 832 } 833 834 835 void 836 ScreenSaverWindow::SetMinimalSizeLimit(float width, float height) 837 { 838 if (width < fMinWidth) 839 width = fMinWidth; 840 if (height < fMinHeight) 841 height = fMinHeight; 842 843 SetSizeLimits(width, 32767, height, 32767); 844 } 845 846 847 void 848 ScreenSaverWindow::MessageReceived(BMessage *msg) 849 { 850 // "Fade" tab, slider updates 851 852 switch (msg->what) { 853 case kMsgRunSliderChanged: 854 case kMsgRunSliderUpdate: 855 if (fRunSlider->Value() > fTurnOffSlider->Value()) 856 fTurnOffSlider->SetValue(fRunSlider->Value()); 857 858 if (fRunSlider->Value() > fPasswordSlider->Value()) 859 fPasswordSlider->SetValue(fRunSlider->Value()); 860 break; 861 862 case kMsgTurnOffSliderChanged: 863 case kMsgTurnOffSliderUpdate: 864 if (fRunSlider->Value() > fTurnOffSlider->Value()) 865 fRunSlider->SetValue(fTurnOffSlider->Value()); 866 break; 867 868 case kMsgPasswordSliderChanged: 869 case kMsgPasswordSliderUpdate: 870 if (fPasswordSlider->Value() < fRunSlider->Value()) 871 fRunSlider->SetValue(fPasswordSlider->Value()); 872 break; 873 } 874 875 switch (msg->what) { 876 // "Fade" tab 877 878 case kMsgTurnOffCheckBox: 879 fTurnOffSlider->SetEnabled(fTurnOffCheckBox->Value() == B_CONTROL_ON); 880 break; 881 882 case kMsgRunSliderChanged: 883 case kMsgTurnOffSliderChanged: 884 case kMsgPasswordSliderChanged: 885 case kMsgPasswordCheckBox: 886 case kMsgEnableScreenSaverBox: 887 case kMsgFadeCornerChanged: 888 case kMsgNeverFadeCornerChanged: 889 _UpdateStatus(); 890 fSettings.Save(); 891 break; 892 893 case kMsgChangePassword: 894 fPasswordWindow->Show(); 895 break; 896 897 // "Modules" tab 898 899 case kMsgUpdateList: 900 fModulesView->PopulateScreenSaverList(); 901 break; 902 903 default: 904 BWindow::MessageReceived(msg); 905 break; 906 } 907 } 908 909 910 void 911 ScreenSaverWindow::ScreenChanged(BRect frame, color_space colorSpace) 912 { 913 _UpdateTurnOffScreen(); 914 } 915 916 917 bool 918 ScreenSaverWindow::QuitRequested() 919 { 920 _UpdateStatus(); 921 fModulesView->SaveState(); 922 fSettings.Save(); 923 924 be_app->PostMessage(B_QUIT_REQUESTED); 925 return true; 926 } 927 928