tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / preferences / screensaver / ScreenSaverWindow.cpp
blob5dfa4dd8215d602d34672c3e78e3ae0fdc38524c
1 /*
2 * Copyright 2003-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 * Jérôme Duval, jerome.duval@free.fr
8 * Michael Phipps
9 * John Scipione, jscipione@gmail.com
10 * Puck Meerburg, puck@puckipedia.nl
14 #include "ScreenSaverWindow.h"
16 #include <stdio.h>
17 #include <strings.h>
19 #include <Alignment.h>
20 #include <Application.h>
21 #include <Box.h>
22 #include <Button.h>
23 #include <Catalog.h>
24 #include <CheckBox.h>
25 #include <ControlLook.h>
26 #include <Directory.h>
27 #include <DurationFormat.h>
28 #include <Entry.h>
29 #include <File.h>
30 #include <FindDirectory.h>
31 #include <Font.h>
32 #include <Layout.h>
33 #include <LayoutBuilder.h>
34 #include <ListItem.h>
35 #include <ListView.h>
36 #include <Path.h>
37 #include <Rect.h>
38 #include <Roster.h>
39 #include <Screen.h>
40 #include <ScreenSaver.h>
41 #include <ScreenSaverRunner.h>
42 #include <ScrollView.h>
43 #include <Size.h>
44 #include <Slider.h>
45 #include <StringView.h>
46 #include <TabView.h>
47 #include <TextView.h>
49 #include <algorithm>
50 // for std::max and std::min
52 #include <BuildScreenSaverDefaultSettingsView.h>
54 #include "PreviewView.h"
55 #include "ScreenCornerSelector.h"
56 #include "ScreenSaverItem.h"
57 #include "ScreenSaverShared.h"
59 #undef B_TRANSLATION_CONTEXT
60 #define B_TRANSLATION_CONTEXT "ScreenSaver"
63 const uint32 kPreviewMonitorGap = 16;
64 const uint32 kMinSettingsWidth = 230;
65 const uint32 kMinSettingsHeight = 120;
67 const int32 kMsgSaverSelected = 'SSEL';
68 const int32 kMsgPasswordCheckBox = 'PWCB';
69 const int32 kMsgRunSliderChanged = 'RSch';
70 const int32 kMsgRunSliderUpdate = 'RSup';
71 const int32 kMsgPasswordSliderChanged = 'PWch';
72 const int32 kMsgPasswordSliderUpdate = 'PWup';
73 const int32 kMsgChangePassword = 'PWBT';
74 const int32 kMsgEnableScreenSaverBox = 'ESCH';
76 const int32 kMsgTurnOffCheckBox = 'TUOF';
77 const int32 kMsgTurnOffSliderChanged = 'TUch';
78 const int32 kMsgTurnOffSliderUpdate = 'TUup';
80 const int32 kMsgFadeCornerChanged = 'fdcc';
81 const int32 kMsgNeverFadeCornerChanged = 'nfcc';
84 class TimeSlider : public BSlider {
85 public:
86 TimeSlider(const char* name,
87 uint32 changedMessage,
88 uint32 updateMessage);
89 virtual ~TimeSlider();
91 virtual void SetValue(int32 value);
93 void SetTime(bigtime_t useconds);
94 bigtime_t Time() const;
96 private:
97 void _TimeToString(bigtime_t useconds,
98 BString& string);
102 class TabView : public BTabView {
103 public:
104 TabView();
106 virtual void MouseDown(BPoint where);
110 class FadeView : public BView {
111 public:
112 FadeView(const char* name,
113 ScreenSaverSettings& settings);
115 virtual void AttachedToWindow();
116 virtual void MessageReceived(BMessage* message);
118 void UpdateTurnOffScreen();
119 void UpdateStatus();
121 private:
122 ScreenSaverSettings& fSettings;
123 uint32 fTurnOffScreenFlags;
125 BCheckBox* fEnableCheckBox;
126 TimeSlider* fRunSlider;
128 BTextView* fTurnOffNotSupported;
129 BCheckBox* fTurnOffCheckBox;
130 TimeSlider* fTurnOffSlider;
132 BCheckBox* fPasswordCheckBox;
133 TimeSlider* fPasswordSlider;
134 BButton* fPasswordButton;
136 ScreenCornerSelector* fFadeNow;
137 ScreenCornerSelector* fFadeNever;
141 class ModulesView : public BView {
142 public:
143 ModulesView(const char* name,
144 ScreenSaverSettings& settings);
145 virtual ~ModulesView();
147 virtual void DetachedFromWindow();
148 virtual void AttachedToWindow();
149 virtual void AllAttached();
150 virtual void MessageReceived(BMessage* message);
152 void EmptyScreenSaverList();
153 void PopulateScreenSaverList();
155 void SaveState();
157 BScreenSaver* ScreenSaver();
159 private:
160 friend class TabView;
162 static int _CompareScreenSaverItems(const void* left,
163 const void* right);
165 void _CloseSaver();
166 void _OpenSaver();
168 private:
169 ScreenSaverSettings& fSettings;
171 BListView* fScreenSaversListView;
172 BButton* fTestButton;
174 ScreenSaverRunner* fSaverRunner;
175 BString fCurrentName;
177 BBox* fSettingsBox;
178 BView* fSettingsView;
180 PreviewView* fPreviewView;
182 team_id fScreenSaverTestTeam;
186 // #pragma mark - TimeSlider
189 static const int32 kTimeInUnits[] = {
190 30, 60, 90,
191 120, 150, 180,
192 240, 300, 360,
193 420, 480, 540,
194 600, 900, 1200,
195 1500, 1800, 2400,
196 3000, 3600, 5400,
197 7200, 9000, 10800,
198 14400, 18000
201 static const int32 kTimeUnitCount
202 = sizeof(kTimeInUnits) / sizeof(kTimeInUnits[0]);
205 TimeSlider::TimeSlider(const char* name, uint32 changedMessage,
206 uint32 updateMessage)
208 BSlider(name, B_TRANSLATE("30 seconds"), new BMessage(changedMessage),
209 0, kTimeUnitCount - 1, B_HORIZONTAL, B_TRIANGLE_THUMB)
211 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
212 SetModificationMessage(new BMessage(updateMessage));
213 SetBarThickness(10);
217 TimeSlider::~TimeSlider()
222 void
223 TimeSlider::SetValue(int32 value)
225 int32 oldValue = Value();
226 BSlider::SetValue(value);
228 if (oldValue != Value()) {
229 BString label;
230 _TimeToString(kTimeInUnits[Value()] * 1000000LL, label);
231 SetLabel(label.String());
236 void
237 TimeSlider::SetTime(bigtime_t useconds)
239 for (int t = 0; t < kTimeUnitCount; t++) {
240 if (kTimeInUnits[t] * 1000000LL == useconds) {
241 SetValue(t);
242 break;
248 bigtime_t
249 TimeSlider::Time() const
251 return 1000000LL * kTimeInUnits[Value()];
255 void
256 TimeSlider::_TimeToString(bigtime_t useconds, BString& string)
258 BDurationFormat formatter;
259 formatter.Format(string, 0, useconds);
263 // #pragma mark - FadeView
266 FadeView::FadeView(const char* name, ScreenSaverSettings& settings)
268 BView(name, B_WILL_DRAW),
269 fSettings(settings)
271 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
273 font_height fontHeight;
274 be_plain_font->GetHeight(&fontHeight);
275 float textHeight = ceilf(fontHeight.ascent + fontHeight.descent);
277 fEnableCheckBox = new BCheckBox("EnableCheckBox",
278 B_TRANSLATE("Enable screensaver"),
279 new BMessage(kMsgEnableScreenSaverBox));
281 BBox* box = new BBox("EnableScreenSaverBox");
282 box->SetLabel(fEnableCheckBox);
284 // Start Screensaver
285 BStringView* startScreenSaver = new BStringView("startScreenSaver",
286 B_TRANSLATE("Start screensaver"));
287 startScreenSaver->SetAlignment(B_ALIGN_RIGHT);
289 fRunSlider = new TimeSlider("RunSlider", kMsgRunSliderChanged,
290 kMsgRunSliderUpdate);
292 // Turn Off
293 rgb_color textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
294 B_DISABLED_LABEL_TINT);
295 fTurnOffNotSupported = new BTextView("not_supported", be_plain_font,
296 &textColor, B_WILL_DRAW);
297 fTurnOffNotSupported->SetExplicitMinSize(BSize(B_SIZE_UNSET,
298 3 + textHeight * 3));
299 fTurnOffNotSupported->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
300 fTurnOffNotSupported->MakeEditable(false);
301 fTurnOffNotSupported->MakeSelectable(false);
302 fTurnOffNotSupported->SetText(
303 B_TRANSLATE("Display Power Management Signaling not available"));
305 fTurnOffCheckBox = new BCheckBox("TurnOffScreenCheckBox",
306 B_TRANSLATE("Turn off screen"), new BMessage(kMsgTurnOffCheckBox));
307 fTurnOffCheckBox->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
308 B_ALIGN_VERTICAL_CENTER));
310 fTurnOffSlider = new TimeSlider("TurnOffSlider", kMsgTurnOffSliderChanged,
311 kMsgTurnOffSliderUpdate);
313 // Password
314 fPasswordCheckBox = new BCheckBox("PasswordCheckbox",
315 B_TRANSLATE("Password lock"), new BMessage(kMsgPasswordCheckBox));
316 fPasswordCheckBox->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
317 B_ALIGN_VERTICAL_CENTER));
319 fPasswordSlider = new TimeSlider("PasswordSlider",
320 kMsgPasswordSliderChanged, kMsgPasswordSliderUpdate);
322 fPasswordButton = new BButton("PasswordButton",
323 B_TRANSLATE("Password" B_UTF8_ELLIPSIS),
324 new BMessage(kMsgChangePassword));
326 // Bottom
327 float monitorHeight = 10 + textHeight * 3;
328 float aspectRatio = 4.0f / 3.0f;
329 float monitorWidth = monitorHeight * aspectRatio;
330 BRect monitorRect = BRect(0, 0, monitorWidth, monitorHeight);
332 fFadeNow = new ScreenCornerSelector(monitorRect, "FadeNow",
333 new BMessage(kMsgFadeCornerChanged), B_FOLLOW_NONE);
334 BTextView* fadeNowText = new BTextView("FadeNowText", B_WILL_DRAW);
335 fadeNowText->SetExplicitMinSize(BSize(B_SIZE_UNSET,
336 4 + textHeight * 4));
337 fadeNowText->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
338 fadeNowText->MakeEditable(false);
339 fadeNowText->MakeSelectable(false);
340 fadeNowText->SetText(B_TRANSLATE("Fade now when mouse is here"));
342 fFadeNever = new ScreenCornerSelector(monitorRect, "FadeNever",
343 new BMessage(kMsgNeverFadeCornerChanged), B_FOLLOW_NONE);
344 BTextView* fadeNeverText = new BTextView("FadeNeverText", B_WILL_DRAW);
345 fadeNeverText->SetExplicitMinSize(BSize(B_SIZE_UNSET,
346 4 + textHeight * 4));
347 fadeNeverText->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
348 fadeNeverText->MakeEditable(false);
349 fadeNeverText->MakeSelectable(false);
350 fadeNeverText->SetText(B_TRANSLATE("Don't fade when mouse is here"));
352 box->AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
353 .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
354 B_USE_DEFAULT_SPACING)
355 .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
356 .Add(startScreenSaver, 0, 0)
357 .Add(fRunSlider, 1, 0)
358 .Add(fTurnOffCheckBox, 0, 1)
359 .Add(BLayoutBuilder::Group<>(B_VERTICAL)
360 .Add(fTurnOffNotSupported)
361 .Add(fTurnOffSlider)
362 .View(), 1, 1)
363 .Add(fPasswordCheckBox, 0, 2)
364 .Add(fPasswordSlider, 1, 2)
365 .End()
366 .AddGroup(B_HORIZONTAL)
367 .AddGlue()
368 .Add(fPasswordButton)
369 .End()
370 .AddGlue()
371 .AddGroup(B_HORIZONTAL)
372 .Add(fFadeNow)
373 .AddGroup(B_VERTICAL, 0)
374 .Add(fadeNowText)
375 .AddGlue()
376 .End()
377 .Add(fFadeNever)
378 .AddGroup(B_VERTICAL, 0)
379 .Add(fadeNeverText)
380 .AddGlue()
381 .End()
382 .End()
383 .AddGlue()
384 .View());
386 BLayoutBuilder::Group<>(this, B_HORIZONTAL)
387 .SetInsets(B_USE_SMALL_SPACING)
388 .Add(box)
389 .End();
393 void
394 FadeView::AttachedToWindow()
396 fEnableCheckBox->SetTarget(this);
397 fRunSlider->SetTarget(this);
398 fTurnOffCheckBox->SetTarget(this);
399 fTurnOffSlider->SetTarget(this);
400 fFadeNow->SetTarget(this);
401 fFadeNever->SetTarget(this);
402 fPasswordCheckBox->SetTarget(this);
403 fPasswordSlider->SetTarget(this);
405 fEnableCheckBox->SetValue(
406 fSettings.TimeFlags() & ENABLE_SAVER ? B_CONTROL_ON : B_CONTROL_OFF);
407 fRunSlider->SetTime(fSettings.BlankTime());
408 fTurnOffSlider->SetTime(fSettings.OffTime() + fSettings.BlankTime());
409 fFadeNow->SetCorner(fSettings.BlankCorner());
410 fFadeNever->SetCorner(fSettings.NeverBlankCorner());
411 fPasswordCheckBox->SetValue(fSettings.LockEnable());
412 fPasswordSlider->SetTime(fSettings.PasswordTime());
414 UpdateTurnOffScreen();
415 UpdateStatus();
419 void
420 FadeView::MessageReceived(BMessage *message)
422 switch (message->what) {
423 case kMsgRunSliderChanged:
424 case kMsgRunSliderUpdate:
425 if (fRunSlider->Value() > fTurnOffSlider->Value())
426 fTurnOffSlider->SetValue(fRunSlider->Value());
428 if (fRunSlider->Value() > fPasswordSlider->Value())
429 fPasswordSlider->SetValue(fRunSlider->Value());
430 break;
432 case kMsgTurnOffSliderChanged:
433 case kMsgTurnOffSliderUpdate:
434 if (fRunSlider->Value() > fTurnOffSlider->Value())
435 fRunSlider->SetValue(fTurnOffSlider->Value());
436 break;
438 case kMsgPasswordSliderChanged:
439 case kMsgPasswordSliderUpdate:
440 if (fPasswordSlider->Value() < fRunSlider->Value())
441 fRunSlider->SetValue(fPasswordSlider->Value());
442 break;
444 case kMsgTurnOffCheckBox:
445 fTurnOffSlider->SetEnabled(
446 fTurnOffCheckBox->Value() == B_CONTROL_ON);
447 break;
450 switch (message->what) {
451 case kMsgRunSliderChanged:
452 case kMsgTurnOffSliderChanged:
453 case kMsgPasswordSliderChanged:
454 case kMsgPasswordCheckBox:
455 case kMsgEnableScreenSaverBox:
456 case kMsgFadeCornerChanged:
457 case kMsgNeverFadeCornerChanged:
458 UpdateStatus();
459 fSettings.Save();
460 break;
462 default:
463 BView::MessageReceived(message);
468 void
469 FadeView::UpdateTurnOffScreen()
471 bool enabled = (fSettings.TimeFlags() & ENABLE_DPMS_MASK) != 0;
473 BScreen screen(Window());
474 uint32 dpmsCapabilities = screen.DPMSCapabilites();
476 fTurnOffScreenFlags = 0;
477 if (dpmsCapabilities & B_DPMS_OFF)
478 fTurnOffScreenFlags |= ENABLE_DPMS_OFF;
479 if (dpmsCapabilities & B_DPMS_STAND_BY)
480 fTurnOffScreenFlags |= ENABLE_DPMS_STAND_BY;
481 if (dpmsCapabilities & B_DPMS_SUSPEND)
482 fTurnOffScreenFlags |= ENABLE_DPMS_SUSPEND;
484 fTurnOffCheckBox->SetValue(enabled && fTurnOffScreenFlags != 0
485 ? B_CONTROL_ON : B_CONTROL_OFF);
487 enabled = fEnableCheckBox->Value() == B_CONTROL_ON;
488 fTurnOffCheckBox->SetEnabled(enabled && fTurnOffScreenFlags != 0);
489 if (fTurnOffScreenFlags != 0) {
490 fTurnOffNotSupported->Hide();
491 fTurnOffSlider->Show();
492 } else {
493 fTurnOffSlider->Hide();
494 fTurnOffNotSupported->Show();
499 void
500 FadeView::UpdateStatus()
502 Window()->DisableUpdates();
504 bool enabled = fEnableCheckBox->Value() == B_CONTROL_ON;
505 fPasswordCheckBox->SetEnabled(enabled);
506 fTurnOffCheckBox->SetEnabled(enabled && fTurnOffScreenFlags != 0);
507 fRunSlider->SetEnabled(enabled);
508 fTurnOffSlider->SetEnabled(enabled && fTurnOffCheckBox->Value());
509 fPasswordSlider->SetEnabled(enabled && fPasswordCheckBox->Value());
510 fPasswordButton->SetEnabled(enabled && fPasswordCheckBox->Value());
512 Window()->EnableUpdates();
514 // Update the saved preferences
515 fSettings.SetWindowFrame(Frame());
516 fSettings.SetTimeFlags((enabled ? ENABLE_SAVER : 0)
517 | (fTurnOffCheckBox->Value() ? fTurnOffScreenFlags : 0));
518 fSettings.SetBlankTime(fRunSlider->Time());
519 bigtime_t offTime = fTurnOffSlider->Time() - fSettings.BlankTime();
520 fSettings.SetOffTime(offTime);
521 fSettings.SetSuspendTime(offTime);
522 fSettings.SetStandByTime(offTime);
523 fSettings.SetBlankCorner(fFadeNow->Corner());
524 fSettings.SetNeverBlankCorner(fFadeNever->Corner());
525 fSettings.SetLockEnable(fPasswordCheckBox->Value());
526 fSettings.SetPasswordTime(fPasswordSlider->Time());
528 // TODO - Tell the password window to update its stuff
532 // #pragma mark - ModulesView
535 ModulesView::ModulesView(const char* name, ScreenSaverSettings& settings)
537 BView(name, B_WILL_DRAW),
538 fSettings(settings),
539 fScreenSaversListView(new BListView("SaversListView")),
540 fTestButton(new BButton("TestButton", B_TRANSLATE("Test"),
541 new BMessage(kMsgTestSaver))),
542 fSaverRunner(NULL),
543 fSettingsBox(new BBox("SettingsBox")),
544 fSettingsView(NULL),
545 fPreviewView(new PreviewView("preview")),
546 fScreenSaverTestTeam(-1)
548 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
550 fScreenSaversListView->SetSelectionMessage(
551 new BMessage(kMsgSaverSelected));
552 BScrollView* saversListScrollView = new BScrollView("scroll_list",
553 fScreenSaversListView, 0, false, true);
555 fSettingsBox->SetLabel(B_TRANSLATE("Screensaver settings"));
557 BLayoutBuilder::Group<>(this, B_HORIZONTAL)
558 .SetInsets(B_USE_DEFAULT_SPACING)
559 .AddGroup(B_VERTICAL)
560 .Add(fPreviewView)
561 .Add(saversListScrollView)
562 .AddGroup(B_HORIZONTAL)
563 .Add(fTestButton)
564 .AddGlue()
565 .End()
566 .End()
567 .Add(fSettingsBox)
568 .End();
572 ModulesView::~ModulesView()
574 delete fTestButton;
575 delete fSettingsBox;
576 delete fPreviewView;
580 void
581 ModulesView::DetachedFromWindow()
583 SaveState();
584 EmptyScreenSaverList();
586 _CloseSaver();
590 void
591 ModulesView::AttachedToWindow()
593 fScreenSaversListView->SetTarget(this);
594 fTestButton->SetTarget(this);
598 void
599 ModulesView::AllAttached()
601 PopulateScreenSaverList();
602 fScreenSaversListView->Invoke();
606 void
607 ModulesView::MessageReceived(BMessage* message)
609 switch (message->what) {
610 case kMsgSaverSelected:
612 int32 selection = fScreenSaversListView->CurrentSelection();
613 if (selection < 0)
614 break;
616 ScreenSaverItem* item
617 = (ScreenSaverItem*)fScreenSaversListView->ItemAt(selection);
618 if (item == NULL)
619 break;
621 if (strcmp(item->Text(), B_TRANSLATE("Blackness")) == 0)
622 fSettings.SetModuleName("");
623 else
624 fSettings.SetModuleName(item->Text());
626 SaveState();
627 _CloseSaver();
628 _OpenSaver();
629 fSettings.Save();
630 break;
633 case kMsgTestSaver:
635 SaveState();
636 fSettings.Save();
638 _CloseSaver();
640 be_roster->StartWatching(BMessenger(this, Looper()),
641 B_REQUEST_QUIT);
642 BMessage message(kMsgTestSaver);
643 if (be_roster->Launch(SCREEN_BLANKER_SIG, &message,
644 &fScreenSaverTestTeam) == B_OK) {
645 break;
648 // Try really hard to launch it. It's very likely that this fails
649 // when we run from the CD, and there is only an incomplete mime
650 // database for example...
651 BPath path;
652 if (find_directory(B_SYSTEM_BIN_DIRECTORY, &path) != B_OK
653 || path.Append("screen_blanker") != B_OK) {
654 path.SetTo("/bin/screen_blanker");
657 BEntry entry(path.Path());
658 entry_ref ref;
659 if (entry.GetRef(&ref) == B_OK) {
660 be_roster->Launch(&ref, &message,
661 &fScreenSaverTestTeam);
663 break;
666 case B_SOME_APP_QUIT:
668 team_id team;
669 if (message->FindInt32("be:team", &team) == B_OK
670 && team == fScreenSaverTestTeam) {
671 be_roster->StopWatching(this);
672 _OpenSaver();
674 break;
677 default:
678 BView::MessageReceived(message);
683 void
684 ModulesView::SaveState()
686 BScreenSaver* saver = ScreenSaver();
687 if (saver == NULL)
688 return;
690 BMessage state;
691 if (saver->SaveState(&state) == B_OK)
692 fSettings.SetModuleState(fCurrentName.String(), &state);
696 void
697 ModulesView::EmptyScreenSaverList()
699 fScreenSaversListView->DeselectAll();
700 while (BListItem* item = fScreenSaversListView->RemoveItem((int32)0))
701 delete item;
705 void
706 ModulesView::PopulateScreenSaverList()
708 // Blackness is a built-in screen saver
709 ScreenSaverItem* defaultItem
710 = new ScreenSaverItem(B_TRANSLATE("Blackness"), "");
711 fScreenSaversListView->AddItem(defaultItem);
713 // Iterate over add-on directories, and add their files to the list view
715 directory_which which[] = {
716 B_USER_NONPACKAGED_ADDONS_DIRECTORY,
717 B_USER_ADDONS_DIRECTORY,
718 B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
719 B_SYSTEM_ADDONS_DIRECTORY,
721 ScreenSaverItem* selectedItem = NULL;
723 for (uint32 i = 0; i < sizeof(which) / sizeof(which[0]); i++) {
724 BPath basePath;
725 if (find_directory(which[i], &basePath) != B_OK)
726 continue;
727 else if (basePath.Append("Screen Savers", true) != B_OK)
728 continue;
730 BDirectory dir(basePath.Path());
731 BEntry entry;
732 while (dir.GetNextEntry(&entry, true) == B_OK) {
733 char name[B_FILE_NAME_LENGTH];
734 if (entry.GetName(name) != B_OK)
735 continue;
737 BPath path(basePath);
738 if (path.Append(name) != B_OK)
739 continue;
741 ScreenSaverItem* item = new ScreenSaverItem(name, path.Path());
742 fScreenSaversListView->AddItem(item);
744 if (selectedItem != NULL)
745 continue;
747 if (strcmp(fSettings.ModuleName(), item->Text()) == 0)
748 selectedItem = item;
752 fScreenSaversListView->SortItems(_CompareScreenSaverItems);
753 if (selectedItem == NULL)
754 selectedItem = defaultItem;
756 fScreenSaversListView->Select(fScreenSaversListView->IndexOf(selectedItem));
757 fScreenSaversListView->ScrollToSelection();
761 //! Sorting function for ScreenSaverItems
763 ModulesView::_CompareScreenSaverItems(const void* left, const void* right)
765 ScreenSaverItem* leftItem = *(ScreenSaverItem **)left;
766 ScreenSaverItem* rightItem = *(ScreenSaverItem **)right;
768 return strcasecmp(leftItem->Text(), rightItem->Text());
772 BScreenSaver*
773 ModulesView::ScreenSaver()
775 if (fSaverRunner != NULL)
776 return fSaverRunner->ScreenSaver();
778 return NULL;
782 void
783 ModulesView::_CloseSaver()
785 // remove old screen saver preview & config
787 BScreenSaver* saver = ScreenSaver();
788 BView* view = fPreviewView->RemovePreview();
789 if (fSettingsView != NULL)
790 fSettingsBox->RemoveChild(fSettingsView);
792 if (fSaverRunner != NULL)
793 fSaverRunner->Quit();
795 if (saver != NULL)
796 saver->StopConfig();
798 delete view;
799 delete fSettingsView;
800 delete fSaverRunner;
801 // the saver runner also unloads the add-on, so it must
802 // be deleted last
804 fSettingsView = NULL;
805 fSaverRunner = NULL;
809 void
810 ModulesView::_OpenSaver()
812 // create new screen saver preview & config
814 BView* view = fPreviewView->AddPreview();
815 fCurrentName = fSettings.ModuleName();
816 fSaverRunner = new ScreenSaverRunner(view->Window(), view, fSettings);
818 #ifdef __HAIKU__
819 BRect rect = fSettingsBox->InnerFrame().InsetByCopy(4, 4);
820 #else
821 BRect rect = fSettingsBox->Bounds().InsetByCopy(4, 4);
822 rect.top += 14;
823 #endif
824 fSettingsView = new BView(rect, "SettingsView", B_FOLLOW_ALL, B_WILL_DRAW);
826 fSettingsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
827 fSettingsBox->AddChild(fSettingsView);
829 BScreenSaver* saver = ScreenSaver();
830 if (saver != NULL && fSettingsView != NULL) {
831 saver->StartConfig(fSettingsView);
832 if (saver->StartSaver(view, true) == B_OK) {
833 fPreviewView->HideNoPreview();
834 fSaverRunner->Run();
835 } else
836 fPreviewView->ShowNoPreview();
837 } else {
838 // Failed to load OR this is the "Darkness" screensaver. Show a black
839 // preview (this is what will happen in both cases when screen_blanker
840 // runs).
841 fPreviewView->HideNoPreview();
844 if (fSettingsView->ChildAt(0) == NULL) {
845 // There are no settings at all, we add the module name here to
846 // let it look a bit better at least.
847 BPrivate::BuildScreenSaverDefaultSettingsView(fSettingsView,
848 fSettings.ModuleName()[0] ? fSettings.ModuleName()
849 : B_TRANSLATE("Blackness"),
850 saver != NULL || !fSettings.ModuleName()[0]
851 ? B_TRANSLATE("No options available")
852 : B_TRANSLATE("Could not load screen saver"));
857 // #pragma mark - TabView
860 TabView::TabView()
862 BTabView("tab_view", B_WIDTH_FROM_LABEL)
867 void
868 TabView::MouseDown(BPoint where)
870 BTab* fadeTab = TabAt(0);
871 BRect fadeTabFrame(TabFrame(0));
872 BTab* modulesTab = TabAt(1);
873 BRect modulesTabFrame(TabFrame(1));
874 ModulesView* modulesView = dynamic_cast<ModulesView*>(modulesTab->View());
876 if (fadeTab != NULL && Selection() != 0 && fadeTabFrame.Contains(where)
877 && modulesView != NULL) {
878 // clicked on the fade tab
879 modulesView->SaveState();
880 modulesView->_CloseSaver();
881 } else if (modulesTab != NULL && Selection() != 1
882 && modulesTabFrame.Contains(where) && modulesView != NULL) {
883 // clicked on the modules tab
884 BMessage message(kMsgSaverSelected);
885 modulesView->MessageReceived(&message);
888 BTabView::MouseDown(where);
892 // #pragma mark - ScreenSaverWindow
895 ScreenSaverWindow::ScreenSaverWindow()
897 BWindow(BRect(50, 50, 496, 375),
898 B_TRANSLATE_SYSTEM_NAME("ScreenSaver"), B_TITLED_WINDOW,
899 B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS)
901 fSettings.Load();
903 fMinWidth = ceilf(std::max(446.0f,
904 be_control_look->DefaultItemSpacing() * 44.6f));
906 font_height fontHeight;
907 be_plain_font->GetHeight(&fontHeight);
908 float textHeight = ceilf(fontHeight.ascent + fontHeight.descent);
910 fMinHeight = ceilf(std::max(325.0f, textHeight * 28));
912 // Create the password editing window
913 fPasswordWindow = new PasswordWindow(fSettings);
914 fPasswordWindow->Run();
916 // Create the tab view
917 fTabView = new TabView();
918 fTabView->SetBorder(B_NO_BORDER);
920 // Create the controls inside the tabs
921 fFadeView = new FadeView(B_TRANSLATE("General"), fSettings);
922 fModulesView = new ModulesView(B_TRANSLATE("Screensavers"), fSettings);
924 fTabView->AddTab(fFadeView);
925 fTabView->AddTab(fModulesView);
927 // Create the topmost background view
928 BView* topView = new BView("topView", B_WILL_DRAW);
929 topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
930 topView->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
931 B_ALIGN_USE_FULL_HEIGHT));
932 topView->SetExplicitMinSize(BSize(fMinWidth, fMinHeight));
933 BLayoutBuilder::Group<>(topView, B_VERTICAL)
934 .SetInsets(0, B_USE_SMALL_SPACING, 0, 0)
935 .Add(fTabView)
936 .End();
938 SetLayout(new BGroupLayout(B_VERTICAL));
939 GetLayout()->AddView(topView);
941 fTabView->Select(fSettings.WindowTab());
943 if (fSettings.WindowFrame().left > 0 && fSettings.WindowFrame().top > 0)
944 MoveTo(fSettings.WindowFrame().left, fSettings.WindowFrame().top);
946 if (fSettings.WindowFrame().Width() > 0
947 && fSettings.WindowFrame().Height() > 0) {
948 ResizeTo(fSettings.WindowFrame().Width(),
949 fSettings.WindowFrame().Height());
954 ScreenSaverWindow::~ScreenSaverWindow()
956 Hide();
957 fFadeView->UpdateStatus();
958 fSettings.SetWindowTab(fTabView->Selection());
960 delete fTabView->RemoveTab(1);
961 // We delete this here in order to make sure the module view saves its
962 // state while the window is still intact.
964 fSettings.Save();
968 void
969 ScreenSaverWindow::MessageReceived(BMessage* message)
971 switch (message->what) {
972 case kMsgChangePassword:
973 fPasswordWindow->CenterIn(Frame());
974 fPasswordWindow->Show();
975 break;
977 case kMsgUpdateList:
978 fModulesView->EmptyScreenSaverList();
979 fModulesView->PopulateScreenSaverList();
980 break;
982 default:
983 BWindow::MessageReceived(message);
988 void
989 ScreenSaverWindow::ScreenChanged(BRect frame, color_space colorSpace)
991 fFadeView->UpdateTurnOffScreen();
995 bool
996 ScreenSaverWindow::QuitRequested()
998 be_app->PostMessage(B_QUIT_REQUESTED);
999 return true;