* 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
This commit is contained in:
Axel Dörfler
2006-03-25 20:10:34 +00:00
parent 7a3806ce87
commit 29e8a73a07
6 changed files with 197 additions and 179 deletions
+1
View File
@@ -1,5 +1,6 @@
SubDir HAIKU_TOP src preferences screen ; SubDir HAIKU_TOP src preferences screen ;
SetSubDirSupportedPlatformsBeOSCompatible ;
AddSubDirSupportedPlatforms libbe_test ; AddSubDirSupportedPlatforms libbe_test ;
UsePrivateHeaders [ FDirName graphics radeon ] ; UsePrivateHeaders [ FDirName graphics radeon ] ;
+36 -20
View File
@@ -1,48 +1,64 @@
#include <Alert.h> /*
#include <Application.h> * Copyright 2001-2006, Haiku.
#include <Button.h> * Distributed under the terms of the MIT License.
#include <String.h> *
#include <Window.h> * Authors:
* Rafael Romo
* Stefano Ceccherini ([email protected])
* Axel Dörfler, [email protected]
*/
#include "RefreshWindow.h" #include "RefreshWindow.h"
#include "RefreshView.h" #include "RefreshView.h"
#include "RefreshSlider.h" #include "RefreshSlider.h"
#include "Constants.h" #include "Constants.h"
RefreshWindow::RefreshWindow(BRect frame, int32 value) #include <Alert.h>
: BWindow(frame, "Refresh Rate", B_MODAL_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES) #include <Application.h>
#include <Button.h>
#include <String.h>
#include <Window.h>
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()); BRect bounds(Bounds());
bounds.InsetBy(-1, -1); bounds.InsetBy(-1, -1);
fRefreshView = new RefreshView(bounds, "RefreshView"); fRefreshView = new RefreshView(bounds, "RefreshView");
AddChild(fRefreshView); AddChild(fRefreshView);
min = ceilf(min);
max = floorf(max);
BRect sliderRect; BRect sliderRect;
BString maxRefresh; BString maxRefresh;
maxRefresh << gMaxRefresh; maxRefresh << (uint32)min;
BString minRefresh; BString minRefresh;
minRefresh << gMinRefresh; minRefresh << (uint32)max;
sliderRect.Set(10.0, 35.0, 299.0, 60.0); sliderRect.Set(10.0, 35.0, 299.0, 60.0);
fRefreshSlider = new RefreshSlider(sliderRect); fRefreshSlider = new RefreshSlider(sliderRect);
fRefreshSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 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->SetLimitLabels(minRefresh.String(), maxRefresh.String());
fRefreshSlider->SetKeyIncrementValue(1); fRefreshSlider->SetKeyIncrementValue(1);
fRefreshSlider->SetValue(value); fRefreshSlider->SetValue(rint(current * 10));
fRefreshSlider->SetSnoozeAmount(1); fRefreshSlider->SetSnoozeAmount(1);
fRefreshSlider->SetModificationMessage(new BMessage(SLIDER_MODIFICATION_MSG)); fRefreshSlider->SetModificationMessage(new BMessage(SLIDER_MODIFICATION_MSG));
fRefreshView->AddChild(fRefreshSlider); fRefreshView->AddChild(fRefreshSlider);
BRect ButtonRect(219.0, 97.0, 230.0, 120.0); BRect ButtonRect(219.0, 97.0, 230.0, 120.0);
fDoneButton = new BButton(ButtonRect, "DoneButton", "Done", fDoneButton = new BButton(ButtonRect, "DoneButton", "Done",
new BMessage(BUTTON_DONE_MSG)); new BMessage(BUTTON_DONE_MSG));
fDoneButton->ResizeToPreferred(); fDoneButton->ResizeToPreferred();
fDoneButton->MakeDefault(true); fDoneButton->MakeDefault(true);
+23 -14
View File
@@ -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 ([email protected])
* Axel Dörfler, [email protected]
*/
#ifndef REFRESH_WINDOW_H
#define REFRESH_WINDOW_H
#include <Window.h> #include <Window.h>
#include "RefreshView.h" #include "RefreshView.h"
#include "RefreshSlider.h" #include "RefreshSlider.h"
class RefreshWindow : public BWindow class RefreshWindow : public BWindow {
{ public:
RefreshWindow(BRect frame, float current, float min, float max);
public: virtual void MessageReceived(BMessage *message);
RefreshWindow(BRect frame, int32 value); virtual void WindowActivated(bool active);
virtual void MessageReceived(BMessage *message);
virtual void WindowActivated(bool active);
private: private:
RefreshView *fRefreshView; RefreshView *fRefreshView;
RefreshSlider *fRefreshSlider; RefreshSlider *fRefreshSlider;
BButton *fDoneButton; BButton *fDoneButton;
BButton *fCancelButton; BButton *fCancelButton;
}; };
#endif #endif // REFRESH_WINDOW_H
+19 -6
View File
@@ -173,7 +173,7 @@ ScreenMode::~ScreenMode()
status_t status_t
ScreenMode::Set(screen_mode& mode) ScreenMode::Set(const screen_mode& mode)
{ {
if (!fUpdatedMode) if (!fUpdatedMode)
UpdateOriginalMode(); UpdateOriginalMode();
@@ -243,16 +243,29 @@ ScreenMode::UpdateOriginalMode()
bool bool
ScreenMode::SupportsColorSpace(screen_mode& mode, color_space space) ScreenMode::SupportsColorSpace(const screen_mode& mode, color_space space)
{ {
return false; return true;
} }
status_t 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 bool
ScreenMode::GetDisplayMode(screen_mode& mode, display_mode& displayMode) ScreenMode::GetDisplayMode(const screen_mode& mode, display_mode& displayMode)
{ {
uint16 virtualWidth, virtualHeight; uint16 virtualWidth, virtualHeight;
int32 bestIndex = -1; int32 bestIndex = -1;
+4 -4
View File
@@ -41,20 +41,20 @@ class ScreenMode {
ScreenMode(BWindow* window); ScreenMode(BWindow* window);
~ScreenMode(); ~ScreenMode();
status_t Set(screen_mode& mode); status_t Set(const screen_mode& mode);
status_t Get(screen_mode& mode); status_t Get(screen_mode& mode);
status_t Revert(); status_t Revert();
void UpdateOriginalMode(); void UpdateOriginalMode();
bool SupportsColorSpace(screen_mode& mode, color_space space); bool SupportsColorSpace(const screen_mode& mode, color_space space);
status_t GetRefreshLimits(screen_mode& mode, float& min, float& max); status_t GetRefreshLimits(const screen_mode& mode, float& min, float& max);
screen_mode ModeAt(int32 index); screen_mode ModeAt(int32 index);
int32 CountModes(); int32 CountModes();
private: private:
bool GetDisplayMode(screen_mode& mode, display_mode& displayMode); bool GetDisplayMode(const screen_mode& mode, display_mode& displayMode);
BWindow* fWindow; BWindow* fWindow;
display_mode* fModeList; display_mode* fModeList;
+114 -135
View File
@@ -52,11 +52,6 @@
#include "multimon.h" // the usual: DANGER WILL, ROBINSON! #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"; const char* kBackgroundsSignature = "application/x-vnd.haiku-backgrounds";
// list of officially supported colour spaces // 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 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 };
static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]);
// list of combine modes // list of combine modes
static const struct { static const struct {
combine_mode mode; combine_mode mode;
@@ -88,6 +82,13 @@ static const struct {
}; };
static const int32 kCombineModeCount = sizeof(kCombineModes) / sizeof(kCombineModes[0]); 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 static BString
tv_standard_to_string(uint32 mode) tv_standard_to_string(uint32 mode)
@@ -146,12 +147,59 @@ screen_errors(status_t status)
} }
} }
enum {
SHOW_COMBINE_FIELD = 0x01, static float
SHOW_SWAP_FIELD = 0x02, max_label_width(BMenuField* control, float widestLabel)
SHOW_LAPTOP_PANEL_FIELD = 0x04, {
SHOW_TV_STANDARD_FIELD = 0x08, 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 - // #pragma mark -
@@ -246,7 +294,7 @@ ScreenWindow::ScreenWindow(ScreenSettings *settings)
fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 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 // fResolutionField needs to be at the correct
// left-top offset, because all other menu fields // left-top offset, because all other menu fields
// will be layouted relative to it // will be layouted relative to it
@@ -271,22 +319,36 @@ ScreenWindow::ScreenWindow(ScreenSettings *settings)
fRefreshMenu = new BPopUpMenu("refresh rate", true, true); fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
#ifdef USE_FIXED_REFRESH BMessage *message;
for (int32 i = 0; i < kRefreshRateCount; ++i) {
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; BString name;
name << kRefreshRates[i] << " Hz"; name << min << " Hz";
BMessage *message = new BMessage(POP_REFRESH_MSG); message = new BMessage(POP_REFRESH_MSG);
message->AddFloat("refresh", kRefreshRates[i]); 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); fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:", fRefreshMenu, true);
fControlsBox->AddChild(fRefreshField); fControlsBox->AddChild(fRefreshField);
@@ -497,67 +559,26 @@ ScreenWindow::CheckColorMenu()
} }
/** Enable/disable refresh options according to current mode. /** Enable/disable refresh options according to current mode. */
* Only needed when USE_FIXED_REFRESH is not defined.
*/
void void
ScreenWindow::CheckRefreshMenu() ScreenWindow::CheckRefreshMenu()
{ {
#ifndef USE_FIXED_REFRESH float min, max;
// ToDo: does currently not compile! if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max)
for (int32 i = fRefreshMenu->CountItems() - 2; i >= 0; --i) { return;
delete fRefreshMenu->RemoveItem(i);
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 void
ScreenWindow::UpdateRefreshControl() ScreenWindow::UpdateRefreshControl()
@@ -569,6 +590,7 @@ ScreenWindow::UpdateRefreshControl()
if (item) { if (item) {
if (!item->IsMarked()) if (!item->IsMarked())
item->SetMarked(true); item->SetMarked(true);
// "Other…" items only contains a refresh rate when active // "Other…" items only contains a refresh rate when active
fOtherRefresh->SetLabel("Other…"); fOtherRefresh->SetLabel("Other…");
return; return;
@@ -788,13 +810,20 @@ ScreenWindow::MessageReceived(BMessage* message)
case POP_OTHER_REFRESH_MSG: case POP_OTHER_REFRESH_MSG:
{ {
// make sure menu shows something usefull // make sure menu shows something useful
UpdateRefreshControl(); UpdateRefreshControl();
float min = 0, max = 999;
fScreenMode.GetRefreshLimits(fSelected, min, max);
if (min < gMinRefresh)
min = gMinRefresh;
if (max > gMaxRefresh)
max = gMaxRefresh;
BRect frame(Frame()); BRect frame(Frame());
RefreshWindow *fRefreshWindow = new RefreshWindow(BRect(frame.left + 201.0, RefreshWindow *fRefreshWindow = new RefreshWindow(BRect(frame.left + 201.0,
frame.top + 34.0, frame.left + 509.0, frame.top + 169.0), frame.top + 34.0, frame.left + 509.0, frame.top + 169.0),
int32(fSelected.refresh * 10)); fSelected.refresh, min, max);
fRefreshWindow->Show(); fRefreshWindow->Show();
break; break;
} }
@@ -988,7 +1017,11 @@ ScreenWindow::LayoutControls(uint32 flags)
+ backgroundsButtonHeight + backgroundsButtonHeight
+ 20.0; + 20.0;
#ifdef __HAIKU__
fScreenBox->MoveTo(10.0, 10.0 + fControlsBox->TopBorderOffset()); fScreenBox->MoveTo(10.0, 10.0 + fControlsBox->TopBorderOffset());
#else
fScreenBox->MoveTo(10.0, 10.0 + 3);
#endif
fScreenBox->ResizeTo(screenBoxWidth, screenBoxHeight); fScreenBox->ResizeTo(screenBoxWidth, screenBoxHeight);
float leftOffset = 10.0; 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 BRect
ScreenWindow::LayoutMenuFields(uint32 flags, bool sideBySide) ScreenWindow::LayoutMenuFields(uint32 flags, bool sideBySide)
{ {