/*! Reflect active mode in chosen settings */ void ScreenWindow::_UpdateActiveMode() { // Usually, this function gets called after a mode // has been set manually; still, as the graphics driver // is free to fiddle with mode passed, we better ask // what kind of mode we actually got fScreenMode.Get(fActive); fSelected = fActive; _UpdateMonitor(); _UpdateControls(); }
void ScreenWindow::_UpdateActiveMode(int32 workspace) { // Usually, this function gets called after a mode // has been set manually; still, as the graphics driver // is free to fiddle with mode passed, we better ask // what kind of mode we actually got if (fScreenMode.Get(fActive, workspace) == B_OK) { fSelected = fActive; _UpdateMonitor(); _BuildSupportedColorSpaces(); _UpdateControls(); } }
ScreenWindow::ScreenWindow(ScreenSettings* settings) : BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Screen"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), fIsVesa(false), fBootWorkspaceApplied(false), fOtherRefresh(NULL), fScreenMode(this), fUndoScreenMode(this), fModified(false) { BScreen screen(this); accelerant_device_info info; if (screen.GetDeviceInfo(&info) == B_OK && !strcasecmp(info.chipset, "VESA")) fIsVesa = true; _UpdateOriginal(); _BuildSupportedColorSpaces(); fActive = fSelected = fOriginal; fSettings = settings; // we need the "Current Workspace" first to get its height BPopUpMenu *popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), true, true); fAllWorkspacesItem = new BMenuItem(B_TRANSLATE("All workspaces"), new BMessage(WORKSPACE_CHECK_MSG)); popUpMenu->AddItem(fAllWorkspacesItem); BMenuItem *item = new BMenuItem(B_TRANSLATE("Current workspace"), new BMessage(WORKSPACE_CHECK_MSG)); popUpMenu->AddItem(item); fAllWorkspacesItem->SetMarked(true); BMenuField* workspaceMenuField = new BMenuField("WorkspaceMenu", NULL, popUpMenu); workspaceMenuField->ResizeToPreferred(); // box on the left with workspace count and monitor view BBox* screenBox = new BBox("screen box"); BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 5.0); layout->SetInsets(10, 10, 10, 10); screenBox->SetLayout(layout); fMonitorInfo = new BStringView("monitor info", ""); screenBox->AddChild(fMonitorInfo); fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), "monitor", screen.Frame().IntegerWidth() + 1, screen.Frame().IntegerHeight() + 1); screenBox->AddChild(fMonitorView); fColumnsControl = new BTextControl(B_TRANSLATE("Columns:"), "0", new BMessage(kMsgWorkspaceColumnsChanged)); fRowsControl = new BTextControl(B_TRANSLATE("Rows:"), "0", new BMessage(kMsgWorkspaceRowsChanged)); screenBox->AddChild(BLayoutBuilder::Grid<>(5.0, 5.0) .Add(new BStringView("", B_TRANSLATE("Workspaces")), 0, 0, 3) .AddTextControl(fColumnsControl, 0, 1, B_ALIGN_RIGHT) .AddGroup(B_HORIZONTAL, 0, 2, 1) .Add(_CreateColumnRowButton(true, false)) .Add(_CreateColumnRowButton(true, true)) .End() .AddTextControl(fRowsControl, 0, 2, B_ALIGN_RIGHT) .AddGroup(B_HORIZONTAL, 0, 2, 2) .Add(_CreateColumnRowButton(false, false)) .Add(_CreateColumnRowButton(false, true)) .End() .View()); fBackgroundsButton = new BButton("BackgroundsButton", B_TRANSLATE("Set background" B_UTF8_ELLIPSIS), new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); screenBox->AddChild(fBackgroundsButton); // box on the right with screen resolution, etc. BBox* controlsBox = new BBox("controls box"); controlsBox->SetLabel(workspaceMenuField); BGroupView* outerControlsView = new BGroupView(B_VERTICAL, 10.0); outerControlsView->GroupLayout()->SetInsets(10, 10, 10, 10); controlsBox->AddChild(outerControlsView); fResolutionMenu = new BPopUpMenu("resolution", true, true); uint16 maxWidth = 0; uint16 maxHeight = 0; uint16 previousWidth = 0; uint16 previousHeight = 0; for (int32 i = 0; i < fScreenMode.CountModes(); i++) { screen_mode mode = fScreenMode.ModeAt(i); if (mode.width == previousWidth && mode.height == previousHeight) continue; previousWidth = mode.width; previousHeight = mode.height; if (maxWidth < mode.width) maxWidth = mode.width; if (maxHeight < mode.height) maxHeight = mode.height; BMessage* message = new BMessage(POP_RESOLUTION_MSG); message->AddInt32("width", mode.width); message->AddInt32("height", mode.height); BString name; name << mode.width << " x " << mode.height; fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); } fMonitorView->SetMaxResolution(maxWidth, maxHeight); fResolutionField = new BMenuField("ResolutionMenu", B_TRANSLATE("Resolution:"), fResolutionMenu); fColorsMenu = new BPopUpMenu("colors", true, false); for (int32 i = 0; i < kColorSpaceCount; i++) { if ((fSupportedColorSpaces & (1 << i)) == 0) continue; BMessage* message = new BMessage(POP_COLORS_MSG); message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); message->AddInt32("space", kColorSpaces[i].space); BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); if (kColorSpaces[i].space == screen.ColorSpace()) fUserSelectedColorSpace = item; fColorsMenu->AddItem(item); } fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"), fColorsMenu); fRefreshMenu = new BPopUpMenu("refresh rate", true, true); float min, max; if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) { // if we couldn't obtain the refresh limits, reset to the default // range. Constraints from detected monitors will fine-tune this // later. min = kRefreshRates[0]; max = kRefreshRates[kRefreshRateCount - 1]; } if (min == max) { // This is a special case for drivers that only support a single // frequency, like the VESA driver BString name; refresh_rate_to_string(min, name); BMessage *message = new BMessage(POP_REFRESH_MSG); message->AddFloat("refresh", min); BMenuItem *item = new BMenuItem(name.String(), message); fRefreshMenu->AddItem(item); item->SetEnabled(false); } else { monitor_info info; if (fScreenMode.GetMonitorInfo(info) == B_OK) { min = max_c(info.min_vertical_frequency, min); max = min_c(info.max_vertical_frequency, max); } for (int32 i = 0; i < kRefreshRateCount; ++i) { if (kRefreshRates[i] < min || kRefreshRates[i] > max) continue; BString name; name << kRefreshRates[i] << " " << B_TRANSLATE("Hz"); BMessage *message = new BMessage(POP_REFRESH_MSG); message->AddFloat("refresh", kRefreshRates[i]); fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); } fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), new BMessage(POP_OTHER_REFRESH_MSG)); fRefreshMenu->AddItem(fOtherRefresh); } fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"), fRefreshMenu); if (_IsVesa()) fRefreshField->Hide(); // enlarged area for multi-monitor settings { bool dummy; uint32 dummy32; bool multiMonSupport; bool useLaptopPanelSupport; bool tvStandardSupport; multiMonSupport = TestMultiMonSupport(&screen) == B_OK; useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; // even if there is no support, we still create all controls // to make sure we don't access NULL pointers later on fCombineMenu = new BPopUpMenu("CombineDisplays", true, true); for (int32 i = 0; i < kCombineModeCount; i++) { BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG); message->AddInt32("mode", kCombineModes[i].mode); fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, message)); } fCombineField = new BMenuField("CombineMenu", B_TRANSLATE("Combine displays:"), fCombineMenu); if (!multiMonSupport) fCombineField->Hide(); fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true); // !order is important - we rely that boolean value == idx BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG); message->AddBool("swap", false); fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message)); message = new BMessage(POP_SWAP_DISPLAYS_MSG); message->AddBool("swap", true); fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message)); fSwapDisplaysField = new BMenuField("SwapMenu", B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu); if (!multiMonSupport) fSwapDisplaysField->Hide(); fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true); // !order is important - we rely that boolean value == idx message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); message->AddBool("use", false); fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"), message)); message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); message->AddBool("use", true); fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"), message)); fUseLaptopPanelField = new BMenuField("UseLaptopPanel", B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu); if (!useLaptopPanelSupport) fUseLaptopPanelField->Hide(); fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); // arbitrary limit uint32 i; for (i = 0; i < 100; ++i) { uint32 mode; if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) break; BString name = tv_standard_to_string(mode); message = new BMessage(POP_TV_STANDARD_MSG); message->AddInt32("tv_standard", mode); fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); } fTVStandardField = new BMenuField("tv standard", B_TRANSLATE("Video format:"), fTVStandardMenu); fTVStandardField->SetAlignment(B_ALIGN_RIGHT); if (!tvStandardSupport || i == 0) fTVStandardField->Hide(); } BLayoutBuilder::Group<>(outerControlsView) .AddGrid(5.0, 5.0) .AddMenuField(fResolutionField, 0, 0, B_ALIGN_RIGHT) .AddMenuField(fColorsField, 0, 1, B_ALIGN_RIGHT) .AddMenuField(fRefreshField, 0, 2, B_ALIGN_RIGHT) .AddMenuField(fCombineField, 0, 3, B_ALIGN_RIGHT) .AddMenuField(fSwapDisplaysField, 0, 4, B_ALIGN_RIGHT) .AddMenuField(fUseLaptopPanelField, 0, 5, B_ALIGN_RIGHT) .AddMenuField(fTVStandardField, 0, 6, B_ALIGN_RIGHT) .End(); // TODO: we don't support getting the screen's preferred settings /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", new BMessage(BUTTON_DEFAULTS_MSG));*/ fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"), new BMessage(BUTTON_APPLY_MSG)); fApplyButton->SetEnabled(false); BLayoutBuilder::Group<>(outerControlsView) .AddGlue() .AddGroup(B_HORIZONTAL) .AddGlue() .Add(fApplyButton); fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"), new BMessage(BUTTON_REVERT_MSG)); fRevertButton->SetEnabled(false); BLayoutBuilder::Group<>(this, B_VERTICAL, 10.0) .SetInsets(10, 10, 10, 10) .AddGroup(B_HORIZONTAL, 10.0) .AddGroup(B_VERTICAL) .AddStrut(floor(controlsBox->TopBorderOffset() / 16) - 1) .Add(screenBox) .End() .Add(controlsBox) .End() .AddGroup(B_HORIZONTAL, 10.0) .Add(fRevertButton) .AddGlue(); _UpdateControls(); _UpdateMonitor(); }