1a10cf76eSAxel Dörfler /* 28bf216d6SAxel Dörfler * Copyright 2001-2015 Haiku, Inc. All rights reserved. 3a10cf76eSAxel Dörfler * Distributed under the terms of the MIT License. 4a10cf76eSAxel Dörfler * 5a10cf76eSAxel Dörfler * Authors: 6e1c88201SJohn Scipione * Stephan Aßmus, superstippi@gmx.de 7a10cf76eSAxel Dörfler * Andrew Bachmann 8e1c88201SJohn Scipione * Stefano Ceccherini, burton666@libero.it 9e1c88201SJohn Scipione * Alexandre Deckner, alex@zappotek.com 10e1c88201SJohn Scipione * Axel Dörfler, axeld@pinc-software.de 117e44de36SRene Gollent * Rene Gollent, rene@gollent.com 12a10cf76eSAxel Dörfler * Thomas Kurschel 13e1c88201SJohn Scipione * Rafael Romo 14e1c88201SJohn Scipione * John Scipione, jscipione@gmail.com 15a10cf76eSAxel Dörfler */ 16a10cf76eSAxel Dörfler 17a10cf76eSAxel Dörfler 18b21d610eSAxel Dörfler #include "ScreenWindow.h" 19b21d610eSAxel Dörfler 20b21d610eSAxel Dörfler #include <stdio.h> 21b21d610eSAxel Dörfler #include <stdlib.h> 223aeed660SJérôme Duval #include <strings.h> 23b21d610eSAxel Dörfler 24b21d610eSAxel Dörfler #include <Alert.h> 25b21d610eSAxel Dörfler #include <Application.h> 26b21d610eSAxel Dörfler #include <Box.h> 27b21d610eSAxel Dörfler #include <Button.h> 28c9e8f97aSAdrien Destugues #include <Catalog.h> 29e1c88201SJohn Scipione #include <ControlLook.h> 30b21d610eSAxel Dörfler #include <Directory.h> 31b21d610eSAxel Dörfler #include <File.h> 32b21d610eSAxel Dörfler #include <FindDirectory.h> 33b21d610eSAxel Dörfler #include <InterfaceDefs.h> 34b21d610eSAxel Dörfler #include <LayoutBuilder.h> 35b21d610eSAxel Dörfler #include <MenuBar.h> 36b21d610eSAxel Dörfler #include <MenuItem.h> 37b21d610eSAxel Dörfler #include <MenuField.h> 38b21d610eSAxel Dörfler #include <Messenger.h> 39b21d610eSAxel Dörfler #include <Path.h> 40b21d610eSAxel Dörfler #include <PopUpMenu.h> 41b21d610eSAxel Dörfler #include <Screen.h> 42e1c88201SJohn Scipione #include <SpaceLayoutItem.h> 43a3fa81bdSJohn Scipione #include <Spinner.h> 44b21d610eSAxel Dörfler #include <String.h> 45b21d610eSAxel Dörfler #include <StringView.h> 46b21d610eSAxel Dörfler #include <Roster.h> 47b21d610eSAxel Dörfler #include <Window.h> 48b21d610eSAxel Dörfler 49b21d610eSAxel Dörfler #include <InterfacePrivate.h> 50b21d610eSAxel Dörfler 51a10cf76eSAxel Dörfler #include "AlertWindow.h" 52a10cf76eSAxel Dörfler #include "Constants.h" 53a10cf76eSAxel Dörfler #include "RefreshWindow.h" 54a10cf76eSAxel Dörfler #include "MonitorView.h" 55a10cf76eSAxel Dörfler #include "ScreenSettings.h" 56a10cf76eSAxel Dörfler #include "Utility.h" 57a10cf76eSAxel Dörfler 58a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant. 59a10cf76eSAxel Dörfler * It's a solution that works with the current BeOS interface that Haiku 60a10cf76eSAxel Dörfler * adopted. 61a10cf76eSAxel Dörfler * However, it's not a nice and clean solution. Don't use this header in any 62a10cf76eSAxel Dörfler * application if you can avoid it. No other driver is using this, or should 63a10cf76eSAxel Dörfler * be using this. 64a10cf76eSAxel Dörfler * It will be replaced as soon as we introduce an updated accelerant interface 65a10cf76eSAxel Dörfler * which may even happen before R1 hits the streets. 66a10cf76eSAxel Dörfler */ 67a10cf76eSAxel Dörfler #include "multimon.h" // the usual: DANGER WILL, ROBINSON! 68a10cf76eSAxel Dörfler 69a10cf76eSAxel Dörfler 70546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 71546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Screen" 72c9e8f97aSAdrien Destugues 73c9e8f97aSAdrien Destugues 7475c92c56SRyan Leavengood const char* kBackgroundsSignature = "application/x-vnd.Haiku-Backgrounds"; 75c5d80d47SAxel Dörfler 76a10cf76eSAxel Dörfler // list of officially supported colour spaces 77a10cf76eSAxel Dörfler static const struct { 78a10cf76eSAxel Dörfler color_space space; 79a10cf76eSAxel Dörfler int32 bits_per_pixel; 80a10cf76eSAxel Dörfler const char* label; 81a10cf76eSAxel Dörfler } kColorSpaces[] = { 8226747978SAdrien Destugues { B_CMAP8, 8, B_TRANSLATE("8 bits/pixel, 256 colors") }, 83c9e8f97aSAdrien Destugues { B_RGB15, 15, B_TRANSLATE("15 bits/pixel, 32768 colors") }, 84c9e8f97aSAdrien Destugues { B_RGB16, 16, B_TRANSLATE("16 bits/pixel, 65536 colors") }, 85c9e8f97aSAdrien Destugues { B_RGB24, 24, B_TRANSLATE("24 bits/pixel, 16 Million colors") }, 86c9e8f97aSAdrien Destugues { B_RGB32, 32, B_TRANSLATE("32 bits/pixel, 16 Million colors") } 87a10cf76eSAxel Dörfler }; 88b21d610eSAxel Dörfler static const int32 kColorSpaceCount 89b21d610eSAxel Dörfler = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]); 90a10cf76eSAxel Dörfler 91a10cf76eSAxel Dörfler // list of standard refresh rates 92a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 }; 93b21d610eSAxel Dörfler static const int32 kRefreshRateCount 94b21d610eSAxel Dörfler = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); 95a10cf76eSAxel Dörfler 96a10cf76eSAxel Dörfler // list of combine modes 97a10cf76eSAxel Dörfler static const struct { 98a10cf76eSAxel Dörfler combine_mode mode; 99a10cf76eSAxel Dörfler const char *name; 100a10cf76eSAxel Dörfler } kCombineModes[] = { 101c9e8f97aSAdrien Destugues { kCombineDisable, B_TRANSLATE("disable") }, 102c9e8f97aSAdrien Destugues { kCombineHorizontally, B_TRANSLATE("horizontally") }, 103c9e8f97aSAdrien Destugues { kCombineVertically, B_TRANSLATE("vertically") } 104a10cf76eSAxel Dörfler }; 105b21d610eSAxel Dörfler static const int32 kCombineModeCount 106b21d610eSAxel Dörfler = sizeof(kCombineModes) / sizeof(kCombineModes[0]); 10729e8a73aSAxel Dörfler 108a10cf76eSAxel Dörfler 109a10cf76eSAxel Dörfler static BString 110a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode) 111a10cf76eSAxel Dörfler { 112a10cf76eSAxel Dörfler switch (mode) { 113a10cf76eSAxel Dörfler case 0: return "disabled"; 114a10cf76eSAxel Dörfler case 1: return "NTSC"; 115a10cf76eSAxel Dörfler case 2: return "NTSC Japan"; 116a10cf76eSAxel Dörfler case 3: return "PAL BDGHI"; 117a10cf76eSAxel Dörfler case 4: return "PAL M"; 118a10cf76eSAxel Dörfler case 5: return "PAL N"; 119a10cf76eSAxel Dörfler case 6: return "SECAM"; 120a10cf76eSAxel Dörfler case 101: return "NTSC 443"; 121a10cf76eSAxel Dörfler case 102: return "PAL 60"; 122a10cf76eSAxel Dörfler case 103: return "PAL NC"; 123a10cf76eSAxel Dörfler default: 124a10cf76eSAxel Dörfler { 125a10cf76eSAxel Dörfler BString name; 126a10cf76eSAxel Dörfler name << "??? (" << mode << ")"; 127a10cf76eSAxel Dörfler 128a10cf76eSAxel Dörfler return name; 129a10cf76eSAxel Dörfler } 130a10cf76eSAxel Dörfler } 131a10cf76eSAxel Dörfler } 132a10cf76eSAxel Dörfler 133a10cf76eSAxel Dörfler 134a10cf76eSAxel Dörfler static void 135a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string) 136a10cf76eSAxel Dörfler { 137a10cf76eSAxel Dörfler string << mode.width << " x " << mode.height; 138a10cf76eSAxel Dörfler } 139a10cf76eSAxel Dörfler 140a10cf76eSAxel Dörfler 141a10cf76eSAxel Dörfler static void 142a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string, 143a10cf76eSAxel Dörfler bool appendUnit = true, bool alwaysWithFraction = false) 144a10cf76eSAxel Dörfler { 1458bf23e3cSAxel Dörfler snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, 1468bf23e3cSAxel Dörfler refresh); 147a10cf76eSAxel Dörfler string.UnlockBuffer(); 148a10cf76eSAxel Dörfler 149a10cf76eSAxel Dörfler if (appendUnit) 150551c9f15SSiarzhuk Zharski string << " " << B_TRANSLATE("Hz"); 151a10cf76eSAxel Dörfler } 152a10cf76eSAxel Dörfler 153a10cf76eSAxel Dörfler 15407184a9eSAxel Dörfler static const char* 15507184a9eSAxel Dörfler screen_errors(status_t status) 15607184a9eSAxel Dörfler { 15707184a9eSAxel Dörfler switch (status) { 15807184a9eSAxel Dörfler case B_ENTRY_NOT_FOUND: 159c9e8f97aSAdrien Destugues return B_TRANSLATE("Unknown mode"); 16007184a9eSAxel Dörfler // TODO: add more? 16107184a9eSAxel Dörfler 16207184a9eSAxel Dörfler default: 16307184a9eSAxel Dörfler return strerror(status); 16407184a9eSAxel Dörfler } 16507184a9eSAxel Dörfler } 16607184a9eSAxel Dörfler 16729e8a73aSAxel Dörfler 168a3fa81bdSJohn Scipione // #pragma mark - ScreenWindow 1693dfd20c0SStephan Aßmus 1703dfd20c0SStephan Aßmus 1715a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings* settings) 172b21d610eSAxel Dörfler : 173560ff447SJonas Sundström BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Screen"), 174958e0ca5SJohn Scipione B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE 175958e0ca5SJohn Scipione | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), 1763f953a72SAxel Dörfler fIsVesa(false), 177199893c3SAxel Dörfler fBootWorkspaceApplied(false), 1787e44de36SRene Gollent fOtherRefresh(NULL), 179294a85aaSRene Gollent fScreenMode(this), 18061c5c89bSAxel Dörfler fUndoScreenMode(this), 181abc649b8SWaldemar Kornewald fModified(false) 182a10cf76eSAxel Dörfler { 183a10cf76eSAxel Dörfler BScreen screen(this); 184a10cf76eSAxel Dörfler 18512580984SAxel Dörfler accelerant_device_info info; 186d1516993SAxel Dörfler if (screen.GetDeviceInfo(&info) == B_OK 187d1516993SAxel Dörfler && !strcasecmp(info.chipset, "VESA")) 18812580984SAxel Dörfler fIsVesa = true; 18912580984SAxel Dörfler 1905de171daSAxel Dörfler _UpdateOriginal(); 1911fc4cb1fSAxel Dörfler _BuildSupportedColorSpaces(); 192a10cf76eSAxel Dörfler fActive = fSelected = fOriginal; 193a10cf76eSAxel Dörfler 1945a78744bSAxel Dörfler fSettings = settings; 1955a78744bSAxel Dörfler 1965a78744bSAxel Dörfler // we need the "Current Workspace" first to get its height 1975a78744bSAxel Dörfler 198c9e8f97aSAdrien Destugues BPopUpMenu* popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), 199c9e8f97aSAdrien Destugues true, true); 200c9e8f97aSAdrien Destugues fAllWorkspacesItem = new BMenuItem(B_TRANSLATE("All workspaces"), 201d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 2025a78744bSAxel Dörfler popUpMenu->AddItem(fAllWorkspacesItem); 203c9e8f97aSAdrien Destugues BMenuItem *item = new BMenuItem(B_TRANSLATE("Current workspace"), 204d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 205b72c4836SAlexandre Deckner 2065a78744bSAxel Dörfler popUpMenu->AddItem(item); 20727c43a2dSRene Gollent fAllWorkspacesItem->SetMarked(true); 2085a78744bSAxel Dörfler 209b21d610eSAxel Dörfler BMenuField* workspaceMenuField = new BMenuField("WorkspaceMenu", NULL, 21010dfe897SAxel Dörfler popUpMenu); 2115a78744bSAxel Dörfler workspaceMenuField->ResizeToPreferred(); 212a10cf76eSAxel Dörfler 213a10cf76eSAxel Dörfler // box on the left with workspace count and monitor view 214a10cf76eSAxel Dörfler 215b21d610eSAxel Dörfler BBox* screenBox = new BBox("screen box"); 216e1c88201SJohn Scipione BGroupLayout* layout = new BGroupLayout(B_VERTICAL, B_USE_SMALL_SPACING); 217e1c88201SJohn Scipione layout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 218e1c88201SJohn Scipione B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); 219b21d610eSAxel Dörfler screenBox->SetLayout(layout); 220a10cf76eSAxel Dörfler 22112966d04SAxel Dörfler fMonitorInfo = new BStringView("monitor info", ""); 222e1c88201SJohn Scipione fMonitorInfo->SetAlignment(B_ALIGN_CENTER); 22312966d04SAxel Dörfler screenBox->AddChild(fMonitorInfo); 22412966d04SAxel Dörfler 2258b46ee25SAdrien Destugues fDeviceInfo = new BStringView("monitor info", ""); 2268b46ee25SAdrien Destugues fDeviceInfo->SetAlignment(B_ALIGN_CENTER); 2278b46ee25SAdrien Destugues screenBox->AddChild(fDeviceInfo); 2288b46ee25SAdrien Destugues 2298bf216d6SAxel Dörfler float scaling = std::max(1.0f, be_plain_font->Size() / 12.0f); 2308bf216d6SAxel Dörfler fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0 * scaling, 2318bf216d6SAxel Dörfler 80.0 * scaling), "monitor", screen.Frame().IntegerWidth() + 1, 232c9e8f97aSAdrien Destugues screen.Frame().IntegerHeight() + 1); 233b21d610eSAxel Dörfler screenBox->AddChild(fMonitorView); 2345a78744bSAxel Dörfler 235e1c88201SJohn Scipione BStringView* workspaces = new BStringView("workspaces", 236e1c88201SJohn Scipione B_TRANSLATE("Workspaces")); 237e1c88201SJohn Scipione workspaces->SetAlignment(B_ALIGN_CENTER); 238e1c88201SJohn Scipione 239a3fa81bdSJohn Scipione fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"), 240b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceColumnsChanged)); 241a3fa81bdSJohn Scipione fColumnsControl->SetAlignment(B_ALIGN_RIGHT); 242a3fa81bdSJohn Scipione fColumnsControl->SetRange(1, 32); 243b21d610eSAxel Dörfler 244a3fa81bdSJohn Scipione fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"), 245a3fa81bdSJohn Scipione new BMessage(kMsgWorkspaceRowsChanged)); 246a3fa81bdSJohn Scipione fRowsControl->SetAlignment(B_ALIGN_RIGHT); 247a3fa81bdSJohn Scipione fRowsControl->SetRange(1, 32); 248a3fa81bdSJohn Scipione 249a3fa81bdSJohn Scipione uint32 columns; 250a3fa81bdSJohn Scipione uint32 rows; 251a3fa81bdSJohn Scipione BPrivate::get_workspaces_layout(&columns, &rows); 252a3fa81bdSJohn Scipione fColumnsControl->SetValue(columns); 253a3fa81bdSJohn Scipione fRowsControl->SetValue(rows); 254a3fa81bdSJohn Scipione 255e1c88201SJohn Scipione screenBox->AddChild(BLayoutBuilder::Group<>() 256e1c88201SJohn Scipione .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING) 257e1c88201SJohn Scipione .Add(workspaces) 258a3fa81bdSJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 259e1c88201SJohn Scipione // columns 260e1c88201SJohn Scipione .Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0) 261a3fa81bdSJohn Scipione .Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0) 262e1c88201SJohn Scipione // rows 263e1c88201SJohn Scipione .Add(fRowsControl->CreateLabelLayoutItem(), 0, 1) 264a3fa81bdSJohn Scipione .Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1) 265b21d610eSAxel Dörfler .End() 26625fd5c7bSAlex Wilson .End() 26725fd5c7bSAlex Wilson .View()); 268b21d610eSAxel Dörfler 269b21d610eSAxel Dörfler fBackgroundsButton = new BButton("BackgroundsButton", 270c9e8f97aSAdrien Destugues B_TRANSLATE("Set background" B_UTF8_ELLIPSIS), 271b21d610eSAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 272b21d610eSAxel Dörfler fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 273b21d610eSAxel Dörfler screenBox->AddChild(fBackgroundsButton); 274a10cf76eSAxel Dörfler 275a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 276a10cf76eSAxel Dörfler 277b21d610eSAxel Dörfler BBox* controlsBox = new BBox("controls box"); 278b21d610eSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 2796048f541SJohn Scipione BGroupView* outerControlsView = new BGroupView(B_VERTICAL); 2806048f541SJohn Scipione outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING, 2816048f541SJohn Scipione B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); 282b21d610eSAxel Dörfler controlsBox->AddChild(outerControlsView); 283a10cf76eSAxel Dörfler 284551c9f15SSiarzhuk Zharski fResolutionMenu = new BPopUpMenu("resolution", true, true); 285a10cf76eSAxel Dörfler 28666ab1666SAxel Dörfler uint16 maxWidth = 0; 28766ab1666SAxel Dörfler uint16 maxHeight = 0; 28866ab1666SAxel Dörfler uint16 previousWidth = 0; 28966ab1666SAxel Dörfler uint16 previousHeight = 0; 290a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 291a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 292a10cf76eSAxel Dörfler 293a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 294a10cf76eSAxel Dörfler continue; 295a10cf76eSAxel Dörfler 296a10cf76eSAxel Dörfler previousWidth = mode.width; 297a10cf76eSAxel Dörfler previousHeight = mode.height; 29866ab1666SAxel Dörfler if (maxWidth < mode.width) 29966ab1666SAxel Dörfler maxWidth = mode.width; 30066ab1666SAxel Dörfler if (maxHeight < mode.height) 30166ab1666SAxel Dörfler maxHeight = mode.height; 302a10cf76eSAxel Dörfler 303a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_RESOLUTION_MSG); 304a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 305a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 306a10cf76eSAxel Dörfler 307a10cf76eSAxel Dörfler BString name; 308a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 309a10cf76eSAxel Dörfler 310a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 311a10cf76eSAxel Dörfler } 312a10cf76eSAxel Dörfler 31366ab1666SAxel Dörfler fMonitorView->SetMaxResolution(maxWidth, maxHeight); 31466ab1666SAxel Dörfler 315c9e8f97aSAdrien Destugues fResolutionField = new BMenuField("ResolutionMenu", 31610dfe897SAxel Dörfler B_TRANSLATE("Resolution:"), fResolutionMenu); 3176048f541SJohn Scipione fResolutionField->SetAlignment(B_ALIGN_RIGHT); 318a10cf76eSAxel Dörfler 319551c9f15SSiarzhuk Zharski fColorsMenu = new BPopUpMenu("colors", true, false); 320a10cf76eSAxel Dörfler 321a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 3221fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 3231fc4cb1fSAxel Dörfler continue; 3241fc4cb1fSAxel Dörfler 325a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_COLORS_MSG); 326a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 327a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 328a10cf76eSAxel Dörfler 3291fc4cb1fSAxel Dörfler BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); 3301fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == screen.ColorSpace()) 3311fc4cb1fSAxel Dörfler fUserSelectedColorSpace = item; 3321fc4cb1fSAxel Dörfler 3331fc4cb1fSAxel Dörfler fColorsMenu->AddItem(item); 334a10cf76eSAxel Dörfler } 335a10cf76eSAxel Dörfler 336c9e8f97aSAdrien Destugues fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"), 33710dfe897SAxel Dörfler fColorsMenu); 3386048f541SJohn Scipione fColorsField->SetAlignment(B_ALIGN_RIGHT); 339a10cf76eSAxel Dörfler 340551c9f15SSiarzhuk Zharski fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 341a10cf76eSAxel Dörfler 34229e8a73aSAxel Dörfler float min, max; 343ec495b30SRene Gollent if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) { 344ec495b30SRene Gollent // if we couldn't obtain the refresh limits, reset to the default 345ec495b30SRene Gollent // range. Constraints from detected monitors will fine-tune this 346ec495b30SRene Gollent // later. 347ec495b30SRene Gollent min = kRefreshRates[0]; 348ec495b30SRene Gollent max = kRefreshRates[kRefreshRateCount - 1]; 349ec495b30SRene Gollent } 350ec495b30SRene Gollent 351ec495b30SRene Gollent if (min == max) { 35229e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 35329e8a73aSAxel Dörfler // frequency, like the VESA driver 35429e8a73aSAxel Dörfler BString name; 3557e44de36SRene Gollent refresh_rate_to_string(min, name); 356cf076964SRene Gollent BMessage *message = new BMessage(POP_REFRESH_MSG); 357cf076964SRene Gollent message->AddFloat("refresh", min); 358cf076964SRene Gollent BMenuItem *item = new BMenuItem(name.String(), message); 3590efb8b66SJerome Duval fRefreshMenu->AddItem(item); 36029e8a73aSAxel Dörfler item->SetEnabled(false); 36129e8a73aSAxel Dörfler } else { 36270a2b1b5SAxel Dörfler monitor_info info; 36370a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 36470a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 36570a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 36670a2b1b5SAxel Dörfler } 36770a2b1b5SAxel Dörfler 368a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 36970a2b1b5SAxel Dörfler if (kRefreshRates[i] < min || kRefreshRates[i] > max) 37070a2b1b5SAxel Dörfler continue; 37170a2b1b5SAxel Dörfler 372a10cf76eSAxel Dörfler BString name; 373551c9f15SSiarzhuk Zharski name << kRefreshRates[i] << " " << B_TRANSLATE("Hz"); 374a10cf76eSAxel Dörfler 3750efb8b66SJerome Duval BMessage *message = new BMessage(POP_REFRESH_MSG); 376a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 377a10cf76eSAxel Dörfler 378a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 379a10cf76eSAxel Dörfler } 380a10cf76eSAxel Dörfler 381c9e8f97aSAdrien Destugues fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), 3820efb8b66SJerome Duval new BMessage(POP_OTHER_REFRESH_MSG)); 383a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 38429e8a73aSAxel Dörfler } 385a10cf76eSAxel Dörfler 386c9e8f97aSAdrien Destugues fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"), 38710dfe897SAxel Dörfler fRefreshMenu); 3886048f541SJohn Scipione fRefreshField->SetAlignment(B_ALIGN_RIGHT); 389b21d610eSAxel Dörfler 39012580984SAxel Dörfler if (_IsVesa()) 39112580984SAxel Dörfler fRefreshField->Hide(); 392a10cf76eSAxel Dörfler 393a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 394a10cf76eSAxel Dörfler { 395a10cf76eSAxel Dörfler bool dummy; 396a10cf76eSAxel Dörfler uint32 dummy32; 397a10cf76eSAxel Dörfler bool multiMonSupport; 398a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 399a10cf76eSAxel Dörfler bool tvStandardSupport; 400a10cf76eSAxel Dörfler 401a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 402a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 403a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 404a10cf76eSAxel Dörfler 405a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 406a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 407a10cf76eSAxel Dörfler 408551c9f15SSiarzhuk Zharski fCombineMenu = new BPopUpMenu("CombineDisplays", 409c9e8f97aSAdrien Destugues true, true); 410a10cf76eSAxel Dörfler 411a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 4120efb8b66SJerome Duval BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 413a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 414a10cf76eSAxel Dörfler 415d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 416d1516993SAxel Dörfler message)); 417a10cf76eSAxel Dörfler } 418a10cf76eSAxel Dörfler 419b21d610eSAxel Dörfler fCombineField = new BMenuField("CombineMenu", 42010dfe897SAxel Dörfler B_TRANSLATE("Combine displays:"), fCombineMenu); 4216048f541SJohn Scipione fCombineField->SetAlignment(B_ALIGN_RIGHT); 422a10cf76eSAxel Dörfler 423a10cf76eSAxel Dörfler if (!multiMonSupport) 424df3f5bacSStephan Aßmus fCombineField->Hide(); 425a10cf76eSAxel Dörfler 426551c9f15SSiarzhuk Zharski fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", 427c9e8f97aSAdrien Destugues true, true); 428a10cf76eSAxel Dörfler 429a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 4300efb8b66SJerome Duval BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG); 431a10cf76eSAxel Dörfler message->AddBool("swap", false); 432c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message)); 433a10cf76eSAxel Dörfler 434a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 435a10cf76eSAxel Dörfler message->AddBool("swap", true); 436c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message)); 437a10cf76eSAxel Dörfler 438c9e8f97aSAdrien Destugues fSwapDisplaysField = new BMenuField("SwapMenu", 43910dfe897SAxel Dörfler B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu); 4406048f541SJohn Scipione fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT); 441a10cf76eSAxel Dörfler 442a10cf76eSAxel Dörfler if (!multiMonSupport) 443df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 444a10cf76eSAxel Dörfler 445551c9f15SSiarzhuk Zharski fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", 446c9e8f97aSAdrien Destugues true, true); 447a10cf76eSAxel Dörfler 448a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 449a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 450a10cf76eSAxel Dörfler message->AddBool("use", false); 451c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"), 452c9e8f97aSAdrien Destugues message)); 453a10cf76eSAxel Dörfler 454a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 455a10cf76eSAxel Dörfler message->AddBool("use", true); 456c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"), 457c9e8f97aSAdrien Destugues message)); 458a10cf76eSAxel Dörfler 459b21d610eSAxel Dörfler fUseLaptopPanelField = new BMenuField("UseLaptopPanel", 46010dfe897SAxel Dörfler B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu); 4616048f541SJohn Scipione fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT); 462a10cf76eSAxel Dörfler 463a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 464df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 465a10cf76eSAxel Dörfler 466551c9f15SSiarzhuk Zharski fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 467a10cf76eSAxel Dörfler 468a10cf76eSAxel Dörfler // arbitrary limit 469a10cf76eSAxel Dörfler uint32 i; 470a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 471a10cf76eSAxel Dörfler uint32 mode; 472a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 473a10cf76eSAxel Dörfler break; 474a10cf76eSAxel Dörfler 475a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 476a10cf76eSAxel Dörfler 477a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 478a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 479a10cf76eSAxel Dörfler 480a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 481a10cf76eSAxel Dörfler } 482a10cf76eSAxel Dörfler 483c9e8f97aSAdrien Destugues fTVStandardField = new BMenuField("tv standard", 48410dfe897SAxel Dörfler B_TRANSLATE("Video format:"), fTVStandardMenu); 485df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 486a10cf76eSAxel Dörfler 487b21d610eSAxel Dörfler if (!tvStandardSupport || i == 0) 488df3f5bacSStephan Aßmus fTVStandardField->Hide(); 489a10cf76eSAxel Dörfler } 490a10cf76eSAxel Dörfler 49125fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 4926048f541SJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 4936048f541SJohn Scipione .Add(fResolutionField->CreateLabelLayoutItem(), 0, 0) 4946048f541SJohn Scipione .Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0) 4956048f541SJohn Scipione .Add(fColorsField->CreateLabelLayoutItem(), 0, 1) 4966048f541SJohn Scipione .Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1) 4976048f541SJohn Scipione .Add(fRefreshField->CreateLabelLayoutItem(), 0, 2) 4986048f541SJohn Scipione .Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2) 4996048f541SJohn Scipione .Add(fCombineField->CreateLabelLayoutItem(), 0, 3) 5006048f541SJohn Scipione .Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3) 5016048f541SJohn Scipione .Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4) 5026048f541SJohn Scipione .Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4) 5036048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5) 5046048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5) 5056048f541SJohn Scipione .Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6) 5066048f541SJohn Scipione .Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6) 50725fd5c7bSAlex Wilson .End(); 508df3f5bacSStephan Aßmus 509*3a2b67b5SAdrien Destugues fBrightnessSlider = new BSlider("brightness", "Brightness", 510*3a2b67b5SAdrien Destugues NULL, 0, 255, B_HORIZONTAL); 511*3a2b67b5SAdrien Destugues 512*3a2b67b5SAdrien Destugues status_t result = screen.GetBrightness(&fOriginalBrightness); 513*3a2b67b5SAdrien Destugues if (result == B_OK) { 514*3a2b67b5SAdrien Destugues fBrightnessSlider->SetModificationMessage( 515*3a2b67b5SAdrien Destugues new BMessage(SLIDER_BRIGHTNESS_MSG)); 516*3a2b67b5SAdrien Destugues fBrightnessSlider->SetValue(fOriginalBrightness * 255); 517*3a2b67b5SAdrien Destugues } else { 518*3a2b67b5SAdrien Destugues // The driver does not support changing the brightness, 519*3a2b67b5SAdrien Destugues // so hide the slider 520*3a2b67b5SAdrien Destugues fBrightnessSlider->Hide(); 521*3a2b67b5SAdrien Destugues 522*3a2b67b5SAdrien Destugues fOriginalBrightness = -1; 523*3a2b67b5SAdrien Destugues } 524*3a2b67b5SAdrien Destugues 525abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 526abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 527b21d610eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG));*/ 528a10cf76eSAxel Dörfler 529c9e8f97aSAdrien Destugues fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"), 530df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 531df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 53225fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 533b21d610eSAxel Dörfler .AddGlue() 53425fd5c7bSAlex Wilson .AddGroup(B_HORIZONTAL) 53525fd5c7bSAlex Wilson .AddGlue() 53625fd5c7bSAlex Wilson .Add(fApplyButton); 537b21d610eSAxel Dörfler 538c9e8f97aSAdrien Destugues fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"), 539b21d610eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 540b21d610eSAxel Dörfler fRevertButton->SetEnabled(false); 541b21d610eSAxel Dörfler 5424666484fSJohn Scipione BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) 5434666484fSJohn Scipione .AddGroup(B_HORIZONTAL) 544a2cb1737SAdrien Destugues .AddGroup(B_VERTICAL, 0, 1) 54583cc66b3SJohn Scipione .AddStrut(floorf(controlsBox->TopBorderOffset()) - 1) 546b21d610eSAxel Dörfler .Add(screenBox) 54783cc66b3SJohn Scipione .End() 548*3a2b67b5SAdrien Destugues .AddGroup(B_VERTICAL, 0, 1) 549a2cb1737SAdrien Destugues .Add(controlsBox, 2) 550*3a2b67b5SAdrien Destugues .Add(fBrightnessSlider) 551*3a2b67b5SAdrien Destugues .End() 552b21d610eSAxel Dörfler .End() 5534666484fSJohn Scipione .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 554b21d610eSAxel Dörfler .Add(fRevertButton) 5554666484fSJohn Scipione .AddGlue() 5564666484fSJohn Scipione .End() 557d0ac6099SHumdinger .SetInsets(B_USE_WINDOW_SPACING); 558b21d610eSAxel Dörfler 5595de171daSAxel Dörfler _UpdateControls(); 56012966d04SAxel Dörfler _UpdateMonitor(); 5618bf216d6SAxel Dörfler 5628bf216d6SAxel Dörfler MoveOnScreen(); 563a10cf76eSAxel Dörfler } 564a10cf76eSAxel Dörfler 565a10cf76eSAxel Dörfler 566a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 567a10cf76eSAxel Dörfler { 568a10cf76eSAxel Dörfler delete fSettings; 569a10cf76eSAxel Dörfler } 570a10cf76eSAxel Dörfler 571a10cf76eSAxel Dörfler 572a10cf76eSAxel Dörfler bool 573a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 574a10cf76eSAxel Dörfler { 575a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 576199893c3SAxel Dörfler 577199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 578199893c3SAxel Dörfler screen_mode vesaMode; 579199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 580199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 58112580984SAxel Dörfler if (status < B_OK) { 582c9e8f97aSAdrien Destugues BString warning = B_TRANSLATE("Could not write VESA mode settings" 583c9e8f97aSAdrien Destugues " file:\n\t"); 58412580984SAxel Dörfler warning << strerror(status); 585aed35104SHumdinger BAlert* alert = new BAlert(B_TRANSLATE("Warning"), 586aed35104SHumdinger warning.String(), B_TRANSLATE("OK"), NULL, 587aed35104SHumdinger NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 588aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 589aed35104SHumdinger alert->Go(); 59012580984SAxel Dörfler } 59112580984SAxel Dörfler } 59212580984SAxel Dörfler 593a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 594a10cf76eSAxel Dörfler 595a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 596a10cf76eSAxel Dörfler } 597a10cf76eSAxel Dörfler 598a10cf76eSAxel Dörfler 5995de171daSAxel Dörfler /*! Update resolution list according to combine mode 6001fc4cb1fSAxel Dörfler (some resolutions may not be combinable due to memory restrictions). 601a10cf76eSAxel Dörfler */ 602a10cf76eSAxel Dörfler void 6035de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 604a10cf76eSAxel Dörfler { 605a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 606a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 607a10cf76eSAxel Dörfler 608a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 609a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 610a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 611a10cf76eSAxel Dörfler continue; 612a10cf76eSAxel Dörfler 613a10cf76eSAxel Dörfler BString name; 614a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 615a10cf76eSAxel Dörfler 616a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 617a10cf76eSAxel Dörfler if (item != NULL) 618a10cf76eSAxel Dörfler item->SetEnabled(true); 619a10cf76eSAxel Dörfler } 620a10cf76eSAxel Dörfler } 621a10cf76eSAxel Dörfler 622a10cf76eSAxel Dörfler 6235de171daSAxel Dörfler /*! Update color and refresh options according to current mode 6245de171daSAxel Dörfler (a color space is made active if there is any mode with 6255de171daSAxel Dörfler given resolution and this colour space; same applies for 6265de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 627a10cf76eSAxel Dörfler */ 628a10cf76eSAxel Dörfler void 6295de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 630a10cf76eSAxel Dörfler { 6311fc4cb1fSAxel Dörfler int32 supportsAnything = false; 6321fc4cb1fSAxel Dörfler int32 index = 0; 6331fc4cb1fSAxel Dörfler 634a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 6351fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 6361fc4cb1fSAxel Dörfler continue; 6371fc4cb1fSAxel Dörfler 638a10cf76eSAxel Dörfler bool supported = false; 639a10cf76eSAxel Dörfler 640a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 641a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 642a10cf76eSAxel Dörfler 643a10cf76eSAxel Dörfler if (fSelected.width == mode.width 644a10cf76eSAxel Dörfler && fSelected.height == mode.height 6451fc4cb1fSAxel Dörfler && kColorSpaces[i].space == mode.space 646a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 6471fc4cb1fSAxel Dörfler supportsAnything = true; 648a10cf76eSAxel Dörfler supported = true; 649a10cf76eSAxel Dörfler break; 650a10cf76eSAxel Dörfler } 651a10cf76eSAxel Dörfler } 652a10cf76eSAxel Dörfler 6531fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(index++); 654a10cf76eSAxel Dörfler if (item) 655a10cf76eSAxel Dörfler item->SetEnabled(supported); 656a10cf76eSAxel Dörfler } 6571fc4cb1fSAxel Dörfler 6581fc4cb1fSAxel Dörfler fColorsField->SetEnabled(supportsAnything); 6591fc4cb1fSAxel Dörfler 6601fc4cb1fSAxel Dörfler if (!supportsAnything) 6611fc4cb1fSAxel Dörfler return; 6621fc4cb1fSAxel Dörfler 6631fc4cb1fSAxel Dörfler // Make sure a valid item is selected 6641fc4cb1fSAxel Dörfler 6651fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->FindMarked(); 6661fc4cb1fSAxel Dörfler bool changed = false; 6671fc4cb1fSAxel Dörfler 6681fc4cb1fSAxel Dörfler if (item != fUserSelectedColorSpace) { 6691fc4cb1fSAxel Dörfler if (fUserSelectedColorSpace != NULL 6701fc4cb1fSAxel Dörfler && fUserSelectedColorSpace->IsEnabled()) { 6711fc4cb1fSAxel Dörfler fUserSelectedColorSpace->SetMarked(true); 6721fc4cb1fSAxel Dörfler item = fUserSelectedColorSpace; 6731fc4cb1fSAxel Dörfler changed = true; 6741fc4cb1fSAxel Dörfler } 6751fc4cb1fSAxel Dörfler } 6761fc4cb1fSAxel Dörfler if (item != NULL && !item->IsEnabled()) { 6771fc4cb1fSAxel Dörfler // find the next best item 6781fc4cb1fSAxel Dörfler int32 index = fColorsMenu->IndexOf(item); 6791fc4cb1fSAxel Dörfler bool found = false; 6801fc4cb1fSAxel Dörfler 6811fc4cb1fSAxel Dörfler for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) { 6821fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6831fc4cb1fSAxel Dörfler if (item->IsEnabled()) { 6841fc4cb1fSAxel Dörfler found = true; 6851fc4cb1fSAxel Dörfler break; 6861fc4cb1fSAxel Dörfler } 6871fc4cb1fSAxel Dörfler } 6881fc4cb1fSAxel Dörfler if (!found) { 6891fc4cb1fSAxel Dörfler // search backwards as well 6901fc4cb1fSAxel Dörfler for (int32 i = index - 1; i >= 0; i--) { 6911fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6921fc4cb1fSAxel Dörfler if (item->IsEnabled()) 6931fc4cb1fSAxel Dörfler break; 6941fc4cb1fSAxel Dörfler } 6951fc4cb1fSAxel Dörfler } 6961fc4cb1fSAxel Dörfler 6971fc4cb1fSAxel Dörfler item->SetMarked(true); 6981fc4cb1fSAxel Dörfler changed = true; 6991fc4cb1fSAxel Dörfler } 7001fc4cb1fSAxel Dörfler 7011fc4cb1fSAxel Dörfler if (changed) { 7021fc4cb1fSAxel Dörfler // Update selected space 7031fc4cb1fSAxel Dörfler 7041fc4cb1fSAxel Dörfler BMessage* message = item->Message(); 7051fc4cb1fSAxel Dörfler int32 space; 7061fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) == B_OK) { 7071fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 7081fc4cb1fSAxel Dörfler _UpdateColorLabel(); 7091fc4cb1fSAxel Dörfler } 7101fc4cb1fSAxel Dörfler } 711a10cf76eSAxel Dörfler } 712a10cf76eSAxel Dörfler 713a10cf76eSAxel Dörfler 7145de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 715a10cf76eSAxel Dörfler void 7165de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 717a10cf76eSAxel Dörfler { 71829e8a73aSAxel Dörfler float min, max; 71929e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 72029e8a73aSAxel Dörfler return; 721a10cf76eSAxel Dörfler 72229e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 72329e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 72429e8a73aSAxel Dörfler BMessage* message = item->Message(); 72529e8a73aSAxel Dörfler float refresh; 72629e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 72729e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 728a10cf76eSAxel Dörfler } 729a10cf76eSAxel Dörfler } 730a10cf76eSAxel Dörfler 731a10cf76eSAxel Dörfler 7325de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 733a10cf76eSAxel Dörfler void 7345de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 735a10cf76eSAxel Dörfler { 7367e44de36SRene Gollent for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) { 7377e44de36SRene Gollent BMenuItem* item = fRefreshMenu->ItemAt(i); 7387e44de36SRene Gollent if (item->Message()->FindFloat("refresh") == fSelected.refresh) { 739a10cf76eSAxel Dörfler item->SetMarked(true); 74026747978SAdrien Destugues // "Other" items only contains a refresh rate when active 74126747978SAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 742a10cf76eSAxel Dörfler return; 743a10cf76eSAxel Dörfler } 7447e44de36SRene Gollent } 745a10cf76eSAxel Dörfler 746a10cf76eSAxel Dörfler // this is a non-standard refresh rate 7477e44de36SRene Gollent if (fOtherRefresh != NULL) { 748a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 749a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 750a10cf76eSAxel Dörfler 7517e44de36SRene Gollent BString string; 7527e44de36SRene Gollent refresh_rate_to_string(fSelected.refresh, string); 753a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 754a10cf76eSAxel Dörfler 755c9e8f97aSAdrien Destugues string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS)); 756a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 757a10cf76eSAxel Dörfler } 7587e44de36SRene Gollent } 759a10cf76eSAxel Dörfler 760a10cf76eSAxel Dörfler 761a10cf76eSAxel Dörfler void 7625de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 763a10cf76eSAxel Dörfler { 764a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 765a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 766a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 767a10cf76eSAxel Dörfler 768a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 769a10cf76eSAxel Dörfler } 770a10cf76eSAxel Dörfler 771a10cf76eSAxel Dörfler 772a10cf76eSAxel Dörfler void 7735de171daSAxel Dörfler ScreenWindow::_UpdateControls() 774a10cf76eSAxel Dörfler { 775b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 776b21d610eSAxel Dörfler 777a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 778c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 779a10cf76eSAxel Dörfler item->SetMarked(true); 780a10cf76eSAxel Dörfler 781a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 782c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 783a10cf76eSAxel Dörfler item->SetMarked(true); 784a10cf76eSAxel Dörfler 785a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 786a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 787a10cf76eSAxel Dörfler 788a10cf76eSAxel Dörfler uint32 tvStandard; 789a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 790a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 791a10cf76eSAxel Dörfler if (!item->IsMarked()) 792a10cf76eSAxel Dörfler item->SetMarked(true); 793a10cf76eSAxel Dörfler break; 794a10cf76eSAxel Dörfler } 795a10cf76eSAxel Dörfler } 796a10cf76eSAxel Dörfler 7975de171daSAxel Dörfler _CheckResolutionMenu(); 7985de171daSAxel Dörfler _CheckColorMenu(); 7995de171daSAxel Dörfler _CheckRefreshMenu(); 800a10cf76eSAxel Dörfler 801a10cf76eSAxel Dörfler BString string; 802a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 803a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 804a10cf76eSAxel Dörfler 805a10cf76eSAxel Dörfler if (item != NULL) { 806a10cf76eSAxel Dörfler if (!item->IsMarked()) 807a10cf76eSAxel Dörfler item->SetMarked(true); 808a10cf76eSAxel Dörfler } else { 809a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 810a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 811a10cf76eSAxel Dörfler // 1. add a new resolution to list 812a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 813a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 814a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 815a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 816a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 817a10cf76eSAxel Dörfler // 2. choose nearest resolution 818a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 819a10cf76eSAxel Dörfler // 3. choose lowest resolution 820a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 821a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 822a10cf76eSAxel Dörfler if (item) 823a10cf76eSAxel Dörfler item->SetMarked(true); 824a10cf76eSAxel Dörfler 825a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 826a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 827a10cf76eSAxel Dörfler } 828a10cf76eSAxel Dörfler 829a10cf76eSAxel Dörfler // mark active combine mode 830a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 831a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 832a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 833c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 834a10cf76eSAxel Dörfler item->SetMarked(true); 835a10cf76eSAxel Dörfler break; 836a10cf76eSAxel Dörfler } 837a10cf76eSAxel Dörfler } 838a10cf76eSAxel Dörfler 839a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 840a10cf76eSAxel Dörfler 8411fc4cb1fSAxel Dörfler for (int32 i = 0, index = 0; i < kColorSpaceCount; i++) { 8421fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 8431fc4cb1fSAxel Dörfler continue; 8441fc4cb1fSAxel Dörfler 8451fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 8461fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(index); 847a10cf76eSAxel Dörfler break; 848a10cf76eSAxel Dörfler } 8491fc4cb1fSAxel Dörfler 8501fc4cb1fSAxel Dörfler index++; 851a10cf76eSAxel Dörfler } 852a10cf76eSAxel Dörfler 853c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 854a10cf76eSAxel Dörfler item->SetMarked(true); 855a10cf76eSAxel Dörfler 8561fc4cb1fSAxel Dörfler _UpdateColorLabel(); 8575de171daSAxel Dörfler _UpdateMonitorView(); 8585de171daSAxel Dörfler _UpdateRefreshControl(); 859a10cf76eSAxel Dörfler 8605de171daSAxel Dörfler _CheckApplyEnabled(); 861a10cf76eSAxel Dörfler } 862a10cf76eSAxel Dörfler 863a10cf76eSAxel Dörfler 86412580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 865a10cf76eSAxel Dörfler void 8665de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 867a10cf76eSAxel Dörfler { 868c491b5adSJohn Scipione _UpdateActiveMode(current_workspace()); 869c491b5adSJohn Scipione } 870c491b5adSJohn Scipione 871c491b5adSJohn Scipione 872c491b5adSJohn Scipione void 873c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace) 874c491b5adSJohn Scipione { 87512580984SAxel Dörfler // Usually, this function gets called after a mode 876a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 877a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 878a10cf76eSAxel Dörfler // what kind of mode we actually got 879c491b5adSJohn Scipione if (fScreenMode.Get(fActive, workspace) == B_OK) { 880a10cf76eSAxel Dörfler fSelected = fActive; 881a10cf76eSAxel Dörfler 88212966d04SAxel Dörfler _UpdateMonitor(); 883c491b5adSJohn Scipione _BuildSupportedColorSpaces(); 8845de171daSAxel Dörfler _UpdateControls(); 885a10cf76eSAxel Dörfler } 886c491b5adSJohn Scipione } 887a10cf76eSAxel Dörfler 888a10cf76eSAxel Dörfler 889a10cf76eSAxel Dörfler void 890b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons() 891b21d610eSAxel Dörfler { 892b21d610eSAxel Dörfler uint32 columns; 893b21d610eSAxel Dörfler uint32 rows; 894b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 895b21d610eSAxel Dörfler 896a3fa81bdSJohn Scipione // Set the max values enabling/disabling the up/down arrows 897b21d610eSAxel Dörfler 898a3fa81bdSJohn Scipione if (rows == 1) 899a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(32); 900a3fa81bdSJohn Scipione else if (rows == 2) 901a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(16); 902a3fa81bdSJohn Scipione else if (rows <= 4) 903a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(8); 904a3fa81bdSJohn Scipione else if (rows <= 8) 905a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(4); 906a3fa81bdSJohn Scipione else if (rows <= 16) 907a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(2); 908a3fa81bdSJohn Scipione else if (rows <= 32) 909a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(1); 910b21d610eSAxel Dörfler 911a3fa81bdSJohn Scipione if (columns == 1) 912a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(32); 913a3fa81bdSJohn Scipione else if (columns == 2) 914a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(16); 915a3fa81bdSJohn Scipione else if (columns <= 4) 916a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(8); 917a3fa81bdSJohn Scipione else if (columns <= 8) 918a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(4); 919a3fa81bdSJohn Scipione else if (columns <= 16) 920a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(2); 921a3fa81bdSJohn Scipione else if (columns <= 32) 922a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(1); 923b21d610eSAxel Dörfler } 924b21d610eSAxel Dörfler 925b21d610eSAxel Dörfler 926b21d610eSAxel Dörfler void 927a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 928a10cf76eSAxel Dörfler { 929a10cf76eSAxel Dörfler // move window on screen, if necessary 930a10cf76eSAxel Dörfler if (frame.right <= Frame().right 931a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 932a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 933a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 934a10cf76eSAxel Dörfler } 935a10cf76eSAxel Dörfler } 936a10cf76eSAxel Dörfler 937a10cf76eSAxel Dörfler 938a10cf76eSAxel Dörfler void 939a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 940a10cf76eSAxel Dörfler { 941c491b5adSJohn Scipione if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) { 942c491b5adSJohn Scipione _UpdateActiveMode(workspace); 943a10cf76eSAxel Dörfler 9446edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 9456edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 946a10cf76eSAxel Dörfler } 947c491b5adSJohn Scipione } 948a10cf76eSAxel Dörfler 949a10cf76eSAxel Dörfler 950a10cf76eSAxel Dörfler void 951a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 952a10cf76eSAxel Dörfler { 953a10cf76eSAxel Dörfler switch (message->what) { 954a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 9555de171daSAxel Dörfler _CheckApplyEnabled(); 956a10cf76eSAxel Dörfler break; 957a10cf76eSAxel Dörfler 958b21d610eSAxel Dörfler case kMsgWorkspaceColumnsChanged: 959b21d610eSAxel Dörfler { 960a3fa81bdSJohn Scipione uint32 newColumns = (uint32)fColumnsControl->Value(); 961b21d610eSAxel Dörfler 962b21d610eSAxel Dörfler uint32 rows; 963b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(NULL, &rows); 964b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, rows); 965b21d610eSAxel Dörfler 966b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 967a3fa81bdSJohn Scipione fRowsControl->SetValue(rows); 968a3fa81bdSJohn Scipione // enables/disables up/down arrows 969b21d610eSAxel Dörfler _CheckApplyEnabled(); 970a3fa81bdSJohn Scipione 971b21d610eSAxel Dörfler break; 972b21d610eSAxel Dörfler } 973b21d610eSAxel Dörfler 974b21d610eSAxel Dörfler case kMsgWorkspaceRowsChanged: 975b21d610eSAxel Dörfler { 976a3fa81bdSJohn Scipione uint32 newRows = (uint32)fRowsControl->Value(); 977b21d610eSAxel Dörfler 978b21d610eSAxel Dörfler uint32 columns; 979b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, NULL); 980b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(columns, newRows); 981b21d610eSAxel Dörfler 982b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 983a3fa81bdSJohn Scipione fColumnsControl->SetValue(columns); 984a3fa81bdSJohn Scipione // enables/disables up/down arrows 985b21d610eSAxel Dörfler _CheckApplyEnabled(); 986a10cf76eSAxel Dörfler break; 987a10cf76eSAxel Dörfler } 988a10cf76eSAxel Dörfler 989a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 990a10cf76eSAxel Dörfler { 991a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 992a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 993a10cf76eSAxel Dörfler 9945de171daSAxel Dörfler _CheckColorMenu(); 9955de171daSAxel Dörfler _CheckRefreshMenu(); 996a10cf76eSAxel Dörfler 9975de171daSAxel Dörfler _UpdateMonitorView(); 9985de171daSAxel Dörfler _UpdateRefreshControl(); 999a10cf76eSAxel Dörfler 10005de171daSAxel Dörfler _CheckApplyEnabled(); 1001a10cf76eSAxel Dörfler break; 1002a10cf76eSAxel Dörfler } 1003a10cf76eSAxel Dörfler 1004a10cf76eSAxel Dörfler case POP_COLORS_MSG: 1005a10cf76eSAxel Dörfler { 10061fc4cb1fSAxel Dörfler int32 space; 10071fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) != B_OK) 10081fc4cb1fSAxel Dörfler break; 1009a10cf76eSAxel Dörfler 10101fc4cb1fSAxel Dörfler int32 index; 10111fc4cb1fSAxel Dörfler if (message->FindInt32("index", &index) == B_OK 10121fc4cb1fSAxel Dörfler && fColorsMenu->ItemAt(index) != NULL) 10131fc4cb1fSAxel Dörfler fUserSelectedColorSpace = fColorsMenu->ItemAt(index); 10141fc4cb1fSAxel Dörfler 10151fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 10161fc4cb1fSAxel Dörfler _UpdateColorLabel(); 1017a10cf76eSAxel Dörfler 10185de171daSAxel Dörfler _CheckApplyEnabled(); 1019a10cf76eSAxel Dörfler break; 1020a10cf76eSAxel Dörfler } 1021a10cf76eSAxel Dörfler 1022a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 1023a40498e2SWaldemar Kornewald { 1024a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1025c9e8f97aSAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 10261fc4cb1fSAxel Dörfler // revert "Other…" label - it might have a refresh rate prefix 1027a10cf76eSAxel Dörfler 10285de171daSAxel Dörfler _CheckApplyEnabled(); 1029a10cf76eSAxel Dörfler break; 1030a40498e2SWaldemar Kornewald } 1031a10cf76eSAxel Dörfler 1032a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 1033a10cf76eSAxel Dörfler { 103429e8a73aSAxel Dörfler // make sure menu shows something useful 10355de171daSAxel Dörfler _UpdateRefreshControl(); 1036a10cf76eSAxel Dörfler 103729e8a73aSAxel Dörfler float min = 0, max = 999; 103829e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 103929e8a73aSAxel Dörfler if (min < gMinRefresh) 104029e8a73aSAxel Dörfler min = gMinRefresh; 104129e8a73aSAxel Dörfler if (max > gMaxRefresh) 104229e8a73aSAxel Dörfler max = gMaxRefresh; 104329e8a73aSAxel Dörfler 104470a2b1b5SAxel Dörfler monitor_info info; 104570a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 104670a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 104770a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 104870a2b1b5SAxel Dörfler } 104970a2b1b5SAxel Dörfler 1050c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 105170a2b1b5SAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, 105270a2b1b5SAxel Dörfler min, max); 1053a10cf76eSAxel Dörfler fRefreshWindow->Show(); 1054a10cf76eSAxel Dörfler break; 1055a10cf76eSAxel Dörfler } 1056a10cf76eSAxel Dörfler 1057a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 1058a10cf76eSAxel Dörfler { 1059a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 1060a10cf76eSAxel Dörfler // select the refresh rate chosen 1061a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1062a10cf76eSAxel Dörfler 10635de171daSAxel Dörfler _UpdateRefreshControl(); 10645de171daSAxel Dörfler _CheckApplyEnabled(); 1065a10cf76eSAxel Dörfler break; 1066a10cf76eSAxel Dörfler } 1067a10cf76eSAxel Dörfler 1068a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 1069a10cf76eSAxel Dörfler { 1070a10cf76eSAxel Dörfler // new combine mode has bee chosen 1071a10cf76eSAxel Dörfler int32 mode; 1072a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 1073a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 1074a10cf76eSAxel Dörfler 10755de171daSAxel Dörfler _CheckResolutionMenu(); 10765de171daSAxel Dörfler _CheckApplyEnabled(); 1077a10cf76eSAxel Dörfler break; 1078a10cf76eSAxel Dörfler } 1079a10cf76eSAxel Dörfler 1080a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 1081a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 10825de171daSAxel Dörfler _CheckApplyEnabled(); 1083a10cf76eSAxel Dörfler break; 1084a10cf76eSAxel Dörfler 1085a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 1086a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 10875de171daSAxel Dörfler _CheckApplyEnabled(); 1088a10cf76eSAxel Dörfler break; 1089a10cf76eSAxel Dörfler 1090a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 1091a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 10925de171daSAxel Dörfler _CheckApplyEnabled(); 1093a10cf76eSAxel Dörfler break; 1094a10cf76eSAxel Dörfler 1095df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 10966f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 10976f095d6aSRyan Leavengood app_info info; 10986f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 10996f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 11006f095d6aSRyan Leavengood } 1101df3f5bacSStephan Aßmus break; 1102df3f5bacSStephan Aßmus 1103a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 1104a10cf76eSAxel Dörfler { 11054be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 1106a10cf76eSAxel Dörfler fSelected.width = 640; 1107a10cf76eSAxel Dörfler fSelected.height = 480; 1108a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 1109a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 1110a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 1111a10cf76eSAxel Dörfler fSelected.swap_displays = false; 1112a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 1113a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 1114a10cf76eSAxel Dörfler 1115b21d610eSAxel Dörfler // TODO: workspace defaults 1116abc649b8SWaldemar Kornewald 11175de171daSAxel Dörfler _UpdateControls(); 1118a10cf76eSAxel Dörfler break; 1119a10cf76eSAxel Dörfler } 1120a10cf76eSAxel Dörfler 112110e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 112261c5c89bSAxel Dörfler fUndoScreenMode.Revert(); 11235de171daSAxel Dörfler _UpdateActiveMode(); 1124abc649b8SWaldemar Kornewald break; 1125abc649b8SWaldemar Kornewald 1126abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 1127abc649b8SWaldemar Kornewald { 1128abc649b8SWaldemar Kornewald fModified = false; 1129199893c3SAxel Dörfler fBootWorkspaceApplied = false; 1130abc649b8SWaldemar Kornewald 1131b21d610eSAxel Dörfler // ScreenMode::Revert() assumes that we first set the correct 1132b21d610eSAxel Dörfler // number of workspaces 1133b21d610eSAxel Dörfler 1134b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns, 1135b21d610eSAxel Dörfler fOriginalWorkspacesRows); 1136b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 1137b21d610eSAxel Dörfler 1138a10cf76eSAxel Dörfler fScreenMode.Revert(); 11395de171daSAxel Dörfler _UpdateActiveMode(); 1140*3a2b67b5SAdrien Destugues 1141*3a2b67b5SAdrien Destugues BScreen screen(this); 1142*3a2b67b5SAdrien Destugues screen.SetBrightness(fOriginalBrightness); 1143*3a2b67b5SAdrien Destugues fBrightnessSlider->SetValue(fOriginalBrightness * 255); 1144a10cf76eSAxel Dörfler break; 1145abc649b8SWaldemar Kornewald } 1146a10cf76eSAxel Dörfler 1147a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 11485de171daSAxel Dörfler _Apply(); 1149a10cf76eSAxel Dörfler break; 1150a10cf76eSAxel Dörfler 1151abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 1152abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 1153abc649b8SWaldemar Kornewald fModified = true; 11545de171daSAxel Dörfler _UpdateActiveMode(); 1155a10cf76eSAxel Dörfler break; 1156a10cf76eSAxel Dörfler 1157b8a61399SBrian Hill case UPDATE_DESKTOP_COLOR_MSG: 1158b8a61399SBrian Hill PostMessage(message, fMonitorView); 1159b8a61399SBrian Hill break; 1160b8a61399SBrian Hill 1161*3a2b67b5SAdrien Destugues case SLIDER_BRIGHTNESS_MSG: 1162*3a2b67b5SAdrien Destugues { 1163*3a2b67b5SAdrien Destugues BScreen screen(this); 1164*3a2b67b5SAdrien Destugues screen.SetBrightness(message->FindInt32("be:value") / 255.f); 1165*3a2b67b5SAdrien Destugues _CheckApplyEnabled(); 1166*3a2b67b5SAdrien Destugues break; 1167*3a2b67b5SAdrien Destugues } 1168*3a2b67b5SAdrien Destugues 1169a10cf76eSAxel Dörfler default: 1170a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 1171a10cf76eSAxel Dörfler } 1172a10cf76eSAxel Dörfler } 1173a10cf76eSAxel Dörfler 1174a10cf76eSAxel Dörfler 117512580984SAxel Dörfler status_t 117612580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 117712580984SAxel Dörfler { 117812580984SAxel Dörfler BPath path; 117912580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 118012580984SAxel Dörfler if (status < B_OK) 118112580984SAxel Dörfler return status; 118212580984SAxel Dörfler 118312580984SAxel Dörfler path.Append("kernel/drivers"); 118412580984SAxel Dörfler status = create_directory(path.Path(), 0755); 118512580984SAxel Dörfler if (status < B_OK) 118612580984SAxel Dörfler return status; 118712580984SAxel Dörfler 118812580984SAxel Dörfler path.Append("vesa"); 118912580984SAxel Dörfler BFile file; 119012580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 119112580984SAxel Dörfler if (status < B_OK) 119212580984SAxel Dörfler return status; 119312580984SAxel Dörfler 119412580984SAxel Dörfler char buffer[256]; 11955084d0d4SAlex Smith snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %" 11965084d0d4SAlex Smith B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel()); 119712580984SAxel Dörfler 119812580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 119912580984SAxel Dörfler if (bytesWritten < B_OK) 120012580984SAxel Dörfler return bytesWritten; 120112580984SAxel Dörfler 120212580984SAxel Dörfler return B_OK; 120312580984SAxel Dörfler } 120412580984SAxel Dörfler 120512580984SAxel Dörfler 1206a10cf76eSAxel Dörfler void 12071fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces() 12081fc4cb1fSAxel Dörfler { 12091fc4cb1fSAxel Dörfler fSupportedColorSpaces = 0; 12101fc4cb1fSAxel Dörfler 12111fc4cb1fSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 12121fc4cb1fSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 12131fc4cb1fSAxel Dörfler if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) { 12141fc4cb1fSAxel Dörfler fSupportedColorSpaces |= 1 << i; 12151fc4cb1fSAxel Dörfler break; 12161fc4cb1fSAxel Dörfler } 12171fc4cb1fSAxel Dörfler } 12181fc4cb1fSAxel Dörfler } 12191fc4cb1fSAxel Dörfler } 12201fc4cb1fSAxel Dörfler 12211fc4cb1fSAxel Dörfler 12221fc4cb1fSAxel Dörfler void 12235de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1224a10cf76eSAxel Dörfler { 122595ef5044SJanus bool applyEnabled = true; 122695ef5044SJanus 122795ef5044SJanus if (fSelected == fActive) { 122895ef5044SJanus applyEnabled = false; 122995ef5044SJanus if (fAllWorkspacesItem->IsMarked()) { 123095ef5044SJanus screen_mode screenMode; 123195ef5044SJanus const int32 workspaceCount = count_workspaces(); 123295ef5044SJanus for (int32 i = 0; i < workspaceCount; i++) { 123395ef5044SJanus fScreenMode.Get(screenMode, i); 123495ef5044SJanus if (screenMode != fSelected) { 123595ef5044SJanus applyEnabled = true; 123695ef5044SJanus break; 123795ef5044SJanus } 123895ef5044SJanus } 123995ef5044SJanus } 124095ef5044SJanus } 124195ef5044SJanus 124295ef5044SJanus fApplyButton->SetEnabled(applyEnabled); 1243b21d610eSAxel Dörfler 1244b21d610eSAxel Dörfler uint32 columns; 1245b21d610eSAxel Dörfler uint32 rows; 1246b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 1247b21d610eSAxel Dörfler 1248*3a2b67b5SAdrien Destugues BScreen screen(this); 1249*3a2b67b5SAdrien Destugues float brightness = -1; 1250*3a2b67b5SAdrien Destugues screen.GetBrightness(&brightness); 1251*3a2b67b5SAdrien Destugues 1252b21d610eSAxel Dörfler fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns 1253b21d610eSAxel Dörfler || rows != fOriginalWorkspacesRows 1254*3a2b67b5SAdrien Destugues || brightness != fOriginalBrightness 12555de171daSAxel Dörfler || fSelected != fOriginal); 1256a10cf76eSAxel Dörfler } 1257a10cf76eSAxel Dörfler 1258a10cf76eSAxel Dörfler 1259a10cf76eSAxel Dörfler void 12605de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1261abc649b8SWaldemar Kornewald { 1262b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns, 1263b21d610eSAxel Dörfler &fOriginalWorkspacesRows); 1264b21d610eSAxel Dörfler 1265abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1266abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1267abc649b8SWaldemar Kornewald } 1268abc649b8SWaldemar Kornewald 1269abc649b8SWaldemar Kornewald 1270abc649b8SWaldemar Kornewald void 127112966d04SAxel Dörfler ScreenWindow::_UpdateMonitor() 127212966d04SAxel Dörfler { 127312966d04SAxel Dörfler monitor_info info; 127412966d04SAxel Dörfler float diagonalInches; 127512966d04SAxel Dörfler status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches); 127655030977SAxel Dörfler if (status == B_OK) { 12771a8af605SAxel Dörfler char text[512]; 127866ab1666SAxel Dörfler snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor, 127966ab1666SAxel Dörfler info.name[0] ? " " : "", info.name, diagonalInches); 128012966d04SAxel Dörfler 128112966d04SAxel Dörfler fMonitorInfo->SetText(text); 128212966d04SAxel Dörfler 12838bf216d6SAxel Dörfler if (fMonitorInfo->IsHidden(fMonitorInfo)) 128412966d04SAxel Dörfler fMonitorInfo->Show(); 128555030977SAxel Dörfler } else { 12868bf216d6SAxel Dörfler if (!fMonitorInfo->IsHidden(fMonitorInfo)) 128755030977SAxel Dörfler fMonitorInfo->Hide(); 128855030977SAxel Dörfler } 1289af8f9c31SAxel Dörfler 12908b46ee25SAdrien Destugues // Add info about the graphics device 12918b46ee25SAdrien Destugues 12928b46ee25SAdrien Destugues accelerant_device_info deviceInfo; 12938b46ee25SAdrien Destugues 12948b46ee25SAdrien Destugues if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK) { 12958b46ee25SAdrien Destugues BString deviceString; 12968b46ee25SAdrien Destugues 12978b46ee25SAdrien Destugues if (deviceInfo.name[0] && deviceInfo.chipset[0]) { 12988b46ee25SAdrien Destugues deviceString.SetToFormat("%s (%s)", deviceInfo.name, 12998b46ee25SAdrien Destugues deviceInfo.chipset); 13008b46ee25SAdrien Destugues } else if (deviceInfo.name[0] || deviceInfo.chipset[0]) { 13018b46ee25SAdrien Destugues deviceString 13028b46ee25SAdrien Destugues = deviceInfo.name[0] ? deviceInfo.name : deviceInfo.chipset; 13038b46ee25SAdrien Destugues } 13048b46ee25SAdrien Destugues 13058b46ee25SAdrien Destugues fDeviceInfo->SetText(deviceString); 13068b46ee25SAdrien Destugues } 13078b46ee25SAdrien Destugues 13088b46ee25SAdrien Destugues 130955030977SAxel Dörfler char text[512]; 13101a8af605SAxel Dörfler size_t length = 0; 13111a8af605SAxel Dörfler text[0] = 0; 13121a8af605SAxel Dörfler 131355030977SAxel Dörfler if (status == B_OK) { 1314af8f9c31SAxel Dörfler if (info.min_horizontal_frequency != 0 1315af8f9c31SAxel Dörfler && info.min_vertical_frequency != 0 1316af8f9c31SAxel Dörfler && info.max_pixel_clock != 0) { 13171a8af605SAxel Dörfler length = snprintf(text, sizeof(text), 1318c9e8f97aSAdrien Destugues B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n" 13199c1a9b92SAdrien Destugues "Vertical frequency:\t%lu - %lu Hz\n\n" 1320c9e8f97aSAdrien Destugues "Maximum pixel clock:\t%g MHz"), 13211a8af605SAxel Dörfler info.min_horizontal_frequency, info.max_horizontal_frequency, 13221a8af605SAxel Dörfler info.min_vertical_frequency, info.max_vertical_frequency, 13231a8af605SAxel Dörfler info.max_pixel_clock / 1000.0); 1324af8f9c31SAxel Dörfler } 13251a8af605SAxel Dörfler if (info.serial_number[0] && length < sizeof(text)) { 13261a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 1327c9e8f97aSAdrien Destugues B_TRANSLATE("%sSerial no.: %s"), length ? "\n\n" : "", 13281a8af605SAxel Dörfler info.serial_number); 13291a8af605SAxel Dörfler if (info.produced.week != 0 && info.produced.year != 0 13301a8af605SAxel Dörfler && length < sizeof(text)) { 13311a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 13321a8af605SAxel Dörfler " (%u/%u)", info.produced.week, info.produced.year); 13331a8af605SAxel Dörfler } 13341a8af605SAxel Dörfler } 133555030977SAxel Dörfler } 133661c5c89bSAxel Dörfler 13371a8af605SAxel Dörfler if (text[0]) 13381a8af605SAxel Dörfler fMonitorView->SetToolTip(text); 133912966d04SAxel Dörfler } 134012966d04SAxel Dörfler 134112966d04SAxel Dörfler 134212966d04SAxel Dörfler void 13431fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel() 13441fc4cb1fSAxel Dörfler { 13451fc4cb1fSAxel Dörfler BString string; 1346551c9f15SSiarzhuk Zharski string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel"); 13471fc4cb1fSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 13481fc4cb1fSAxel Dörfler } 13491fc4cb1fSAxel Dörfler 13501fc4cb1fSAxel Dörfler 13511fc4cb1fSAxel Dörfler void 13525de171daSAxel Dörfler ScreenWindow::_Apply() 1353a10cf76eSAxel Dörfler { 1354abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 135561c5c89bSAxel Dörfler fUndoScreenMode.UpdateOriginalModes(); 135661c5c89bSAxel Dörfler 135707184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 135807184a9eSAxel Dörfler if (status == B_OK) { 1359abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1360abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1361abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1362abc649b8SWaldemar Kornewald display_mode newMode; 1363abc649b8SWaldemar Kornewald BScreen screen(this); 1364abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1365abc649b8SWaldemar Kornewald 1366abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1367abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 136895ef5044SJanus const int32 workspaceCount = count_workspaces(); 136995ef5044SJanus for (int32 i = 0; i < workspaceCount; i++) { 1370abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1371abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1372abc649b8SWaldemar Kornewald } 1373199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1374199893c3SAxel Dörfler } else { 1375199893c3SAxel Dörfler if (current_workspace() == 0) 1376199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1377abc649b8SWaldemar Kornewald } 1378abc649b8SWaldemar Kornewald 1379a10cf76eSAxel Dörfler fActive = fSelected; 1380a10cf76eSAxel Dörfler 1381abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 138241f43d56SAugustin Cavalier BAlert* window = new AlertWindow(this); 138341f43d56SAugustin Cavalier window->Go(NULL); 138407184a9eSAxel Dörfler } else { 138507184a9eSAxel Dörfler char message[256]; 138607184a9eSAxel Dörfler snprintf(message, sizeof(message), 1387c9e8f97aSAdrien Destugues B_TRANSLATE("The screen mode could not be set:\n\t%s\n"), 1388c9e8f97aSAdrien Destugues screen_errors(status)); 1389551c9f15SSiarzhuk Zharski BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message, 1390c9e8f97aSAdrien Destugues B_TRANSLATE("OK"), NULL, NULL, 139107184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 1392aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 139307184a9eSAxel Dörfler alert->Go(); 1394a10cf76eSAxel Dörfler } 139507184a9eSAxel Dörfler } 1396