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) 258*4dcc9761SJohn Scipione .AddGroup(B_HORIZONTAL, 0) 259*4dcc9761SJohn Scipione .AddGlue() 260a3fa81bdSJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 261e1c88201SJohn Scipione // columns 262e1c88201SJohn Scipione .Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0) 263a3fa81bdSJohn Scipione .Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0) 264e1c88201SJohn Scipione // rows 265e1c88201SJohn Scipione .Add(fRowsControl->CreateLabelLayoutItem(), 0, 1) 266a3fa81bdSJohn Scipione .Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1) 267b21d610eSAxel Dörfler .End() 268*4dcc9761SJohn Scipione .AddGlue() 269*4dcc9761SJohn Scipione .End() 27025fd5c7bSAlex Wilson .End() 27125fd5c7bSAlex Wilson .View()); 272b21d610eSAxel Dörfler 273b21d610eSAxel Dörfler fBackgroundsButton = new BButton("BackgroundsButton", 274c9e8f97aSAdrien Destugues B_TRANSLATE("Set background" B_UTF8_ELLIPSIS), 275b21d610eSAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 276b21d610eSAxel Dörfler fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 277b21d610eSAxel Dörfler screenBox->AddChild(fBackgroundsButton); 278a10cf76eSAxel Dörfler 279a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 280a10cf76eSAxel Dörfler 281b21d610eSAxel Dörfler BBox* controlsBox = new BBox("controls box"); 282b21d610eSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 2836048f541SJohn Scipione BGroupView* outerControlsView = new BGroupView(B_VERTICAL); 2846048f541SJohn Scipione outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING, 2856048f541SJohn Scipione B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); 286b21d610eSAxel Dörfler controlsBox->AddChild(outerControlsView); 287a10cf76eSAxel Dörfler 288551c9f15SSiarzhuk Zharski fResolutionMenu = new BPopUpMenu("resolution", true, true); 289a10cf76eSAxel Dörfler 29066ab1666SAxel Dörfler uint16 maxWidth = 0; 29166ab1666SAxel Dörfler uint16 maxHeight = 0; 29266ab1666SAxel Dörfler uint16 previousWidth = 0; 29366ab1666SAxel Dörfler uint16 previousHeight = 0; 294a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 295a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 296a10cf76eSAxel Dörfler 297a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 298a10cf76eSAxel Dörfler continue; 299a10cf76eSAxel Dörfler 300a10cf76eSAxel Dörfler previousWidth = mode.width; 301a10cf76eSAxel Dörfler previousHeight = mode.height; 30266ab1666SAxel Dörfler if (maxWidth < mode.width) 30366ab1666SAxel Dörfler maxWidth = mode.width; 30466ab1666SAxel Dörfler if (maxHeight < mode.height) 30566ab1666SAxel Dörfler maxHeight = mode.height; 306a10cf76eSAxel Dörfler 307a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_RESOLUTION_MSG); 308a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 309a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 310a10cf76eSAxel Dörfler 311a10cf76eSAxel Dörfler BString name; 312a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 313a10cf76eSAxel Dörfler 314a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 315a10cf76eSAxel Dörfler } 316a10cf76eSAxel Dörfler 31766ab1666SAxel Dörfler fMonitorView->SetMaxResolution(maxWidth, maxHeight); 31866ab1666SAxel Dörfler 319c9e8f97aSAdrien Destugues fResolutionField = new BMenuField("ResolutionMenu", 32010dfe897SAxel Dörfler B_TRANSLATE("Resolution:"), fResolutionMenu); 3216048f541SJohn Scipione fResolutionField->SetAlignment(B_ALIGN_RIGHT); 322a10cf76eSAxel Dörfler 323551c9f15SSiarzhuk Zharski fColorsMenu = new BPopUpMenu("colors", true, false); 324a10cf76eSAxel Dörfler 325a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 3261fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 3271fc4cb1fSAxel Dörfler continue; 3281fc4cb1fSAxel Dörfler 329a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_COLORS_MSG); 330a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 331a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 332a10cf76eSAxel Dörfler 3331fc4cb1fSAxel Dörfler BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); 3341fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == screen.ColorSpace()) 3351fc4cb1fSAxel Dörfler fUserSelectedColorSpace = item; 3361fc4cb1fSAxel Dörfler 3371fc4cb1fSAxel Dörfler fColorsMenu->AddItem(item); 338a10cf76eSAxel Dörfler } 339a10cf76eSAxel Dörfler 340c9e8f97aSAdrien Destugues fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"), 34110dfe897SAxel Dörfler fColorsMenu); 3426048f541SJohn Scipione fColorsField->SetAlignment(B_ALIGN_RIGHT); 343a10cf76eSAxel Dörfler 344551c9f15SSiarzhuk Zharski fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 345a10cf76eSAxel Dörfler 34629e8a73aSAxel Dörfler float min, max; 347ec495b30SRene Gollent if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) { 348ec495b30SRene Gollent // if we couldn't obtain the refresh limits, reset to the default 349ec495b30SRene Gollent // range. Constraints from detected monitors will fine-tune this 350ec495b30SRene Gollent // later. 351ec495b30SRene Gollent min = kRefreshRates[0]; 352ec495b30SRene Gollent max = kRefreshRates[kRefreshRateCount - 1]; 353ec495b30SRene Gollent } 354ec495b30SRene Gollent 355ec495b30SRene Gollent if (min == max) { 35629e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 35729e8a73aSAxel Dörfler // frequency, like the VESA driver 35829e8a73aSAxel Dörfler BString name; 3597e44de36SRene Gollent refresh_rate_to_string(min, name); 360cf076964SRene Gollent BMessage *message = new BMessage(POP_REFRESH_MSG); 361cf076964SRene Gollent message->AddFloat("refresh", min); 362cf076964SRene Gollent BMenuItem *item = new BMenuItem(name.String(), message); 3630efb8b66SJerome Duval fRefreshMenu->AddItem(item); 36429e8a73aSAxel Dörfler item->SetEnabled(false); 36529e8a73aSAxel Dörfler } else { 36670a2b1b5SAxel Dörfler monitor_info info; 36770a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 36870a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 36970a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 37070a2b1b5SAxel Dörfler } 37170a2b1b5SAxel Dörfler 372a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 37370a2b1b5SAxel Dörfler if (kRefreshRates[i] < min || kRefreshRates[i] > max) 37470a2b1b5SAxel Dörfler continue; 37570a2b1b5SAxel Dörfler 376a10cf76eSAxel Dörfler BString name; 377551c9f15SSiarzhuk Zharski name << kRefreshRates[i] << " " << B_TRANSLATE("Hz"); 378a10cf76eSAxel Dörfler 3790efb8b66SJerome Duval BMessage *message = new BMessage(POP_REFRESH_MSG); 380a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 381a10cf76eSAxel Dörfler 382a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 383a10cf76eSAxel Dörfler } 384a10cf76eSAxel Dörfler 385c9e8f97aSAdrien Destugues fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), 3860efb8b66SJerome Duval new BMessage(POP_OTHER_REFRESH_MSG)); 387a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 38829e8a73aSAxel Dörfler } 389a10cf76eSAxel Dörfler 390c9e8f97aSAdrien Destugues fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"), 39110dfe897SAxel Dörfler fRefreshMenu); 3926048f541SJohn Scipione fRefreshField->SetAlignment(B_ALIGN_RIGHT); 393b21d610eSAxel Dörfler 39412580984SAxel Dörfler if (_IsVesa()) 39512580984SAxel Dörfler fRefreshField->Hide(); 396a10cf76eSAxel Dörfler 397a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 398a10cf76eSAxel Dörfler { 399a10cf76eSAxel Dörfler bool dummy; 400a10cf76eSAxel Dörfler uint32 dummy32; 401a10cf76eSAxel Dörfler bool multiMonSupport; 402a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 403a10cf76eSAxel Dörfler bool tvStandardSupport; 404a10cf76eSAxel Dörfler 405a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 406a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 407a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 408a10cf76eSAxel Dörfler 409a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 410a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 411a10cf76eSAxel Dörfler 412551c9f15SSiarzhuk Zharski fCombineMenu = new BPopUpMenu("CombineDisplays", 413c9e8f97aSAdrien Destugues true, true); 414a10cf76eSAxel Dörfler 415a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 4160efb8b66SJerome Duval BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 417a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 418a10cf76eSAxel Dörfler 419d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 420d1516993SAxel Dörfler message)); 421a10cf76eSAxel Dörfler } 422a10cf76eSAxel Dörfler 423b21d610eSAxel Dörfler fCombineField = new BMenuField("CombineMenu", 42410dfe897SAxel Dörfler B_TRANSLATE("Combine displays:"), fCombineMenu); 4256048f541SJohn Scipione fCombineField->SetAlignment(B_ALIGN_RIGHT); 426a10cf76eSAxel Dörfler 427a10cf76eSAxel Dörfler if (!multiMonSupport) 428df3f5bacSStephan Aßmus fCombineField->Hide(); 429a10cf76eSAxel Dörfler 430551c9f15SSiarzhuk Zharski fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", 431c9e8f97aSAdrien Destugues true, true); 432a10cf76eSAxel Dörfler 433a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 4340efb8b66SJerome Duval BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG); 435a10cf76eSAxel Dörfler message->AddBool("swap", false); 436c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message)); 437a10cf76eSAxel Dörfler 438a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 439a10cf76eSAxel Dörfler message->AddBool("swap", true); 440c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message)); 441a10cf76eSAxel Dörfler 442c9e8f97aSAdrien Destugues fSwapDisplaysField = new BMenuField("SwapMenu", 44310dfe897SAxel Dörfler B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu); 4446048f541SJohn Scipione fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT); 445a10cf76eSAxel Dörfler 446a10cf76eSAxel Dörfler if (!multiMonSupport) 447df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 448a10cf76eSAxel Dörfler 449551c9f15SSiarzhuk Zharski fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", 450c9e8f97aSAdrien Destugues true, true); 451a10cf76eSAxel Dörfler 452a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 453a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 454a10cf76eSAxel Dörfler message->AddBool("use", false); 455c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"), 456c9e8f97aSAdrien Destugues message)); 457a10cf76eSAxel Dörfler 458a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 459a10cf76eSAxel Dörfler message->AddBool("use", true); 460c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"), 461c9e8f97aSAdrien Destugues message)); 462a10cf76eSAxel Dörfler 463b21d610eSAxel Dörfler fUseLaptopPanelField = new BMenuField("UseLaptopPanel", 46410dfe897SAxel Dörfler B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu); 4656048f541SJohn Scipione fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT); 466a10cf76eSAxel Dörfler 467a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 468df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 469a10cf76eSAxel Dörfler 470551c9f15SSiarzhuk Zharski fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 471a10cf76eSAxel Dörfler 472a10cf76eSAxel Dörfler // arbitrary limit 473a10cf76eSAxel Dörfler uint32 i; 474a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 475a10cf76eSAxel Dörfler uint32 mode; 476a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 477a10cf76eSAxel Dörfler break; 478a10cf76eSAxel Dörfler 479a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 480a10cf76eSAxel Dörfler 481a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 482a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 483a10cf76eSAxel Dörfler 484a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 485a10cf76eSAxel Dörfler } 486a10cf76eSAxel Dörfler 487c9e8f97aSAdrien Destugues fTVStandardField = new BMenuField("tv standard", 48810dfe897SAxel Dörfler B_TRANSLATE("Video format:"), fTVStandardMenu); 489df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 490a10cf76eSAxel Dörfler 491b21d610eSAxel Dörfler if (!tvStandardSupport || i == 0) 492df3f5bacSStephan Aßmus fTVStandardField->Hide(); 493a10cf76eSAxel Dörfler } 494a10cf76eSAxel Dörfler 49525fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 4966048f541SJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 4976048f541SJohn Scipione .Add(fResolutionField->CreateLabelLayoutItem(), 0, 0) 4986048f541SJohn Scipione .Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0) 4996048f541SJohn Scipione .Add(fColorsField->CreateLabelLayoutItem(), 0, 1) 5006048f541SJohn Scipione .Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1) 5016048f541SJohn Scipione .Add(fRefreshField->CreateLabelLayoutItem(), 0, 2) 5026048f541SJohn Scipione .Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2) 5036048f541SJohn Scipione .Add(fCombineField->CreateLabelLayoutItem(), 0, 3) 5046048f541SJohn Scipione .Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3) 5056048f541SJohn Scipione .Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4) 5066048f541SJohn Scipione .Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4) 5076048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5) 5086048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5) 5096048f541SJohn Scipione .Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6) 5106048f541SJohn Scipione .Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6) 51125fd5c7bSAlex Wilson .End(); 512df3f5bacSStephan Aßmus 513b05def65SHumdinger fBrightnessSlider = new BSlider("brightness", B_TRANSLATE("Brightness:"), 5143a2b67b5SAdrien Destugues NULL, 0, 255, B_HORIZONTAL); 5153a2b67b5SAdrien Destugues 5163a2b67b5SAdrien Destugues status_t result = screen.GetBrightness(&fOriginalBrightness); 5173a2b67b5SAdrien Destugues if (result == B_OK) { 5183a2b67b5SAdrien Destugues fBrightnessSlider->SetModificationMessage( 5193a2b67b5SAdrien Destugues new BMessage(SLIDER_BRIGHTNESS_MSG)); 5203a2b67b5SAdrien Destugues fBrightnessSlider->SetValue(fOriginalBrightness * 255); 5213a2b67b5SAdrien Destugues } else { 5223a2b67b5SAdrien Destugues // The driver does not support changing the brightness, 5233a2b67b5SAdrien Destugues // so hide the slider 5243a2b67b5SAdrien Destugues fBrightnessSlider->Hide(); 5253a2b67b5SAdrien Destugues 5263a2b67b5SAdrien Destugues fOriginalBrightness = -1; 5273a2b67b5SAdrien Destugues } 5283a2b67b5SAdrien Destugues 529abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 530abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 531b21d610eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG));*/ 532a10cf76eSAxel Dörfler 533c9e8f97aSAdrien Destugues fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"), 534df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 535df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 53625fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 537b21d610eSAxel Dörfler .AddGlue() 53825fd5c7bSAlex Wilson .AddGroup(B_HORIZONTAL) 53925fd5c7bSAlex Wilson .AddGlue() 54025fd5c7bSAlex Wilson .Add(fApplyButton); 541b21d610eSAxel Dörfler 542c9e8f97aSAdrien Destugues fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"), 543b21d610eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 544b21d610eSAxel Dörfler fRevertButton->SetEnabled(false); 545b21d610eSAxel Dörfler 5464666484fSJohn Scipione BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) 5474666484fSJohn Scipione .AddGroup(B_HORIZONTAL) 548a2cb1737SAdrien Destugues .AddGroup(B_VERTICAL, 0, 1) 54983cc66b3SJohn Scipione .AddStrut(floorf(controlsBox->TopBorderOffset()) - 1) 550b21d610eSAxel Dörfler .Add(screenBox) 55183cc66b3SJohn Scipione .End() 5523a2b67b5SAdrien Destugues .AddGroup(B_VERTICAL, 0, 1) 553a2cb1737SAdrien Destugues .Add(controlsBox, 2) 5543a2b67b5SAdrien Destugues .Add(fBrightnessSlider) 5553a2b67b5SAdrien Destugues .End() 556b21d610eSAxel Dörfler .End() 5574666484fSJohn Scipione .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 558b21d610eSAxel Dörfler .Add(fRevertButton) 5594666484fSJohn Scipione .AddGlue() 5604666484fSJohn Scipione .End() 561d0ac6099SHumdinger .SetInsets(B_USE_WINDOW_SPACING); 562b21d610eSAxel Dörfler 5635de171daSAxel Dörfler _UpdateControls(); 56412966d04SAxel Dörfler _UpdateMonitor(); 5658bf216d6SAxel Dörfler 5668bf216d6SAxel Dörfler MoveOnScreen(); 567a10cf76eSAxel Dörfler } 568a10cf76eSAxel Dörfler 569a10cf76eSAxel Dörfler 570a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 571a10cf76eSAxel Dörfler { 572a10cf76eSAxel Dörfler delete fSettings; 573a10cf76eSAxel Dörfler } 574a10cf76eSAxel Dörfler 575a10cf76eSAxel Dörfler 576a10cf76eSAxel Dörfler bool 577a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 578a10cf76eSAxel Dörfler { 579a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 580199893c3SAxel Dörfler 581199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 582199893c3SAxel Dörfler screen_mode vesaMode; 583199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 584199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 58512580984SAxel Dörfler if (status < B_OK) { 586c9e8f97aSAdrien Destugues BString warning = B_TRANSLATE("Could not write VESA mode settings" 587c9e8f97aSAdrien Destugues " file:\n\t"); 58812580984SAxel Dörfler warning << strerror(status); 589aed35104SHumdinger BAlert* alert = new BAlert(B_TRANSLATE("Warning"), 590aed35104SHumdinger warning.String(), B_TRANSLATE("OK"), NULL, 591aed35104SHumdinger NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 592aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 593aed35104SHumdinger alert->Go(); 59412580984SAxel Dörfler } 59512580984SAxel Dörfler } 59612580984SAxel Dörfler 597a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 598a10cf76eSAxel Dörfler 599a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 600a10cf76eSAxel Dörfler } 601a10cf76eSAxel Dörfler 602a10cf76eSAxel Dörfler 6035de171daSAxel Dörfler /*! Update resolution list according to combine mode 6041fc4cb1fSAxel Dörfler (some resolutions may not be combinable due to memory restrictions). 605a10cf76eSAxel Dörfler */ 606a10cf76eSAxel Dörfler void 6075de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 608a10cf76eSAxel Dörfler { 609a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 610a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 611a10cf76eSAxel Dörfler 612a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 613a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 614a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 615a10cf76eSAxel Dörfler continue; 616a10cf76eSAxel Dörfler 617a10cf76eSAxel Dörfler BString name; 618a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 619a10cf76eSAxel Dörfler 620a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 621a10cf76eSAxel Dörfler if (item != NULL) 622a10cf76eSAxel Dörfler item->SetEnabled(true); 623a10cf76eSAxel Dörfler } 624a10cf76eSAxel Dörfler } 625a10cf76eSAxel Dörfler 626a10cf76eSAxel Dörfler 6275de171daSAxel Dörfler /*! Update color and refresh options according to current mode 6285de171daSAxel Dörfler (a color space is made active if there is any mode with 6295de171daSAxel Dörfler given resolution and this colour space; same applies for 6305de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 631a10cf76eSAxel Dörfler */ 632a10cf76eSAxel Dörfler void 6335de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 634a10cf76eSAxel Dörfler { 6351fc4cb1fSAxel Dörfler int32 supportsAnything = false; 6361fc4cb1fSAxel Dörfler int32 index = 0; 6371fc4cb1fSAxel Dörfler 638a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 6391fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 6401fc4cb1fSAxel Dörfler continue; 6411fc4cb1fSAxel Dörfler 642a10cf76eSAxel Dörfler bool supported = false; 643a10cf76eSAxel Dörfler 644a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 645a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 646a10cf76eSAxel Dörfler 647a10cf76eSAxel Dörfler if (fSelected.width == mode.width 648a10cf76eSAxel Dörfler && fSelected.height == mode.height 6491fc4cb1fSAxel Dörfler && kColorSpaces[i].space == mode.space 650a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 6511fc4cb1fSAxel Dörfler supportsAnything = true; 652a10cf76eSAxel Dörfler supported = true; 653a10cf76eSAxel Dörfler break; 654a10cf76eSAxel Dörfler } 655a10cf76eSAxel Dörfler } 656a10cf76eSAxel Dörfler 6571fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(index++); 658a10cf76eSAxel Dörfler if (item) 659a10cf76eSAxel Dörfler item->SetEnabled(supported); 660a10cf76eSAxel Dörfler } 6611fc4cb1fSAxel Dörfler 6621fc4cb1fSAxel Dörfler fColorsField->SetEnabled(supportsAnything); 6631fc4cb1fSAxel Dörfler 6641fc4cb1fSAxel Dörfler if (!supportsAnything) 6651fc4cb1fSAxel Dörfler return; 6661fc4cb1fSAxel Dörfler 6671fc4cb1fSAxel Dörfler // Make sure a valid item is selected 6681fc4cb1fSAxel Dörfler 6691fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->FindMarked(); 6701fc4cb1fSAxel Dörfler bool changed = false; 6711fc4cb1fSAxel Dörfler 6721fc4cb1fSAxel Dörfler if (item != fUserSelectedColorSpace) { 6731fc4cb1fSAxel Dörfler if (fUserSelectedColorSpace != NULL 6741fc4cb1fSAxel Dörfler && fUserSelectedColorSpace->IsEnabled()) { 6751fc4cb1fSAxel Dörfler fUserSelectedColorSpace->SetMarked(true); 6761fc4cb1fSAxel Dörfler item = fUserSelectedColorSpace; 6771fc4cb1fSAxel Dörfler changed = true; 6781fc4cb1fSAxel Dörfler } 6791fc4cb1fSAxel Dörfler } 6801fc4cb1fSAxel Dörfler if (item != NULL && !item->IsEnabled()) { 6811fc4cb1fSAxel Dörfler // find the next best item 6821fc4cb1fSAxel Dörfler int32 index = fColorsMenu->IndexOf(item); 6831fc4cb1fSAxel Dörfler bool found = false; 6841fc4cb1fSAxel Dörfler 6851fc4cb1fSAxel Dörfler for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) { 6861fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6871fc4cb1fSAxel Dörfler if (item->IsEnabled()) { 6881fc4cb1fSAxel Dörfler found = true; 6891fc4cb1fSAxel Dörfler break; 6901fc4cb1fSAxel Dörfler } 6911fc4cb1fSAxel Dörfler } 6921fc4cb1fSAxel Dörfler if (!found) { 6931fc4cb1fSAxel Dörfler // search backwards as well 6941fc4cb1fSAxel Dörfler for (int32 i = index - 1; i >= 0; i--) { 6951fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6961fc4cb1fSAxel Dörfler if (item->IsEnabled()) 6971fc4cb1fSAxel Dörfler break; 6981fc4cb1fSAxel Dörfler } 6991fc4cb1fSAxel Dörfler } 7001fc4cb1fSAxel Dörfler 7011fc4cb1fSAxel Dörfler item->SetMarked(true); 7021fc4cb1fSAxel Dörfler changed = true; 7031fc4cb1fSAxel Dörfler } 7041fc4cb1fSAxel Dörfler 7051fc4cb1fSAxel Dörfler if (changed) { 7061fc4cb1fSAxel Dörfler // Update selected space 7071fc4cb1fSAxel Dörfler 7081fc4cb1fSAxel Dörfler BMessage* message = item->Message(); 7091fc4cb1fSAxel Dörfler int32 space; 7101fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) == B_OK) { 7111fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 7121fc4cb1fSAxel Dörfler _UpdateColorLabel(); 7131fc4cb1fSAxel Dörfler } 7141fc4cb1fSAxel Dörfler } 715a10cf76eSAxel Dörfler } 716a10cf76eSAxel Dörfler 717a10cf76eSAxel Dörfler 7185de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 719a10cf76eSAxel Dörfler void 7205de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 721a10cf76eSAxel Dörfler { 72229e8a73aSAxel Dörfler float min, max; 72329e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 72429e8a73aSAxel Dörfler return; 725a10cf76eSAxel Dörfler 72629e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 72729e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 72829e8a73aSAxel Dörfler BMessage* message = item->Message(); 72929e8a73aSAxel Dörfler float refresh; 73029e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 73129e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 732a10cf76eSAxel Dörfler } 733a10cf76eSAxel Dörfler } 734a10cf76eSAxel Dörfler 735a10cf76eSAxel Dörfler 7365de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 737a10cf76eSAxel Dörfler void 7385de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 739a10cf76eSAxel Dörfler { 7407e44de36SRene Gollent for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) { 7417e44de36SRene Gollent BMenuItem* item = fRefreshMenu->ItemAt(i); 7427e44de36SRene Gollent if (item->Message()->FindFloat("refresh") == fSelected.refresh) { 743a10cf76eSAxel Dörfler item->SetMarked(true); 74426747978SAdrien Destugues // "Other" items only contains a refresh rate when active 745122d4ef7SMurai Takashi if (fOtherRefresh != NULL) 74626747978SAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 747a10cf76eSAxel Dörfler return; 748a10cf76eSAxel Dörfler } 7497e44de36SRene Gollent } 750a10cf76eSAxel Dörfler 751a10cf76eSAxel Dörfler // this is a non-standard refresh rate 7527e44de36SRene Gollent if (fOtherRefresh != NULL) { 753a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 754a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 755a10cf76eSAxel Dörfler 7567e44de36SRene Gollent BString string; 7577e44de36SRene Gollent refresh_rate_to_string(fSelected.refresh, string); 758a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 759a10cf76eSAxel Dörfler 760c9e8f97aSAdrien Destugues string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS)); 761a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 762a10cf76eSAxel Dörfler } 7637e44de36SRene Gollent } 764a10cf76eSAxel Dörfler 765a10cf76eSAxel Dörfler 766a10cf76eSAxel Dörfler void 7675de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 768a10cf76eSAxel Dörfler { 769a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 770a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 771a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 772a10cf76eSAxel Dörfler 773a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 774a10cf76eSAxel Dörfler } 775a10cf76eSAxel Dörfler 776a10cf76eSAxel Dörfler 777a10cf76eSAxel Dörfler void 7785de171daSAxel Dörfler ScreenWindow::_UpdateControls() 779a10cf76eSAxel Dörfler { 780b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 781b21d610eSAxel Dörfler 782a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 783c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 784a10cf76eSAxel Dörfler item->SetMarked(true); 785a10cf76eSAxel Dörfler 786a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 787c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 788a10cf76eSAxel Dörfler item->SetMarked(true); 789a10cf76eSAxel Dörfler 790a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 791a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 792a10cf76eSAxel Dörfler 793a10cf76eSAxel Dörfler uint32 tvStandard; 794a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 795a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 796a10cf76eSAxel Dörfler if (!item->IsMarked()) 797a10cf76eSAxel Dörfler item->SetMarked(true); 798a10cf76eSAxel Dörfler break; 799a10cf76eSAxel Dörfler } 800a10cf76eSAxel Dörfler } 801a10cf76eSAxel Dörfler 8025de171daSAxel Dörfler _CheckResolutionMenu(); 8035de171daSAxel Dörfler _CheckColorMenu(); 8045de171daSAxel Dörfler _CheckRefreshMenu(); 805a10cf76eSAxel Dörfler 806a10cf76eSAxel Dörfler BString string; 807a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 808a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 809a10cf76eSAxel Dörfler 810a10cf76eSAxel Dörfler if (item != NULL) { 811a10cf76eSAxel Dörfler if (!item->IsMarked()) 812a10cf76eSAxel Dörfler item->SetMarked(true); 813a10cf76eSAxel Dörfler } else { 814a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 815a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 816a10cf76eSAxel Dörfler // 1. add a new resolution to list 817a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 818a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 819a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 820a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 821a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 822a10cf76eSAxel Dörfler // 2. choose nearest resolution 823a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 824a10cf76eSAxel Dörfler // 3. choose lowest resolution 825a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 826a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 827a10cf76eSAxel Dörfler if (item) 828a10cf76eSAxel Dörfler item->SetMarked(true); 829a10cf76eSAxel Dörfler 830a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 831a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 832a10cf76eSAxel Dörfler } 833a10cf76eSAxel Dörfler 834a10cf76eSAxel Dörfler // mark active combine mode 835a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 836a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 837a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 838c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 839a10cf76eSAxel Dörfler item->SetMarked(true); 840a10cf76eSAxel Dörfler break; 841a10cf76eSAxel Dörfler } 842a10cf76eSAxel Dörfler } 843a10cf76eSAxel Dörfler 844a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 845a10cf76eSAxel Dörfler 8461fc4cb1fSAxel Dörfler for (int32 i = 0, index = 0; i < kColorSpaceCount; i++) { 8471fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 8481fc4cb1fSAxel Dörfler continue; 8491fc4cb1fSAxel Dörfler 8501fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 8511fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(index); 852a10cf76eSAxel Dörfler break; 853a10cf76eSAxel Dörfler } 8541fc4cb1fSAxel Dörfler 8551fc4cb1fSAxel Dörfler index++; 856a10cf76eSAxel Dörfler } 857a10cf76eSAxel Dörfler 858c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 859a10cf76eSAxel Dörfler item->SetMarked(true); 860a10cf76eSAxel Dörfler 8611fc4cb1fSAxel Dörfler _UpdateColorLabel(); 8625de171daSAxel Dörfler _UpdateMonitorView(); 8635de171daSAxel Dörfler _UpdateRefreshControl(); 864a10cf76eSAxel Dörfler 8655de171daSAxel Dörfler _CheckApplyEnabled(); 866a10cf76eSAxel Dörfler } 867a10cf76eSAxel Dörfler 868a10cf76eSAxel Dörfler 86912580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 870a10cf76eSAxel Dörfler void 8715de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 872a10cf76eSAxel Dörfler { 873c491b5adSJohn Scipione _UpdateActiveMode(current_workspace()); 874c491b5adSJohn Scipione } 875c491b5adSJohn Scipione 876c491b5adSJohn Scipione 877c491b5adSJohn Scipione void 878c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace) 879c491b5adSJohn Scipione { 88012580984SAxel Dörfler // Usually, this function gets called after a mode 881a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 882a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 883a10cf76eSAxel Dörfler // what kind of mode we actually got 884c491b5adSJohn Scipione if (fScreenMode.Get(fActive, workspace) == B_OK) { 885a10cf76eSAxel Dörfler fSelected = fActive; 886a10cf76eSAxel Dörfler 88712966d04SAxel Dörfler _UpdateMonitor(); 888c491b5adSJohn Scipione _BuildSupportedColorSpaces(); 8895de171daSAxel Dörfler _UpdateControls(); 890a10cf76eSAxel Dörfler } 891c491b5adSJohn Scipione } 892a10cf76eSAxel Dörfler 893a10cf76eSAxel Dörfler 894a10cf76eSAxel Dörfler void 895b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons() 896b21d610eSAxel Dörfler { 897b21d610eSAxel Dörfler uint32 columns; 898b21d610eSAxel Dörfler uint32 rows; 899b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 900b21d610eSAxel Dörfler 901a3fa81bdSJohn Scipione // Set the max values enabling/disabling the up/down arrows 902b21d610eSAxel Dörfler 903a3fa81bdSJohn Scipione if (rows == 1) 904a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(32); 905a3fa81bdSJohn Scipione else if (rows == 2) 906a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(16); 907a3fa81bdSJohn Scipione else if (rows <= 4) 908a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(8); 909a3fa81bdSJohn Scipione else if (rows <= 8) 910a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(4); 911a3fa81bdSJohn Scipione else if (rows <= 16) 912a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(2); 913a3fa81bdSJohn Scipione else if (rows <= 32) 914a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(1); 915b21d610eSAxel Dörfler 916a3fa81bdSJohn Scipione if (columns == 1) 917a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(32); 918a3fa81bdSJohn Scipione else if (columns == 2) 919a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(16); 920a3fa81bdSJohn Scipione else if (columns <= 4) 921a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(8); 922a3fa81bdSJohn Scipione else if (columns <= 8) 923a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(4); 924a3fa81bdSJohn Scipione else if (columns <= 16) 925a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(2); 926a3fa81bdSJohn Scipione else if (columns <= 32) 927a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(1); 928b21d610eSAxel Dörfler } 929b21d610eSAxel Dörfler 930b21d610eSAxel Dörfler 931b21d610eSAxel Dörfler void 932a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 933a10cf76eSAxel Dörfler { 934a10cf76eSAxel Dörfler // move window on screen, if necessary 935a10cf76eSAxel Dörfler if (frame.right <= Frame().right 936a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 937a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 938a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 939a10cf76eSAxel Dörfler } 940a10cf76eSAxel Dörfler } 941a10cf76eSAxel Dörfler 942a10cf76eSAxel Dörfler 943a10cf76eSAxel Dörfler void 944a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 945a10cf76eSAxel Dörfler { 946c491b5adSJohn Scipione if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) { 947c491b5adSJohn Scipione _UpdateActiveMode(workspace); 948a10cf76eSAxel Dörfler 9496edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 9506edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 951a10cf76eSAxel Dörfler } 952c491b5adSJohn Scipione } 953a10cf76eSAxel Dörfler 954a10cf76eSAxel Dörfler 955a10cf76eSAxel Dörfler void 956a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 957a10cf76eSAxel Dörfler { 958a10cf76eSAxel Dörfler switch (message->what) { 959a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 9605de171daSAxel Dörfler _CheckApplyEnabled(); 961a10cf76eSAxel Dörfler break; 962a10cf76eSAxel Dörfler 963b21d610eSAxel Dörfler case kMsgWorkspaceColumnsChanged: 964b21d610eSAxel Dörfler { 965a3fa81bdSJohn Scipione uint32 newColumns = (uint32)fColumnsControl->Value(); 966b21d610eSAxel Dörfler 967b21d610eSAxel Dörfler uint32 rows; 968b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(NULL, &rows); 969b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, rows); 970b21d610eSAxel Dörfler 971b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 972a3fa81bdSJohn Scipione fRowsControl->SetValue(rows); 973a3fa81bdSJohn Scipione // enables/disables up/down arrows 974b21d610eSAxel Dörfler _CheckApplyEnabled(); 975a3fa81bdSJohn Scipione 976b21d610eSAxel Dörfler break; 977b21d610eSAxel Dörfler } 978b21d610eSAxel Dörfler 979b21d610eSAxel Dörfler case kMsgWorkspaceRowsChanged: 980b21d610eSAxel Dörfler { 981a3fa81bdSJohn Scipione uint32 newRows = (uint32)fRowsControl->Value(); 982b21d610eSAxel Dörfler 983b21d610eSAxel Dörfler uint32 columns; 984b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, NULL); 985b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(columns, newRows); 986b21d610eSAxel Dörfler 987b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 988a3fa81bdSJohn Scipione fColumnsControl->SetValue(columns); 989a3fa81bdSJohn Scipione // enables/disables up/down arrows 990b21d610eSAxel Dörfler _CheckApplyEnabled(); 991a10cf76eSAxel Dörfler break; 992a10cf76eSAxel Dörfler } 993a10cf76eSAxel Dörfler 994a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 995a10cf76eSAxel Dörfler { 996a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 997a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 998a10cf76eSAxel Dörfler 9995de171daSAxel Dörfler _CheckColorMenu(); 10005de171daSAxel Dörfler _CheckRefreshMenu(); 1001a10cf76eSAxel Dörfler 10025de171daSAxel Dörfler _UpdateMonitorView(); 10035de171daSAxel Dörfler _UpdateRefreshControl(); 1004a10cf76eSAxel Dörfler 10055de171daSAxel Dörfler _CheckApplyEnabled(); 1006a10cf76eSAxel Dörfler break; 1007a10cf76eSAxel Dörfler } 1008a10cf76eSAxel Dörfler 1009a10cf76eSAxel Dörfler case POP_COLORS_MSG: 1010a10cf76eSAxel Dörfler { 10111fc4cb1fSAxel Dörfler int32 space; 10121fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) != B_OK) 10131fc4cb1fSAxel Dörfler break; 1014a10cf76eSAxel Dörfler 10151fc4cb1fSAxel Dörfler int32 index; 10161fc4cb1fSAxel Dörfler if (message->FindInt32("index", &index) == B_OK 10171fc4cb1fSAxel Dörfler && fColorsMenu->ItemAt(index) != NULL) 10181fc4cb1fSAxel Dörfler fUserSelectedColorSpace = fColorsMenu->ItemAt(index); 10191fc4cb1fSAxel Dörfler 10201fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 10211fc4cb1fSAxel Dörfler _UpdateColorLabel(); 1022a10cf76eSAxel Dörfler 10235de171daSAxel Dörfler _CheckApplyEnabled(); 1024a10cf76eSAxel Dörfler break; 1025a10cf76eSAxel Dörfler } 1026a10cf76eSAxel Dörfler 1027a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 1028a40498e2SWaldemar Kornewald { 1029a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1030c9e8f97aSAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 10311fc4cb1fSAxel Dörfler // revert "Other…" label - it might have a refresh rate prefix 1032a10cf76eSAxel Dörfler 10335de171daSAxel Dörfler _CheckApplyEnabled(); 1034a10cf76eSAxel Dörfler break; 1035a40498e2SWaldemar Kornewald } 1036a10cf76eSAxel Dörfler 1037a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 1038a10cf76eSAxel Dörfler { 103929e8a73aSAxel Dörfler // make sure menu shows something useful 10405de171daSAxel Dörfler _UpdateRefreshControl(); 1041a10cf76eSAxel Dörfler 104229e8a73aSAxel Dörfler float min = 0, max = 999; 104329e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 104429e8a73aSAxel Dörfler if (min < gMinRefresh) 104529e8a73aSAxel Dörfler min = gMinRefresh; 104629e8a73aSAxel Dörfler if (max > gMaxRefresh) 104729e8a73aSAxel Dörfler max = gMaxRefresh; 104829e8a73aSAxel Dörfler 104970a2b1b5SAxel Dörfler monitor_info info; 105070a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 105170a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 105270a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 105370a2b1b5SAxel Dörfler } 105470a2b1b5SAxel Dörfler 1055c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 105670a2b1b5SAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, 105770a2b1b5SAxel Dörfler min, max); 1058a10cf76eSAxel Dörfler fRefreshWindow->Show(); 1059a10cf76eSAxel Dörfler break; 1060a10cf76eSAxel Dörfler } 1061a10cf76eSAxel Dörfler 1062a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 1063a10cf76eSAxel Dörfler { 1064a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 1065a10cf76eSAxel Dörfler // select the refresh rate chosen 1066a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1067a10cf76eSAxel Dörfler 10685de171daSAxel Dörfler _UpdateRefreshControl(); 10695de171daSAxel Dörfler _CheckApplyEnabled(); 1070a10cf76eSAxel Dörfler break; 1071a10cf76eSAxel Dörfler } 1072a10cf76eSAxel Dörfler 1073a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 1074a10cf76eSAxel Dörfler { 1075a10cf76eSAxel Dörfler // new combine mode has bee chosen 1076a10cf76eSAxel Dörfler int32 mode; 1077a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 1078a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 1079a10cf76eSAxel Dörfler 10805de171daSAxel Dörfler _CheckResolutionMenu(); 10815de171daSAxel Dörfler _CheckApplyEnabled(); 1082a10cf76eSAxel Dörfler break; 1083a10cf76eSAxel Dörfler } 1084a10cf76eSAxel Dörfler 1085a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 1086a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 10875de171daSAxel Dörfler _CheckApplyEnabled(); 1088a10cf76eSAxel Dörfler break; 1089a10cf76eSAxel Dörfler 1090a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 1091a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 10925de171daSAxel Dörfler _CheckApplyEnabled(); 1093a10cf76eSAxel Dörfler break; 1094a10cf76eSAxel Dörfler 1095a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 1096a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 10975de171daSAxel Dörfler _CheckApplyEnabled(); 1098a10cf76eSAxel Dörfler break; 1099a10cf76eSAxel Dörfler 1100df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 11016f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 11026f095d6aSRyan Leavengood app_info info; 11036f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 11046f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 11056f095d6aSRyan Leavengood } 1106df3f5bacSStephan Aßmus break; 1107df3f5bacSStephan Aßmus 1108a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 1109a10cf76eSAxel Dörfler { 11104be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 1111a10cf76eSAxel Dörfler fSelected.width = 640; 1112a10cf76eSAxel Dörfler fSelected.height = 480; 1113a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 1114a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 1115a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 1116a10cf76eSAxel Dörfler fSelected.swap_displays = false; 1117a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 1118a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 1119a10cf76eSAxel Dörfler 1120b21d610eSAxel Dörfler // TODO: workspace defaults 1121abc649b8SWaldemar Kornewald 11225de171daSAxel Dörfler _UpdateControls(); 1123a10cf76eSAxel Dörfler break; 1124a10cf76eSAxel Dörfler } 1125a10cf76eSAxel Dörfler 112610e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 112761c5c89bSAxel Dörfler fUndoScreenMode.Revert(); 11285de171daSAxel Dörfler _UpdateActiveMode(); 1129abc649b8SWaldemar Kornewald break; 1130abc649b8SWaldemar Kornewald 1131abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 1132abc649b8SWaldemar Kornewald { 1133abc649b8SWaldemar Kornewald fModified = false; 1134199893c3SAxel Dörfler fBootWorkspaceApplied = false; 1135abc649b8SWaldemar Kornewald 1136b21d610eSAxel Dörfler // ScreenMode::Revert() assumes that we first set the correct 1137b21d610eSAxel Dörfler // number of workspaces 1138b21d610eSAxel Dörfler 1139b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns, 1140b21d610eSAxel Dörfler fOriginalWorkspacesRows); 1141b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 1142b21d610eSAxel Dörfler 1143a10cf76eSAxel Dörfler fScreenMode.Revert(); 11445de171daSAxel Dörfler _UpdateActiveMode(); 11453a2b67b5SAdrien Destugues 11463a2b67b5SAdrien Destugues BScreen screen(this); 11473a2b67b5SAdrien Destugues screen.SetBrightness(fOriginalBrightness); 11483a2b67b5SAdrien Destugues fBrightnessSlider->SetValue(fOriginalBrightness * 255); 1149a10cf76eSAxel Dörfler break; 1150abc649b8SWaldemar Kornewald } 1151a10cf76eSAxel Dörfler 1152a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 11535de171daSAxel Dörfler _Apply(); 1154a10cf76eSAxel Dörfler break; 1155a10cf76eSAxel Dörfler 1156abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 1157abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 1158abc649b8SWaldemar Kornewald fModified = true; 11595de171daSAxel Dörfler _UpdateActiveMode(); 1160a10cf76eSAxel Dörfler break; 1161a10cf76eSAxel Dörfler 1162b8a61399SBrian Hill case UPDATE_DESKTOP_COLOR_MSG: 1163b8a61399SBrian Hill PostMessage(message, fMonitorView); 1164b8a61399SBrian Hill break; 1165b8a61399SBrian Hill 11663a2b67b5SAdrien Destugues case SLIDER_BRIGHTNESS_MSG: 11673a2b67b5SAdrien Destugues { 11683a2b67b5SAdrien Destugues BScreen screen(this); 11693a2b67b5SAdrien Destugues screen.SetBrightness(message->FindInt32("be:value") / 255.f); 11703a2b67b5SAdrien Destugues _CheckApplyEnabled(); 11713a2b67b5SAdrien Destugues break; 11723a2b67b5SAdrien Destugues } 11733a2b67b5SAdrien Destugues 1174a10cf76eSAxel Dörfler default: 1175a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 1176a10cf76eSAxel Dörfler } 1177a10cf76eSAxel Dörfler } 1178a10cf76eSAxel Dörfler 1179a10cf76eSAxel Dörfler 118012580984SAxel Dörfler status_t 118112580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 118212580984SAxel Dörfler { 118312580984SAxel Dörfler BPath path; 118412580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 118512580984SAxel Dörfler if (status < B_OK) 118612580984SAxel Dörfler return status; 118712580984SAxel Dörfler 118812580984SAxel Dörfler path.Append("kernel/drivers"); 118912580984SAxel Dörfler status = create_directory(path.Path(), 0755); 119012580984SAxel Dörfler if (status < B_OK) 119112580984SAxel Dörfler return status; 119212580984SAxel Dörfler 119312580984SAxel Dörfler path.Append("vesa"); 119412580984SAxel Dörfler BFile file; 119512580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 119612580984SAxel Dörfler if (status < B_OK) 119712580984SAxel Dörfler return status; 119812580984SAxel Dörfler 119912580984SAxel Dörfler char buffer[256]; 12005084d0d4SAlex Smith snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %" 12015084d0d4SAlex Smith B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel()); 120212580984SAxel Dörfler 120312580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 120412580984SAxel Dörfler if (bytesWritten < B_OK) 120512580984SAxel Dörfler return bytesWritten; 120612580984SAxel Dörfler 120712580984SAxel Dörfler return B_OK; 120812580984SAxel Dörfler } 120912580984SAxel Dörfler 121012580984SAxel Dörfler 1211a10cf76eSAxel Dörfler void 12121fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces() 12131fc4cb1fSAxel Dörfler { 12141fc4cb1fSAxel Dörfler fSupportedColorSpaces = 0; 12151fc4cb1fSAxel Dörfler 12161fc4cb1fSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 12171fc4cb1fSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 12181fc4cb1fSAxel Dörfler if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) { 12191fc4cb1fSAxel Dörfler fSupportedColorSpaces |= 1 << i; 12201fc4cb1fSAxel Dörfler break; 12211fc4cb1fSAxel Dörfler } 12221fc4cb1fSAxel Dörfler } 12231fc4cb1fSAxel Dörfler } 12241fc4cb1fSAxel Dörfler } 12251fc4cb1fSAxel Dörfler 12261fc4cb1fSAxel Dörfler 12271fc4cb1fSAxel Dörfler void 12285de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1229a10cf76eSAxel Dörfler { 123095ef5044SJanus bool applyEnabled = true; 123195ef5044SJanus 123295ef5044SJanus if (fSelected == fActive) { 123395ef5044SJanus applyEnabled = false; 123495ef5044SJanus if (fAllWorkspacesItem->IsMarked()) { 123595ef5044SJanus screen_mode screenMode; 123695ef5044SJanus const int32 workspaceCount = count_workspaces(); 123795ef5044SJanus for (int32 i = 0; i < workspaceCount; i++) { 123895ef5044SJanus fScreenMode.Get(screenMode, i); 123995ef5044SJanus if (screenMode != fSelected) { 124095ef5044SJanus applyEnabled = true; 124195ef5044SJanus break; 124295ef5044SJanus } 124395ef5044SJanus } 124495ef5044SJanus } 124595ef5044SJanus } 124695ef5044SJanus 124795ef5044SJanus fApplyButton->SetEnabled(applyEnabled); 1248b21d610eSAxel Dörfler 1249b21d610eSAxel Dörfler uint32 columns; 1250b21d610eSAxel Dörfler uint32 rows; 1251b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 1252b21d610eSAxel Dörfler 12533a2b67b5SAdrien Destugues BScreen screen(this); 12543a2b67b5SAdrien Destugues float brightness = -1; 12553a2b67b5SAdrien Destugues screen.GetBrightness(&brightness); 12563a2b67b5SAdrien Destugues 1257b21d610eSAxel Dörfler fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns 1258b21d610eSAxel Dörfler || rows != fOriginalWorkspacesRows 12593a2b67b5SAdrien Destugues || brightness != fOriginalBrightness 12605de171daSAxel Dörfler || fSelected != fOriginal); 1261a10cf76eSAxel Dörfler } 1262a10cf76eSAxel Dörfler 1263a10cf76eSAxel Dörfler 1264a10cf76eSAxel Dörfler void 12655de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1266abc649b8SWaldemar Kornewald { 1267b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns, 1268b21d610eSAxel Dörfler &fOriginalWorkspacesRows); 1269b21d610eSAxel Dörfler 1270abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1271abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1272abc649b8SWaldemar Kornewald } 1273abc649b8SWaldemar Kornewald 1274abc649b8SWaldemar Kornewald 1275abc649b8SWaldemar Kornewald void 127612966d04SAxel Dörfler ScreenWindow::_UpdateMonitor() 127712966d04SAxel Dörfler { 127812966d04SAxel Dörfler monitor_info info; 127912966d04SAxel Dörfler float diagonalInches; 128012966d04SAxel Dörfler status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches); 128155030977SAxel Dörfler if (status == B_OK) { 12821a8af605SAxel Dörfler char text[512]; 128366ab1666SAxel Dörfler snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor, 128466ab1666SAxel Dörfler info.name[0] ? " " : "", info.name, diagonalInches); 128512966d04SAxel Dörfler 128612966d04SAxel Dörfler fMonitorInfo->SetText(text); 128712966d04SAxel Dörfler 12888bf216d6SAxel Dörfler if (fMonitorInfo->IsHidden(fMonitorInfo)) 128912966d04SAxel Dörfler fMonitorInfo->Show(); 129055030977SAxel Dörfler } else { 12918bf216d6SAxel Dörfler if (!fMonitorInfo->IsHidden(fMonitorInfo)) 129255030977SAxel Dörfler fMonitorInfo->Hide(); 129355030977SAxel Dörfler } 1294af8f9c31SAxel Dörfler 12958b46ee25SAdrien Destugues // Add info about the graphics device 12968b46ee25SAdrien Destugues 12978b46ee25SAdrien Destugues accelerant_device_info deviceInfo; 12988b46ee25SAdrien Destugues 12998b46ee25SAdrien Destugues if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK) { 13008b46ee25SAdrien Destugues BString deviceString; 13018b46ee25SAdrien Destugues 13028b46ee25SAdrien Destugues if (deviceInfo.name[0] && deviceInfo.chipset[0]) { 13038b46ee25SAdrien Destugues deviceString.SetToFormat("%s (%s)", deviceInfo.name, 13048b46ee25SAdrien Destugues deviceInfo.chipset); 13058b46ee25SAdrien Destugues } else if (deviceInfo.name[0] || deviceInfo.chipset[0]) { 13068b46ee25SAdrien Destugues deviceString 13078b46ee25SAdrien Destugues = deviceInfo.name[0] ? deviceInfo.name : deviceInfo.chipset; 13088b46ee25SAdrien Destugues } 13098b46ee25SAdrien Destugues 13108b46ee25SAdrien Destugues fDeviceInfo->SetText(deviceString); 13118b46ee25SAdrien Destugues } 13128b46ee25SAdrien Destugues 13138b46ee25SAdrien Destugues 131455030977SAxel Dörfler char text[512]; 13151a8af605SAxel Dörfler size_t length = 0; 13161a8af605SAxel Dörfler text[0] = 0; 13171a8af605SAxel Dörfler 131855030977SAxel Dörfler if (status == B_OK) { 1319af8f9c31SAxel Dörfler if (info.min_horizontal_frequency != 0 1320af8f9c31SAxel Dörfler && info.min_vertical_frequency != 0 1321af8f9c31SAxel Dörfler && info.max_pixel_clock != 0) { 13221a8af605SAxel Dörfler length = snprintf(text, sizeof(text), 1323c9e8f97aSAdrien Destugues B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n" 13249c1a9b92SAdrien Destugues "Vertical frequency:\t%lu - %lu Hz\n\n" 1325c9e8f97aSAdrien Destugues "Maximum pixel clock:\t%g MHz"), 13261a8af605SAxel Dörfler info.min_horizontal_frequency, info.max_horizontal_frequency, 13271a8af605SAxel Dörfler info.min_vertical_frequency, info.max_vertical_frequency, 13281a8af605SAxel Dörfler info.max_pixel_clock / 1000.0); 1329af8f9c31SAxel Dörfler } 13301a8af605SAxel Dörfler if (info.serial_number[0] && length < sizeof(text)) { 13311a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 1332c9e8f97aSAdrien Destugues B_TRANSLATE("%sSerial no.: %s"), length ? "\n\n" : "", 13331a8af605SAxel Dörfler info.serial_number); 13341a8af605SAxel Dörfler if (info.produced.week != 0 && info.produced.year != 0 13351a8af605SAxel Dörfler && length < sizeof(text)) { 13361a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 13371a8af605SAxel Dörfler " (%u/%u)", info.produced.week, info.produced.year); 13381a8af605SAxel Dörfler } 13391a8af605SAxel Dörfler } 134055030977SAxel Dörfler } 134161c5c89bSAxel Dörfler 13421a8af605SAxel Dörfler if (text[0]) 13431a8af605SAxel Dörfler fMonitorView->SetToolTip(text); 134412966d04SAxel Dörfler } 134512966d04SAxel Dörfler 134612966d04SAxel Dörfler 134712966d04SAxel Dörfler void 13481fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel() 13491fc4cb1fSAxel Dörfler { 13501fc4cb1fSAxel Dörfler BString string; 1351551c9f15SSiarzhuk Zharski string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel"); 13521fc4cb1fSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 13531fc4cb1fSAxel Dörfler } 13541fc4cb1fSAxel Dörfler 13551fc4cb1fSAxel Dörfler 13561fc4cb1fSAxel Dörfler void 13575de171daSAxel Dörfler ScreenWindow::_Apply() 1358a10cf76eSAxel Dörfler { 1359abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 136061c5c89bSAxel Dörfler fUndoScreenMode.UpdateOriginalModes(); 136161c5c89bSAxel Dörfler 136207184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 136307184a9eSAxel Dörfler if (status == B_OK) { 1364abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1365abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1366abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1367abc649b8SWaldemar Kornewald display_mode newMode; 1368abc649b8SWaldemar Kornewald BScreen screen(this); 1369abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1370abc649b8SWaldemar Kornewald 1371abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1372abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 137395ef5044SJanus const int32 workspaceCount = count_workspaces(); 137495ef5044SJanus for (int32 i = 0; i < workspaceCount; i++) { 1375abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1376abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1377abc649b8SWaldemar Kornewald } 1378199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1379199893c3SAxel Dörfler } else { 1380199893c3SAxel Dörfler if (current_workspace() == 0) 1381199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1382abc649b8SWaldemar Kornewald } 1383abc649b8SWaldemar Kornewald 1384a10cf76eSAxel Dörfler fActive = fSelected; 1385a10cf76eSAxel Dörfler 1386abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 138741f43d56SAugustin Cavalier BAlert* window = new AlertWindow(this); 138841f43d56SAugustin Cavalier window->Go(NULL); 138907184a9eSAxel Dörfler } else { 139007184a9eSAxel Dörfler char message[256]; 139107184a9eSAxel Dörfler snprintf(message, sizeof(message), 1392c9e8f97aSAdrien Destugues B_TRANSLATE("The screen mode could not be set:\n\t%s\n"), 1393c9e8f97aSAdrien Destugues screen_errors(status)); 1394551c9f15SSiarzhuk Zharski BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message, 1395c9e8f97aSAdrien Destugues B_TRANSLATE("OK"), NULL, NULL, 139607184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 1397aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 139807184a9eSAxel Dörfler alert->Go(); 1399a10cf76eSAxel Dörfler } 140007184a9eSAxel Dörfler } 1401