From 29e8a73a07ad05379041635507d5a55c65c8d71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 25 Mar 2006 20:10:34 +0000 Subject: [PATCH] * No longer ignores the screen refresh limits from the driver. * Now builds under R5, but looks ugly (for testing only). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16877 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/preferences/screen/Jamfile | 1 + src/preferences/screen/RefreshWindow.cpp | 56 +++-- src/preferences/screen/RefreshWindow.h | 37 ++-- src/preferences/screen/ScreenMode.cpp | 25 ++- src/preferences/screen/ScreenMode.h | 8 +- src/preferences/screen/ScreenWindow.cpp | 249 +++++++++++------------ 6 files changed, 197 insertions(+), 179 deletions(-) diff --git a/src/preferences/screen/Jamfile b/src/preferences/screen/Jamfile index 9245c018f5..3a4fcf5947 100644 --- a/src/preferences/screen/Jamfile +++ b/src/preferences/screen/Jamfile @@ -1,5 +1,6 @@ SubDir HAIKU_TOP src preferences screen ; +SetSubDirSupportedPlatformsBeOSCompatible ; AddSubDirSupportedPlatforms libbe_test ; UsePrivateHeaders [ FDirName graphics radeon ] ; diff --git a/src/preferences/screen/RefreshWindow.cpp b/src/preferences/screen/RefreshWindow.cpp index 6e16eff475..ae21b1b16a 100644 --- a/src/preferences/screen/RefreshWindow.cpp +++ b/src/preferences/screen/RefreshWindow.cpp @@ -1,48 +1,64 @@ -#include -#include -#include -#include -#include +/* + * Copyright 2001-2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Rafael Romo + * Stefano Ceccherini (burton666@libero.it) + * Axel Dörfler, axeld@pinc-software.de + */ + #include "RefreshWindow.h" #include "RefreshView.h" #include "RefreshSlider.h" #include "Constants.h" -RefreshWindow::RefreshWindow(BRect frame, int32 value) - : BWindow(frame, "Refresh Rate", B_MODAL_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES) +#include +#include +#include +#include +#include + + +RefreshWindow::RefreshWindow(BRect frame, float current, float min, float max) + : BWindow(frame, "Refresh Rate", B_MODAL_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, + B_ALL_WORKSPACES) { BRect bounds(Bounds()); bounds.InsetBy(-1, -1); - + fRefreshView = new RefreshView(bounds, "RefreshView"); AddChild(fRefreshView); - + + min = ceilf(min); + max = floorf(max); + BRect sliderRect; BString maxRefresh; - maxRefresh << gMaxRefresh; + maxRefresh << (uint32)min; BString minRefresh; - minRefresh << gMinRefresh; - + minRefresh << (uint32)max; + sliderRect.Set(10.0, 35.0, 299.0, 60.0); - + fRefreshSlider = new RefreshSlider(sliderRect); - + fRefreshSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); - fRefreshSlider->SetHashMarkCount((gMaxRefresh-gMinRefresh)/5+1); + fRefreshSlider->SetHashMarkCount(uint32(max - min) / 5 + 1); fRefreshSlider->SetLimitLabels(minRefresh.String(), maxRefresh.String()); fRefreshSlider->SetKeyIncrementValue(1); - fRefreshSlider->SetValue(value); + fRefreshSlider->SetValue(rint(current * 10)); fRefreshSlider->SetSnoozeAmount(1); fRefreshSlider->SetModificationMessage(new BMessage(SLIDER_MODIFICATION_MSG)); - + fRefreshView->AddChild(fRefreshSlider); - + BRect ButtonRect(219.0, 97.0, 230.0, 120.0); - + fDoneButton = new BButton(ButtonRect, "DoneButton", "Done", new BMessage(BUTTON_DONE_MSG)); - + fDoneButton->ResizeToPreferred(); fDoneButton->MakeDefault(true); diff --git a/src/preferences/screen/RefreshWindow.h b/src/preferences/screen/RefreshWindow.h index 49ecf09853..67e2647598 100644 --- a/src/preferences/screen/RefreshWindow.h +++ b/src/preferences/screen/RefreshWindow.h @@ -1,24 +1,33 @@ -#ifndef REFRESHWINDOW_H -#define REFRESHWINDOW_H +/* + * Copyright 2001-2006, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Rafael Romo + * Stefano Ceccherini (burton666@libero.it) + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef REFRESH_WINDOW_H +#define REFRESH_WINDOW_H + #include #include "RefreshView.h" #include "RefreshSlider.h" -class RefreshWindow : public BWindow -{ +class RefreshWindow : public BWindow { + public: + RefreshWindow(BRect frame, float current, float min, float max); -public: - RefreshWindow(BRect frame, int32 value); - virtual void MessageReceived(BMessage *message); - virtual void WindowActivated(bool active); + virtual void MessageReceived(BMessage *message); + virtual void WindowActivated(bool active); -private: - RefreshView *fRefreshView; - RefreshSlider *fRefreshSlider; - BButton *fDoneButton; - BButton *fCancelButton; + private: + RefreshView *fRefreshView; + RefreshSlider *fRefreshSlider; + BButton *fDoneButton; + BButton *fCancelButton; }; -#endif +#endif // REFRESH_WINDOW_H diff --git a/src/preferences/screen/ScreenMode.cpp b/src/preferences/screen/ScreenMode.cpp index d0ba4ad6b6..66c3335b6d 100644 --- a/src/preferences/screen/ScreenMode.cpp +++ b/src/preferences/screen/ScreenMode.cpp @@ -173,7 +173,7 @@ ScreenMode::~ScreenMode() status_t -ScreenMode::Set(screen_mode& mode) +ScreenMode::Set(const screen_mode& mode) { if (!fUpdatedMode) UpdateOriginalMode(); @@ -243,16 +243,29 @@ ScreenMode::UpdateOriginalMode() bool -ScreenMode::SupportsColorSpace(screen_mode& mode, color_space space) +ScreenMode::SupportsColorSpace(const screen_mode& mode, color_space space) { - return false; + return true; } status_t -ScreenMode::GetRefreshLimits(screen_mode& mode, float& min, float& max) +ScreenMode::GetRefreshLimits(const screen_mode& mode, float& min, float& max) { - return B_ERROR; + uint32 minClock, maxClock; + display_mode displayMode; + if (!GetDisplayMode(mode, displayMode)) + return B_ERROR; + + BScreen screen(fWindow); + if (screen.GetPixelClockLimits(&displayMode, &minClock, &maxClock) < B_OK) + return B_ERROR; + + uint32 total = displayMode.timing.h_total * displayMode.timing.v_total; + min = minClock * 1000.0 / total; + max = maxClock * 1000.0 / total; + + return B_OK; } @@ -279,7 +292,7 @@ ScreenMode::CountModes() bool -ScreenMode::GetDisplayMode(screen_mode& mode, display_mode& displayMode) +ScreenMode::GetDisplayMode(const screen_mode& mode, display_mode& displayMode) { uint16 virtualWidth, virtualHeight; int32 bestIndex = -1; diff --git a/src/preferences/screen/ScreenMode.h b/src/preferences/screen/ScreenMode.h index 1a9c54d6c3..cfa150d19c 100644 --- a/src/preferences/screen/ScreenMode.h +++ b/src/preferences/screen/ScreenMode.h @@ -41,20 +41,20 @@ class ScreenMode { ScreenMode(BWindow* window); ~ScreenMode(); - status_t Set(screen_mode& mode); + status_t Set(const screen_mode& mode); status_t Get(screen_mode& mode); status_t Revert(); void UpdateOriginalMode(); - bool SupportsColorSpace(screen_mode& mode, color_space space); - status_t GetRefreshLimits(screen_mode& mode, float& min, float& max); + bool SupportsColorSpace(const screen_mode& mode, color_space space); + status_t GetRefreshLimits(const screen_mode& mode, float& min, float& max); screen_mode ModeAt(int32 index); int32 CountModes(); private: - bool GetDisplayMode(screen_mode& mode, display_mode& displayMode); + bool GetDisplayMode(const screen_mode& mode, display_mode& displayMode); BWindow* fWindow; display_mode* fModeList; diff --git a/src/preferences/screen/ScreenWindow.cpp b/src/preferences/screen/ScreenWindow.cpp index c1166c6e13..608713202c 100644 --- a/src/preferences/screen/ScreenWindow.cpp +++ b/src/preferences/screen/ScreenWindow.cpp @@ -52,11 +52,6 @@ #include "multimon.h" // the usual: DANGER WILL, ROBINSON! -#define USE_FIXED_REFRESH - // define to use fixed standard refresh rates - // undefine to get standard refresh rates from driver - - const char* kBackgroundsSignature = "application/x-vnd.haiku-backgrounds"; // list of officially supported colour spaces @@ -76,7 +71,6 @@ static const int32 kColorSpaceCount = sizeof(kColorSpaces) / sizeof(kColorSpaces static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 }; static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); - // list of combine modes static const struct { combine_mode mode; @@ -88,6 +82,13 @@ static const struct { }; static const int32 kCombineModeCount = sizeof(kCombineModes) / sizeof(kCombineModes[0]); +enum { + SHOW_COMBINE_FIELD = 0x01, + SHOW_SWAP_FIELD = 0x02, + SHOW_LAPTOP_PANEL_FIELD = 0x04, + SHOW_TV_STANDARD_FIELD = 0x08, +}; + static BString tv_standard_to_string(uint32 mode) @@ -146,12 +147,59 @@ screen_errors(status_t status) } } -enum { - SHOW_COMBINE_FIELD = 0x01, - SHOW_SWAP_FIELD = 0x02, - SHOW_LAPTOP_PANEL_FIELD = 0x04, - SHOW_TV_STANDARD_FIELD = 0x08, -}; + +static float +max_label_width(BMenuField* control, float widestLabel) +{ + float labelWidth = control->StringWidth(control->Label()); + if (widestLabel < labelWidth) + return labelWidth; + return widestLabel; +} + + +static BRect +stack_and_align_menu_fields(const BList& menuFields) +{ + float widestLabel = 0.0; + int32 count = menuFields.CountItems(); + for (int32 i = 0; i < count; i++) { + BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); + widestLabel = max_label_width(menuField, widestLabel); + } + + // add some room (but only if there is text at all) + if (widestLabel > 0.0) + widestLabel += 5.0; + + // make all controls the same width + float widestField = 0.0; + for (int32 i = 0; i < count; i++) { + BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); + menuField->SetAlignment(B_ALIGN_RIGHT); + menuField->SetDivider(widestLabel); + menuField->ResizeToPreferred(); + widestField = max_c(menuField->Bounds().Width(), widestField); + } + + // layout controls under each other, resize all to size + // of largest of them (they could still have different + // heights though) + BMenuField* topMenuField = (BMenuField*)menuFields.FirstItem(); + BPoint leftTop = topMenuField->Frame().LeftTop(); + BRect frame = topMenuField->Frame(); + + for (int32 i = 0; i < count; i++) { + BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); + menuField->MoveTo(leftTop); + float height = menuField->Bounds().Height(); + menuField->ResizeTo(widestField, height); + frame = frame | menuField->Frame(); + leftTop.y += height + 5.0; + } + + return frame; +} // #pragma mark - @@ -246,7 +294,7 @@ ScreenWindow::ScreenWindow(ScreenSettings *settings) fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); } - BRect rect(0.0, 0.0, 30.0, 15.0); + BRect rect(0.0, 0.0, 200.0, 15.0); // fResolutionField needs to be at the correct // left-top offset, because all other menu fields // will be layouted relative to it @@ -271,22 +319,36 @@ ScreenWindow::ScreenWindow(ScreenSettings *settings) fRefreshMenu = new BPopUpMenu("refresh rate", true, true); -#ifdef USE_FIXED_REFRESH - for (int32 i = 0; i < kRefreshRateCount; ++i) { + BMessage *message; + + float min, max; + if (fScreenMode.GetRefreshLimits(fActive, min, max) && min == max) { + // This is a special case for drivers that only support a single + // frequency, like the VESA driver BString name; - name << kRefreshRates[i] << " Hz"; + name << min << " Hz"; - BMessage *message = new BMessage(POP_REFRESH_MSG); - message->AddFloat("refresh", kRefreshRates[i]); + message = new BMessage(POP_REFRESH_MSG); + message->AddFloat("refresh", min); - fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); + fRefreshMenu->AddItem(item = new BMenuItem(name.String(), message)); + item->SetEnabled(false); + } else { + for (int32 i = 0; i < kRefreshRateCount; ++i) { + BString name; + name << kRefreshRates[i] << " Hz"; + + message = new BMessage(POP_REFRESH_MSG); + message->AddFloat("refresh", kRefreshRates[i]); + + fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); + } + + message = new BMessage(POP_OTHER_REFRESH_MSG); + + fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message); + fRefreshMenu->AddItem(fOtherRefresh); } -#endif - - BMessage *message = new BMessage(POP_OTHER_REFRESH_MSG); - - fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message); - fRefreshMenu->AddItem(fOtherRefresh); fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:", fRefreshMenu, true); fControlsBox->AddChild(fRefreshField); @@ -497,67 +559,26 @@ ScreenWindow::CheckColorMenu() } -/** Enable/disable refresh options according to current mode. - * Only needed when USE_FIXED_REFRESH is not defined. - */ +/** Enable/disable refresh options according to current mode. */ void ScreenWindow::CheckRefreshMenu() -{ -#ifndef USE_FIXED_REFRESH - // ToDo: does currently not compile! - for (int32 i = fRefreshMenu->CountItems() - 2; i >= 0; --i) { - delete fRefreshMenu->RemoveItem(i); +{ + float min, max; + if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) + return; + + for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { + BMenuItem* item = fRefreshMenu->ItemAt(i); + BMessage* message = item->Message(); + float refresh; + if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) + item->SetEnabled(refresh >= min && refresh <= max); } - - for (int32 i = 0; i < fModeListCount; ++i) { - if (virtualWidth == fModeList[i].virtual_width - && virtualHeight == fModeList[i].virtual_height - && combine == get_combine_mode(&fModeList[i])) { - BString name; - BMenuItem *item; - - int32 refresh10 = get_refresh10(fModeList[i]); - refresh10_to_string(name, refresh10); - - item = fRefreshMenu->FindItem(name.String()); - if (item == NULL) { - BMessage *msg = new BMessage(POP_REFRESH_MSG); - msg->AddFloat("refresh", refresh); - - fRefreshMenu->AddItem(new BMenuItem(name.String(), msg), - fRefreshMenu->CountItems() - 1); - } - } - } -#endif - - // TBD: some drivers lack many refresh rates; still, they - // can be used by generating the mode manually -/* - for( i = 0; i < sizeof( refresh_list ) / sizeof( refresh_list[0] ); ++i ) { - BMenuItem *item; - bool supported = false; - - for( j = 0; j < fModeListCount; ++j ) { - if( width == fModeList[j].virtual_width && - height == fModeList[j].virtual_height && - refresh_list[i].refresh * 10 == getModeRefresh10( &fModeList[j] )) - { - supported = true; - break; - } - } - - item = fRefreshMenu->ItemAt( i ); - if( item ) - item->SetEnabled( supported ); - } -*/ } -/** activate appropriate menu item according to selected refresh rate */ +/** Activate appropriate menu item according to selected refresh rate */ void ScreenWindow::UpdateRefreshControl() @@ -569,6 +590,7 @@ ScreenWindow::UpdateRefreshControl() if (item) { if (!item->IsMarked()) item->SetMarked(true); + // "Other…" items only contains a refresh rate when active fOtherRefresh->SetLabel("Other…"); return; @@ -788,13 +810,20 @@ ScreenWindow::MessageReceived(BMessage* message) case POP_OTHER_REFRESH_MSG: { - // make sure menu shows something usefull + // make sure menu shows something useful UpdateRefreshControl(); + float min = 0, max = 999; + fScreenMode.GetRefreshLimits(fSelected, min, max); + if (min < gMinRefresh) + min = gMinRefresh; + if (max > gMaxRefresh) + max = gMaxRefresh; + BRect frame(Frame()); RefreshWindow *fRefreshWindow = new RefreshWindow(BRect(frame.left + 201.0, frame.top + 34.0, frame.left + 509.0, frame.top + 169.0), - int32(fSelected.refresh * 10)); + fSelected.refresh, min, max); fRefreshWindow->Show(); break; } @@ -988,7 +1017,11 @@ ScreenWindow::LayoutControls(uint32 flags) + backgroundsButtonHeight + 20.0; +#ifdef __HAIKU__ fScreenBox->MoveTo(10.0, 10.0 + fControlsBox->TopBorderOffset()); +#else + fScreenBox->MoveTo(10.0, 10.0 + 3); +#endif fScreenBox->ResizeTo(screenBoxWidth, screenBoxHeight); float leftOffset = 10.0; @@ -1046,60 +1079,6 @@ ScreenWindow::LayoutControls(uint32 flags) } -static float -max_label_width(BMenuField* control, float widestLabel) -{ - float labelWidth = control->StringWidth(control->Label()); - if (widestLabel < labelWidth) - return labelWidth; - return widestLabel; -} - - -static BRect -stack_and_align_menu_fields(const BList& menuFields) -{ - float widestLabel = 0.0; - int32 count = menuFields.CountItems(); - for (int32 i = 0; i < count; i++) { - BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); - widestLabel = max_label_width(menuField, widestLabel); - } - - // add some room (but only if there is text at all) - if (widestLabel > 0.0) - widestLabel += 5.0; - - // make all controls the same width - float widestField = 0.0; - for (int32 i = 0; i < count; i++) { - BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); - menuField->SetAlignment(B_ALIGN_RIGHT); - menuField->SetDivider(widestLabel); - menuField->ResizeToPreferred(); - widestField = max_c(menuField->Bounds().Width(), widestField); - } - - // layout controls under each other, resize all to size - // of largest of them (they could still have different - // heights though) - BMenuField* topMenuField = (BMenuField*)menuFields.FirstItem(); - BPoint leftTop = topMenuField->Frame().LeftTop(); - BRect frame = topMenuField->Frame(); - - for (int32 i = 0; i < count; i++) { - BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); - menuField->MoveTo(leftTop); - float height = menuField->Bounds().Height(); - menuField->ResizeTo(widestField, height); - frame = frame | menuField->Frame(); - leftTop.y += height + 5.0; - } - - return frame; -} - - BRect ScreenWindow::LayoutMenuFields(uint32 flags, bool sideBySide) {