1a10cf76eSAxel Dörfler /* 2a3fa81bdSJohn Scipione * Copyright 2001-2014 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 229c9e8f97aSAdrien Destugues fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), 230551c9f15SSiarzhuk Zharski "monitor", screen.Frame().IntegerWidth() + 1, 231c9e8f97aSAdrien Destugues screen.Frame().IntegerHeight() + 1); 232b21d610eSAxel Dörfler screenBox->AddChild(fMonitorView); 2335a78744bSAxel Dörfler 234e1c88201SJohn Scipione BStringView* workspaces = new BStringView("workspaces", 235e1c88201SJohn Scipione B_TRANSLATE("Workspaces")); 236e1c88201SJohn Scipione workspaces->SetAlignment(B_ALIGN_CENTER); 237e1c88201SJohn Scipione 238a3fa81bdSJohn Scipione fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"), 239b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceColumnsChanged)); 240a3fa81bdSJohn Scipione fColumnsControl->SetAlignment(B_ALIGN_RIGHT); 241a3fa81bdSJohn Scipione fColumnsControl->SetRange(1, 32); 242b21d610eSAxel Dörfler 243a3fa81bdSJohn Scipione fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"), 244a3fa81bdSJohn Scipione new BMessage(kMsgWorkspaceRowsChanged)); 245a3fa81bdSJohn Scipione fRowsControl->SetAlignment(B_ALIGN_RIGHT); 246a3fa81bdSJohn Scipione fRowsControl->SetRange(1, 32); 247a3fa81bdSJohn Scipione 248a3fa81bdSJohn Scipione uint32 columns; 249a3fa81bdSJohn Scipione uint32 rows; 250a3fa81bdSJohn Scipione BPrivate::get_workspaces_layout(&columns, &rows); 251a3fa81bdSJohn Scipione fColumnsControl->SetValue(columns); 252a3fa81bdSJohn Scipione fRowsControl->SetValue(rows); 253a3fa81bdSJohn Scipione 254e1c88201SJohn Scipione screenBox->AddChild(BLayoutBuilder::Group<>() 255e1c88201SJohn Scipione .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING) 256e1c88201SJohn Scipione .Add(workspaces) 257a3fa81bdSJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 258e1c88201SJohn Scipione // columns 259e1c88201SJohn Scipione .Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0) 260a3fa81bdSJohn Scipione .Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0) 261e1c88201SJohn Scipione // rows 262e1c88201SJohn Scipione .Add(fRowsControl->CreateLabelLayoutItem(), 0, 1) 263a3fa81bdSJohn Scipione .Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1) 264b21d610eSAxel Dörfler .End() 26525fd5c7bSAlex Wilson .End() 26625fd5c7bSAlex Wilson .View()); 267b21d610eSAxel Dörfler 268b21d610eSAxel Dörfler fBackgroundsButton = new BButton("BackgroundsButton", 269c9e8f97aSAdrien Destugues B_TRANSLATE("Set background" B_UTF8_ELLIPSIS), 270b21d610eSAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 271b21d610eSAxel Dörfler fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 272b21d610eSAxel Dörfler screenBox->AddChild(fBackgroundsButton); 273a10cf76eSAxel Dörfler 274a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 275a10cf76eSAxel Dörfler 276b21d610eSAxel Dörfler BBox* controlsBox = new BBox("controls box"); 277b21d610eSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 2786048f541SJohn Scipione BGroupView* outerControlsView = new BGroupView(B_VERTICAL); 2796048f541SJohn Scipione outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING, 2806048f541SJohn Scipione B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); 281b21d610eSAxel Dörfler controlsBox->AddChild(outerControlsView); 282a10cf76eSAxel Dörfler 283551c9f15SSiarzhuk Zharski fResolutionMenu = new BPopUpMenu("resolution", true, true); 284a10cf76eSAxel Dörfler 28566ab1666SAxel Dörfler uint16 maxWidth = 0; 28666ab1666SAxel Dörfler uint16 maxHeight = 0; 28766ab1666SAxel Dörfler uint16 previousWidth = 0; 28866ab1666SAxel Dörfler uint16 previousHeight = 0; 289a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 290a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 291a10cf76eSAxel Dörfler 292a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 293a10cf76eSAxel Dörfler continue; 294a10cf76eSAxel Dörfler 295a10cf76eSAxel Dörfler previousWidth = mode.width; 296a10cf76eSAxel Dörfler previousHeight = mode.height; 29766ab1666SAxel Dörfler if (maxWidth < mode.width) 29866ab1666SAxel Dörfler maxWidth = mode.width; 29966ab1666SAxel Dörfler if (maxHeight < mode.height) 30066ab1666SAxel Dörfler maxHeight = mode.height; 301a10cf76eSAxel Dörfler 302a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_RESOLUTION_MSG); 303a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 304a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 305a10cf76eSAxel Dörfler 306a10cf76eSAxel Dörfler BString name; 307a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 308a10cf76eSAxel Dörfler 309a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 310a10cf76eSAxel Dörfler } 311a10cf76eSAxel Dörfler 31266ab1666SAxel Dörfler fMonitorView->SetMaxResolution(maxWidth, maxHeight); 31366ab1666SAxel Dörfler 314c9e8f97aSAdrien Destugues fResolutionField = new BMenuField("ResolutionMenu", 31510dfe897SAxel Dörfler B_TRANSLATE("Resolution:"), fResolutionMenu); 3166048f541SJohn Scipione fResolutionField->SetAlignment(B_ALIGN_RIGHT); 317a10cf76eSAxel Dörfler 318551c9f15SSiarzhuk Zharski fColorsMenu = new BPopUpMenu("colors", true, false); 319a10cf76eSAxel Dörfler 320a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 3211fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 3221fc4cb1fSAxel Dörfler continue; 3231fc4cb1fSAxel Dörfler 324a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_COLORS_MSG); 325a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 326a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 327a10cf76eSAxel Dörfler 3281fc4cb1fSAxel Dörfler BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); 3291fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == screen.ColorSpace()) 3301fc4cb1fSAxel Dörfler fUserSelectedColorSpace = item; 3311fc4cb1fSAxel Dörfler 3321fc4cb1fSAxel Dörfler fColorsMenu->AddItem(item); 333a10cf76eSAxel Dörfler } 334a10cf76eSAxel Dörfler 335c9e8f97aSAdrien Destugues fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"), 33610dfe897SAxel Dörfler fColorsMenu); 3376048f541SJohn Scipione fColorsField->SetAlignment(B_ALIGN_RIGHT); 338a10cf76eSAxel Dörfler 339551c9f15SSiarzhuk Zharski fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 340a10cf76eSAxel Dörfler 34129e8a73aSAxel Dörfler float min, max; 342ec495b30SRene Gollent if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) { 343ec495b30SRene Gollent // if we couldn't obtain the refresh limits, reset to the default 344ec495b30SRene Gollent // range. Constraints from detected monitors will fine-tune this 345ec495b30SRene Gollent // later. 346ec495b30SRene Gollent min = kRefreshRates[0]; 347ec495b30SRene Gollent max = kRefreshRates[kRefreshRateCount - 1]; 348ec495b30SRene Gollent } 349ec495b30SRene Gollent 350ec495b30SRene Gollent if (min == max) { 35129e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 35229e8a73aSAxel Dörfler // frequency, like the VESA driver 35329e8a73aSAxel Dörfler BString name; 3547e44de36SRene Gollent refresh_rate_to_string(min, name); 355cf076964SRene Gollent BMessage *message = new BMessage(POP_REFRESH_MSG); 356cf076964SRene Gollent message->AddFloat("refresh", min); 357cf076964SRene Gollent BMenuItem *item = new BMenuItem(name.String(), message); 3580efb8b66SJerome Duval fRefreshMenu->AddItem(item); 35929e8a73aSAxel Dörfler item->SetEnabled(false); 36029e8a73aSAxel Dörfler } else { 36170a2b1b5SAxel Dörfler monitor_info info; 36270a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 36370a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 36470a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 36570a2b1b5SAxel Dörfler } 36670a2b1b5SAxel Dörfler 367a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 36870a2b1b5SAxel Dörfler if (kRefreshRates[i] < min || kRefreshRates[i] > max) 36970a2b1b5SAxel Dörfler continue; 37070a2b1b5SAxel Dörfler 371a10cf76eSAxel Dörfler BString name; 372551c9f15SSiarzhuk Zharski name << kRefreshRates[i] << " " << B_TRANSLATE("Hz"); 373a10cf76eSAxel Dörfler 3740efb8b66SJerome Duval BMessage *message = new BMessage(POP_REFRESH_MSG); 375a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 376a10cf76eSAxel Dörfler 377a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 378a10cf76eSAxel Dörfler } 379a10cf76eSAxel Dörfler 380c9e8f97aSAdrien Destugues fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), 3810efb8b66SJerome Duval new BMessage(POP_OTHER_REFRESH_MSG)); 382a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 38329e8a73aSAxel Dörfler } 384a10cf76eSAxel Dörfler 385c9e8f97aSAdrien Destugues fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"), 38610dfe897SAxel Dörfler fRefreshMenu); 3876048f541SJohn Scipione fRefreshField->SetAlignment(B_ALIGN_RIGHT); 388b21d610eSAxel Dörfler 38912580984SAxel Dörfler if (_IsVesa()) 39012580984SAxel Dörfler fRefreshField->Hide(); 391a10cf76eSAxel Dörfler 392a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 393a10cf76eSAxel Dörfler { 394a10cf76eSAxel Dörfler bool dummy; 395a10cf76eSAxel Dörfler uint32 dummy32; 396a10cf76eSAxel Dörfler bool multiMonSupport; 397a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 398a10cf76eSAxel Dörfler bool tvStandardSupport; 399a10cf76eSAxel Dörfler 400a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 401a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 402a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 403a10cf76eSAxel Dörfler 404a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 405a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 406a10cf76eSAxel Dörfler 407551c9f15SSiarzhuk Zharski fCombineMenu = new BPopUpMenu("CombineDisplays", 408c9e8f97aSAdrien Destugues true, true); 409a10cf76eSAxel Dörfler 410a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 4110efb8b66SJerome Duval BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 412a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 413a10cf76eSAxel Dörfler 414d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 415d1516993SAxel Dörfler message)); 416a10cf76eSAxel Dörfler } 417a10cf76eSAxel Dörfler 418b21d610eSAxel Dörfler fCombineField = new BMenuField("CombineMenu", 41910dfe897SAxel Dörfler B_TRANSLATE("Combine displays:"), fCombineMenu); 4206048f541SJohn Scipione fCombineField->SetAlignment(B_ALIGN_RIGHT); 421a10cf76eSAxel Dörfler 422a10cf76eSAxel Dörfler if (!multiMonSupport) 423df3f5bacSStephan Aßmus fCombineField->Hide(); 424a10cf76eSAxel Dörfler 425551c9f15SSiarzhuk Zharski fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", 426c9e8f97aSAdrien Destugues true, true); 427a10cf76eSAxel Dörfler 428a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 4290efb8b66SJerome Duval BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG); 430a10cf76eSAxel Dörfler message->AddBool("swap", false); 431c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message)); 432a10cf76eSAxel Dörfler 433a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 434a10cf76eSAxel Dörfler message->AddBool("swap", true); 435c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message)); 436a10cf76eSAxel Dörfler 437c9e8f97aSAdrien Destugues fSwapDisplaysField = new BMenuField("SwapMenu", 43810dfe897SAxel Dörfler B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu); 4396048f541SJohn Scipione fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT); 440a10cf76eSAxel Dörfler 441a10cf76eSAxel Dörfler if (!multiMonSupport) 442df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 443a10cf76eSAxel Dörfler 444551c9f15SSiarzhuk Zharski fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", 445c9e8f97aSAdrien Destugues true, true); 446a10cf76eSAxel Dörfler 447a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 448a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 449a10cf76eSAxel Dörfler message->AddBool("use", false); 450c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"), 451c9e8f97aSAdrien Destugues message)); 452a10cf76eSAxel Dörfler 453a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 454a10cf76eSAxel Dörfler message->AddBool("use", true); 455c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"), 456c9e8f97aSAdrien Destugues message)); 457a10cf76eSAxel Dörfler 458b21d610eSAxel Dörfler fUseLaptopPanelField = new BMenuField("UseLaptopPanel", 45910dfe897SAxel Dörfler B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu); 4606048f541SJohn Scipione fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT); 461a10cf76eSAxel Dörfler 462a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 463df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 464a10cf76eSAxel Dörfler 465551c9f15SSiarzhuk Zharski fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 466a10cf76eSAxel Dörfler 467a10cf76eSAxel Dörfler // arbitrary limit 468a10cf76eSAxel Dörfler uint32 i; 469a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 470a10cf76eSAxel Dörfler uint32 mode; 471a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 472a10cf76eSAxel Dörfler break; 473a10cf76eSAxel Dörfler 474a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 475a10cf76eSAxel Dörfler 476a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 477a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 478a10cf76eSAxel Dörfler 479a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 480a10cf76eSAxel Dörfler } 481a10cf76eSAxel Dörfler 482c9e8f97aSAdrien Destugues fTVStandardField = new BMenuField("tv standard", 48310dfe897SAxel Dörfler B_TRANSLATE("Video format:"), fTVStandardMenu); 484df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 485a10cf76eSAxel Dörfler 486b21d610eSAxel Dörfler if (!tvStandardSupport || i == 0) 487df3f5bacSStephan Aßmus fTVStandardField->Hide(); 488a10cf76eSAxel Dörfler } 489a10cf76eSAxel Dörfler 49025fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 4916048f541SJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 4926048f541SJohn Scipione .Add(fResolutionField->CreateLabelLayoutItem(), 0, 0) 4936048f541SJohn Scipione .Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0) 4946048f541SJohn Scipione .Add(fColorsField->CreateLabelLayoutItem(), 0, 1) 4956048f541SJohn Scipione .Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1) 4966048f541SJohn Scipione .Add(fRefreshField->CreateLabelLayoutItem(), 0, 2) 4976048f541SJohn Scipione .Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2) 4986048f541SJohn Scipione .Add(fCombineField->CreateLabelLayoutItem(), 0, 3) 4996048f541SJohn Scipione .Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3) 5006048f541SJohn Scipione .Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4) 5016048f541SJohn Scipione .Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4) 5026048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5) 5036048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5) 5046048f541SJohn Scipione .Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6) 5056048f541SJohn Scipione .Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6) 50625fd5c7bSAlex Wilson .End(); 507df3f5bacSStephan Aßmus 508abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 509abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 510b21d610eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG));*/ 511a10cf76eSAxel Dörfler 512c9e8f97aSAdrien Destugues fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"), 513df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 514df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 51525fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 516b21d610eSAxel Dörfler .AddGlue() 51725fd5c7bSAlex Wilson .AddGroup(B_HORIZONTAL) 51825fd5c7bSAlex Wilson .AddGlue() 51925fd5c7bSAlex Wilson .Add(fApplyButton); 520b21d610eSAxel Dörfler 521c9e8f97aSAdrien Destugues fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"), 522b21d610eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 523b21d610eSAxel Dörfler fRevertButton->SetEnabled(false); 524b21d610eSAxel Dörfler 5254666484fSJohn Scipione BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) 5264666484fSJohn Scipione .AddGroup(B_HORIZONTAL) 527a2cb1737SAdrien Destugues .AddGroup(B_VERTICAL, 0, 1) 52883cc66b3SJohn Scipione .AddStrut(floorf(controlsBox->TopBorderOffset()) - 1) 529b21d610eSAxel Dörfler .Add(screenBox) 53083cc66b3SJohn Scipione .End() 531a2cb1737SAdrien Destugues .Add(controlsBox, 2) 532b21d610eSAxel Dörfler .End() 5334666484fSJohn Scipione .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 534b21d610eSAxel Dörfler .Add(fRevertButton) 5354666484fSJohn Scipione .AddGlue() 5364666484fSJohn Scipione .End() 5374666484fSJohn Scipione .SetInsets(B_USE_DEFAULT_SPACING); 538b21d610eSAxel Dörfler 5395de171daSAxel Dörfler _UpdateControls(); 54012966d04SAxel Dörfler _UpdateMonitor(); 541a10cf76eSAxel Dörfler } 542a10cf76eSAxel Dörfler 543a10cf76eSAxel Dörfler 544a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 545a10cf76eSAxel Dörfler { 546a10cf76eSAxel Dörfler delete fSettings; 547a10cf76eSAxel Dörfler } 548a10cf76eSAxel Dörfler 549a10cf76eSAxel Dörfler 550a10cf76eSAxel Dörfler bool 551a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 552a10cf76eSAxel Dörfler { 553a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 554199893c3SAxel Dörfler 555199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 556199893c3SAxel Dörfler screen_mode vesaMode; 557199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 558199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 55912580984SAxel Dörfler if (status < B_OK) { 560c9e8f97aSAdrien Destugues BString warning = B_TRANSLATE("Could not write VESA mode settings" 561c9e8f97aSAdrien Destugues " file:\n\t"); 56212580984SAxel Dörfler warning << strerror(status); 563aed35104SHumdinger BAlert* alert = new BAlert(B_TRANSLATE("Warning"), 564aed35104SHumdinger warning.String(), B_TRANSLATE("OK"), NULL, 565aed35104SHumdinger NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 566aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 567aed35104SHumdinger alert->Go(); 56812580984SAxel Dörfler } 56912580984SAxel Dörfler } 57012580984SAxel Dörfler 571a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 572a10cf76eSAxel Dörfler 573a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 574a10cf76eSAxel Dörfler } 575a10cf76eSAxel Dörfler 576a10cf76eSAxel Dörfler 5775de171daSAxel Dörfler /*! Update resolution list according to combine mode 5781fc4cb1fSAxel Dörfler (some resolutions may not be combinable due to memory restrictions). 579a10cf76eSAxel Dörfler */ 580a10cf76eSAxel Dörfler void 5815de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 582a10cf76eSAxel Dörfler { 583a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 584a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 585a10cf76eSAxel Dörfler 586a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 587a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 588a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 589a10cf76eSAxel Dörfler continue; 590a10cf76eSAxel Dörfler 591a10cf76eSAxel Dörfler BString name; 592a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 593a10cf76eSAxel Dörfler 594a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 595a10cf76eSAxel Dörfler if (item != NULL) 596a10cf76eSAxel Dörfler item->SetEnabled(true); 597a10cf76eSAxel Dörfler } 598a10cf76eSAxel Dörfler } 599a10cf76eSAxel Dörfler 600a10cf76eSAxel Dörfler 6015de171daSAxel Dörfler /*! Update color and refresh options according to current mode 6025de171daSAxel Dörfler (a color space is made active if there is any mode with 6035de171daSAxel Dörfler given resolution and this colour space; same applies for 6045de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 605a10cf76eSAxel Dörfler */ 606a10cf76eSAxel Dörfler void 6075de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 608a10cf76eSAxel Dörfler { 6091fc4cb1fSAxel Dörfler int32 supportsAnything = false; 6101fc4cb1fSAxel Dörfler int32 index = 0; 6111fc4cb1fSAxel Dörfler 612a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 6131fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 6141fc4cb1fSAxel Dörfler continue; 6151fc4cb1fSAxel Dörfler 616a10cf76eSAxel Dörfler bool supported = false; 617a10cf76eSAxel Dörfler 618a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 619a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 620a10cf76eSAxel Dörfler 621a10cf76eSAxel Dörfler if (fSelected.width == mode.width 622a10cf76eSAxel Dörfler && fSelected.height == mode.height 6231fc4cb1fSAxel Dörfler && kColorSpaces[i].space == mode.space 624a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 6251fc4cb1fSAxel Dörfler supportsAnything = true; 626a10cf76eSAxel Dörfler supported = true; 627a10cf76eSAxel Dörfler break; 628a10cf76eSAxel Dörfler } 629a10cf76eSAxel Dörfler } 630a10cf76eSAxel Dörfler 6311fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(index++); 632a10cf76eSAxel Dörfler if (item) 633a10cf76eSAxel Dörfler item->SetEnabled(supported); 634a10cf76eSAxel Dörfler } 6351fc4cb1fSAxel Dörfler 6361fc4cb1fSAxel Dörfler fColorsField->SetEnabled(supportsAnything); 6371fc4cb1fSAxel Dörfler 6381fc4cb1fSAxel Dörfler if (!supportsAnything) 6391fc4cb1fSAxel Dörfler return; 6401fc4cb1fSAxel Dörfler 6411fc4cb1fSAxel Dörfler // Make sure a valid item is selected 6421fc4cb1fSAxel Dörfler 6431fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->FindMarked(); 6441fc4cb1fSAxel Dörfler bool changed = false; 6451fc4cb1fSAxel Dörfler 6461fc4cb1fSAxel Dörfler if (item != fUserSelectedColorSpace) { 6471fc4cb1fSAxel Dörfler if (fUserSelectedColorSpace != NULL 6481fc4cb1fSAxel Dörfler && fUserSelectedColorSpace->IsEnabled()) { 6491fc4cb1fSAxel Dörfler fUserSelectedColorSpace->SetMarked(true); 6501fc4cb1fSAxel Dörfler item = fUserSelectedColorSpace; 6511fc4cb1fSAxel Dörfler changed = true; 6521fc4cb1fSAxel Dörfler } 6531fc4cb1fSAxel Dörfler } 6541fc4cb1fSAxel Dörfler if (item != NULL && !item->IsEnabled()) { 6551fc4cb1fSAxel Dörfler // find the next best item 6561fc4cb1fSAxel Dörfler int32 index = fColorsMenu->IndexOf(item); 6571fc4cb1fSAxel Dörfler bool found = false; 6581fc4cb1fSAxel Dörfler 6591fc4cb1fSAxel Dörfler for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) { 6601fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6611fc4cb1fSAxel Dörfler if (item->IsEnabled()) { 6621fc4cb1fSAxel Dörfler found = true; 6631fc4cb1fSAxel Dörfler break; 6641fc4cb1fSAxel Dörfler } 6651fc4cb1fSAxel Dörfler } 6661fc4cb1fSAxel Dörfler if (!found) { 6671fc4cb1fSAxel Dörfler // search backwards as well 6681fc4cb1fSAxel Dörfler for (int32 i = index - 1; i >= 0; i--) { 6691fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6701fc4cb1fSAxel Dörfler if (item->IsEnabled()) 6711fc4cb1fSAxel Dörfler break; 6721fc4cb1fSAxel Dörfler } 6731fc4cb1fSAxel Dörfler } 6741fc4cb1fSAxel Dörfler 6751fc4cb1fSAxel Dörfler item->SetMarked(true); 6761fc4cb1fSAxel Dörfler changed = true; 6771fc4cb1fSAxel Dörfler } 6781fc4cb1fSAxel Dörfler 6791fc4cb1fSAxel Dörfler if (changed) { 6801fc4cb1fSAxel Dörfler // Update selected space 6811fc4cb1fSAxel Dörfler 6821fc4cb1fSAxel Dörfler BMessage* message = item->Message(); 6831fc4cb1fSAxel Dörfler int32 space; 6841fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) == B_OK) { 6851fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 6861fc4cb1fSAxel Dörfler _UpdateColorLabel(); 6871fc4cb1fSAxel Dörfler } 6881fc4cb1fSAxel Dörfler } 689a10cf76eSAxel Dörfler } 690a10cf76eSAxel Dörfler 691a10cf76eSAxel Dörfler 6925de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 693a10cf76eSAxel Dörfler void 6945de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 695a10cf76eSAxel Dörfler { 69629e8a73aSAxel Dörfler float min, max; 69729e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 69829e8a73aSAxel Dörfler return; 699a10cf76eSAxel Dörfler 70029e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 70129e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 70229e8a73aSAxel Dörfler BMessage* message = item->Message(); 70329e8a73aSAxel Dörfler float refresh; 70429e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 70529e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 706a10cf76eSAxel Dörfler } 707a10cf76eSAxel Dörfler } 708a10cf76eSAxel Dörfler 709a10cf76eSAxel Dörfler 7105de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 711a10cf76eSAxel Dörfler void 7125de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 713a10cf76eSAxel Dörfler { 7147e44de36SRene Gollent for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) { 7157e44de36SRene Gollent BMenuItem* item = fRefreshMenu->ItemAt(i); 7167e44de36SRene Gollent if (item->Message()->FindFloat("refresh") == fSelected.refresh) { 717a10cf76eSAxel Dörfler item->SetMarked(true); 71826747978SAdrien Destugues // "Other" items only contains a refresh rate when active 71926747978SAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 720a10cf76eSAxel Dörfler return; 721a10cf76eSAxel Dörfler } 7227e44de36SRene Gollent } 723a10cf76eSAxel Dörfler 724a10cf76eSAxel Dörfler // this is a non-standard refresh rate 7257e44de36SRene Gollent if (fOtherRefresh != NULL) { 726a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 727a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 728a10cf76eSAxel Dörfler 7297e44de36SRene Gollent BString string; 7307e44de36SRene Gollent refresh_rate_to_string(fSelected.refresh, string); 731a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 732a10cf76eSAxel Dörfler 733c9e8f97aSAdrien Destugues string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS)); 734a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 735a10cf76eSAxel Dörfler } 7367e44de36SRene Gollent } 737a10cf76eSAxel Dörfler 738a10cf76eSAxel Dörfler 739a10cf76eSAxel Dörfler void 7405de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 741a10cf76eSAxel Dörfler { 742a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 743a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 744a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 745a10cf76eSAxel Dörfler 746a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 747a10cf76eSAxel Dörfler } 748a10cf76eSAxel Dörfler 749a10cf76eSAxel Dörfler 750a10cf76eSAxel Dörfler void 7515de171daSAxel Dörfler ScreenWindow::_UpdateControls() 752a10cf76eSAxel Dörfler { 753b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 754b21d610eSAxel Dörfler 755a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 756c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 757a10cf76eSAxel Dörfler item->SetMarked(true); 758a10cf76eSAxel Dörfler 759a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 760c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 761a10cf76eSAxel Dörfler item->SetMarked(true); 762a10cf76eSAxel Dörfler 763a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 764a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 765a10cf76eSAxel Dörfler 766a10cf76eSAxel Dörfler uint32 tvStandard; 767a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 768a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 769a10cf76eSAxel Dörfler if (!item->IsMarked()) 770a10cf76eSAxel Dörfler item->SetMarked(true); 771a10cf76eSAxel Dörfler break; 772a10cf76eSAxel Dörfler } 773a10cf76eSAxel Dörfler } 774a10cf76eSAxel Dörfler 7755de171daSAxel Dörfler _CheckResolutionMenu(); 7765de171daSAxel Dörfler _CheckColorMenu(); 7775de171daSAxel Dörfler _CheckRefreshMenu(); 778a10cf76eSAxel Dörfler 779a10cf76eSAxel Dörfler BString string; 780a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 781a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 782a10cf76eSAxel Dörfler 783a10cf76eSAxel Dörfler if (item != NULL) { 784a10cf76eSAxel Dörfler if (!item->IsMarked()) 785a10cf76eSAxel Dörfler item->SetMarked(true); 786a10cf76eSAxel Dörfler } else { 787a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 788a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 789a10cf76eSAxel Dörfler // 1. add a new resolution to list 790a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 791a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 792a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 793a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 794a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 795a10cf76eSAxel Dörfler // 2. choose nearest resolution 796a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 797a10cf76eSAxel Dörfler // 3. choose lowest resolution 798a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 799a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 800a10cf76eSAxel Dörfler if (item) 801a10cf76eSAxel Dörfler item->SetMarked(true); 802a10cf76eSAxel Dörfler 803a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 804a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 805a10cf76eSAxel Dörfler } 806a10cf76eSAxel Dörfler 807a10cf76eSAxel Dörfler // mark active combine mode 808a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 809a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 810a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 811c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 812a10cf76eSAxel Dörfler item->SetMarked(true); 813a10cf76eSAxel Dörfler break; 814a10cf76eSAxel Dörfler } 815a10cf76eSAxel Dörfler } 816a10cf76eSAxel Dörfler 817a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 818a10cf76eSAxel Dörfler 8191fc4cb1fSAxel Dörfler for (int32 i = 0, index = 0; i < kColorSpaceCount; i++) { 8201fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 8211fc4cb1fSAxel Dörfler continue; 8221fc4cb1fSAxel Dörfler 8231fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 8241fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(index); 825a10cf76eSAxel Dörfler break; 826a10cf76eSAxel Dörfler } 8271fc4cb1fSAxel Dörfler 8281fc4cb1fSAxel Dörfler index++; 829a10cf76eSAxel Dörfler } 830a10cf76eSAxel Dörfler 831c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 832a10cf76eSAxel Dörfler item->SetMarked(true); 833a10cf76eSAxel Dörfler 8341fc4cb1fSAxel Dörfler _UpdateColorLabel(); 8355de171daSAxel Dörfler _UpdateMonitorView(); 8365de171daSAxel Dörfler _UpdateRefreshControl(); 837a10cf76eSAxel Dörfler 8385de171daSAxel Dörfler _CheckApplyEnabled(); 839a10cf76eSAxel Dörfler } 840a10cf76eSAxel Dörfler 841a10cf76eSAxel Dörfler 84212580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 843a10cf76eSAxel Dörfler void 8445de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 845a10cf76eSAxel Dörfler { 846c491b5adSJohn Scipione _UpdateActiveMode(current_workspace()); 847c491b5adSJohn Scipione } 848c491b5adSJohn Scipione 849c491b5adSJohn Scipione 850c491b5adSJohn Scipione void 851c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace) 852c491b5adSJohn Scipione { 85312580984SAxel Dörfler // Usually, this function gets called after a mode 854a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 855a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 856a10cf76eSAxel Dörfler // what kind of mode we actually got 857c491b5adSJohn Scipione if (fScreenMode.Get(fActive, workspace) == B_OK) { 858a10cf76eSAxel Dörfler fSelected = fActive; 859a10cf76eSAxel Dörfler 86012966d04SAxel Dörfler _UpdateMonitor(); 861c491b5adSJohn Scipione _BuildSupportedColorSpaces(); 8625de171daSAxel Dörfler _UpdateControls(); 863a10cf76eSAxel Dörfler } 864c491b5adSJohn Scipione } 865a10cf76eSAxel Dörfler 866a10cf76eSAxel Dörfler 867a10cf76eSAxel Dörfler void 868b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons() 869b21d610eSAxel Dörfler { 870b21d610eSAxel Dörfler uint32 columns; 871b21d610eSAxel Dörfler uint32 rows; 872b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 873b21d610eSAxel Dörfler 874a3fa81bdSJohn Scipione // Set the max values enabling/disabling the up/down arrows 875b21d610eSAxel Dörfler 876a3fa81bdSJohn Scipione if (rows == 1) 877a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(32); 878a3fa81bdSJohn Scipione else if (rows == 2) 879a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(16); 880a3fa81bdSJohn Scipione else if (rows <= 4) 881a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(8); 882a3fa81bdSJohn Scipione else if (rows <= 8) 883a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(4); 884a3fa81bdSJohn Scipione else if (rows <= 16) 885a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(2); 886a3fa81bdSJohn Scipione else if (rows <= 32) 887a3fa81bdSJohn Scipione fColumnsControl->SetMaxValue(1); 888b21d610eSAxel Dörfler 889a3fa81bdSJohn Scipione if (columns == 1) 890a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(32); 891a3fa81bdSJohn Scipione else if (columns == 2) 892a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(16); 893a3fa81bdSJohn Scipione else if (columns <= 4) 894a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(8); 895a3fa81bdSJohn Scipione else if (columns <= 8) 896a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(4); 897a3fa81bdSJohn Scipione else if (columns <= 16) 898a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(2); 899a3fa81bdSJohn Scipione else if (columns <= 32) 900a3fa81bdSJohn Scipione fRowsControl->SetMaxValue(1); 901b21d610eSAxel Dörfler } 902b21d610eSAxel Dörfler 903b21d610eSAxel Dörfler 904b21d610eSAxel Dörfler void 905a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 906a10cf76eSAxel Dörfler { 907a10cf76eSAxel Dörfler // move window on screen, if necessary 908a10cf76eSAxel Dörfler if (frame.right <= Frame().right 909a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 910a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 911a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 912a10cf76eSAxel Dörfler } 913a10cf76eSAxel Dörfler } 914a10cf76eSAxel Dörfler 915a10cf76eSAxel Dörfler 916a10cf76eSAxel Dörfler void 917a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 918a10cf76eSAxel Dörfler { 919c491b5adSJohn Scipione if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) { 920c491b5adSJohn Scipione _UpdateActiveMode(workspace); 921a10cf76eSAxel Dörfler 9226edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 9236edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 924a10cf76eSAxel Dörfler } 925c491b5adSJohn Scipione } 926a10cf76eSAxel Dörfler 927a10cf76eSAxel Dörfler 928a10cf76eSAxel Dörfler void 929a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 930a10cf76eSAxel Dörfler { 931a10cf76eSAxel Dörfler switch (message->what) { 932a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 9335de171daSAxel Dörfler _CheckApplyEnabled(); 934a10cf76eSAxel Dörfler break; 935a10cf76eSAxel Dörfler 936b21d610eSAxel Dörfler case kMsgWorkspaceColumnsChanged: 937b21d610eSAxel Dörfler { 938a3fa81bdSJohn Scipione uint32 newColumns = (uint32)fColumnsControl->Value(); 939b21d610eSAxel Dörfler 940b21d610eSAxel Dörfler uint32 rows; 941b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(NULL, &rows); 942b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, rows); 943b21d610eSAxel Dörfler 944b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 945a3fa81bdSJohn Scipione fRowsControl->SetValue(rows); 946a3fa81bdSJohn Scipione // enables/disables up/down arrows 947b21d610eSAxel Dörfler _CheckApplyEnabled(); 948a3fa81bdSJohn Scipione 949b21d610eSAxel Dörfler break; 950b21d610eSAxel Dörfler } 951b21d610eSAxel Dörfler 952b21d610eSAxel Dörfler case kMsgWorkspaceRowsChanged: 953b21d610eSAxel Dörfler { 954a3fa81bdSJohn Scipione uint32 newRows = (uint32)fRowsControl->Value(); 955b21d610eSAxel Dörfler 956b21d610eSAxel Dörfler uint32 columns; 957b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, NULL); 958b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(columns, newRows); 959b21d610eSAxel Dörfler 960b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 961a3fa81bdSJohn Scipione fColumnsControl->SetValue(columns); 962a3fa81bdSJohn Scipione // enables/disables up/down arrows 963b21d610eSAxel Dörfler _CheckApplyEnabled(); 964a10cf76eSAxel Dörfler break; 965a10cf76eSAxel Dörfler } 966a10cf76eSAxel Dörfler 967a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 968a10cf76eSAxel Dörfler { 969a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 970a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 971a10cf76eSAxel Dörfler 9725de171daSAxel Dörfler _CheckColorMenu(); 9735de171daSAxel Dörfler _CheckRefreshMenu(); 974a10cf76eSAxel Dörfler 9755de171daSAxel Dörfler _UpdateMonitorView(); 9765de171daSAxel Dörfler _UpdateRefreshControl(); 977a10cf76eSAxel Dörfler 9785de171daSAxel Dörfler _CheckApplyEnabled(); 979a10cf76eSAxel Dörfler break; 980a10cf76eSAxel Dörfler } 981a10cf76eSAxel Dörfler 982a10cf76eSAxel Dörfler case POP_COLORS_MSG: 983a10cf76eSAxel Dörfler { 9841fc4cb1fSAxel Dörfler int32 space; 9851fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) != B_OK) 9861fc4cb1fSAxel Dörfler break; 987a10cf76eSAxel Dörfler 9881fc4cb1fSAxel Dörfler int32 index; 9891fc4cb1fSAxel Dörfler if (message->FindInt32("index", &index) == B_OK 9901fc4cb1fSAxel Dörfler && fColorsMenu->ItemAt(index) != NULL) 9911fc4cb1fSAxel Dörfler fUserSelectedColorSpace = fColorsMenu->ItemAt(index); 9921fc4cb1fSAxel Dörfler 9931fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 9941fc4cb1fSAxel Dörfler _UpdateColorLabel(); 995a10cf76eSAxel Dörfler 9965de171daSAxel Dörfler _CheckApplyEnabled(); 997a10cf76eSAxel Dörfler break; 998a10cf76eSAxel Dörfler } 999a10cf76eSAxel Dörfler 1000a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 1001a40498e2SWaldemar Kornewald { 1002a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1003c9e8f97aSAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 10041fc4cb1fSAxel Dörfler // revert "Other…" label - it might have a refresh rate prefix 1005a10cf76eSAxel Dörfler 10065de171daSAxel Dörfler _CheckApplyEnabled(); 1007a10cf76eSAxel Dörfler break; 1008a40498e2SWaldemar Kornewald } 1009a10cf76eSAxel Dörfler 1010a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 1011a10cf76eSAxel Dörfler { 101229e8a73aSAxel Dörfler // make sure menu shows something useful 10135de171daSAxel Dörfler _UpdateRefreshControl(); 1014a10cf76eSAxel Dörfler 101529e8a73aSAxel Dörfler float min = 0, max = 999; 101629e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 101729e8a73aSAxel Dörfler if (min < gMinRefresh) 101829e8a73aSAxel Dörfler min = gMinRefresh; 101929e8a73aSAxel Dörfler if (max > gMaxRefresh) 102029e8a73aSAxel Dörfler max = gMaxRefresh; 102129e8a73aSAxel Dörfler 102270a2b1b5SAxel Dörfler monitor_info info; 102370a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 102470a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 102570a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 102670a2b1b5SAxel Dörfler } 102770a2b1b5SAxel Dörfler 1028c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 102970a2b1b5SAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, 103070a2b1b5SAxel Dörfler min, max); 1031a10cf76eSAxel Dörfler fRefreshWindow->Show(); 1032a10cf76eSAxel Dörfler break; 1033a10cf76eSAxel Dörfler } 1034a10cf76eSAxel Dörfler 1035a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 1036a10cf76eSAxel Dörfler { 1037a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 1038a10cf76eSAxel Dörfler // select the refresh rate chosen 1039a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1040a10cf76eSAxel Dörfler 10415de171daSAxel Dörfler _UpdateRefreshControl(); 10425de171daSAxel Dörfler _CheckApplyEnabled(); 1043a10cf76eSAxel Dörfler break; 1044a10cf76eSAxel Dörfler } 1045a10cf76eSAxel Dörfler 1046a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 1047a10cf76eSAxel Dörfler { 1048a10cf76eSAxel Dörfler // new combine mode has bee chosen 1049a10cf76eSAxel Dörfler int32 mode; 1050a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 1051a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 1052a10cf76eSAxel Dörfler 10535de171daSAxel Dörfler _CheckResolutionMenu(); 10545de171daSAxel Dörfler _CheckApplyEnabled(); 1055a10cf76eSAxel Dörfler break; 1056a10cf76eSAxel Dörfler } 1057a10cf76eSAxel Dörfler 1058a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 1059a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 10605de171daSAxel Dörfler _CheckApplyEnabled(); 1061a10cf76eSAxel Dörfler break; 1062a10cf76eSAxel Dörfler 1063a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 1064a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 10655de171daSAxel Dörfler _CheckApplyEnabled(); 1066a10cf76eSAxel Dörfler break; 1067a10cf76eSAxel Dörfler 1068a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 1069a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 10705de171daSAxel Dörfler _CheckApplyEnabled(); 1071a10cf76eSAxel Dörfler break; 1072a10cf76eSAxel Dörfler 1073df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 10746f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 10756f095d6aSRyan Leavengood app_info info; 10766f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 10776f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 10786f095d6aSRyan Leavengood } 1079df3f5bacSStephan Aßmus break; 1080df3f5bacSStephan Aßmus 1081a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 1082a10cf76eSAxel Dörfler { 10834be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 1084a10cf76eSAxel Dörfler fSelected.width = 640; 1085a10cf76eSAxel Dörfler fSelected.height = 480; 1086a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 1087a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 1088a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 1089a10cf76eSAxel Dörfler fSelected.swap_displays = false; 1090a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 1091a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 1092a10cf76eSAxel Dörfler 1093b21d610eSAxel Dörfler // TODO: workspace defaults 1094abc649b8SWaldemar Kornewald 10955de171daSAxel Dörfler _UpdateControls(); 1096a10cf76eSAxel Dörfler break; 1097a10cf76eSAxel Dörfler } 1098a10cf76eSAxel Dörfler 109910e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 110061c5c89bSAxel Dörfler fUndoScreenMode.Revert(); 11015de171daSAxel Dörfler _UpdateActiveMode(); 1102abc649b8SWaldemar Kornewald break; 1103abc649b8SWaldemar Kornewald 1104abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 1105abc649b8SWaldemar Kornewald { 1106abc649b8SWaldemar Kornewald fModified = false; 1107199893c3SAxel Dörfler fBootWorkspaceApplied = false; 1108abc649b8SWaldemar Kornewald 1109b21d610eSAxel Dörfler // ScreenMode::Revert() assumes that we first set the correct 1110b21d610eSAxel Dörfler // number of workspaces 1111b21d610eSAxel Dörfler 1112b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns, 1113b21d610eSAxel Dörfler fOriginalWorkspacesRows); 1114b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 1115b21d610eSAxel Dörfler 1116a10cf76eSAxel Dörfler fScreenMode.Revert(); 11175de171daSAxel Dörfler _UpdateActiveMode(); 1118a10cf76eSAxel Dörfler break; 1119abc649b8SWaldemar Kornewald } 1120a10cf76eSAxel Dörfler 1121a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 11225de171daSAxel Dörfler _Apply(); 1123a10cf76eSAxel Dörfler break; 1124a10cf76eSAxel Dörfler 1125abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 1126abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 1127abc649b8SWaldemar Kornewald fModified = true; 11285de171daSAxel Dörfler _UpdateActiveMode(); 1129a10cf76eSAxel Dörfler break; 1130a10cf76eSAxel Dörfler 1131a10cf76eSAxel Dörfler default: 1132a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 1133a10cf76eSAxel Dörfler } 1134a10cf76eSAxel Dörfler } 1135a10cf76eSAxel Dörfler 1136a10cf76eSAxel Dörfler 113712580984SAxel Dörfler status_t 113812580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 113912580984SAxel Dörfler { 114012580984SAxel Dörfler BPath path; 114112580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 114212580984SAxel Dörfler if (status < B_OK) 114312580984SAxel Dörfler return status; 114412580984SAxel Dörfler 114512580984SAxel Dörfler path.Append("kernel/drivers"); 114612580984SAxel Dörfler status = create_directory(path.Path(), 0755); 114712580984SAxel Dörfler if (status < B_OK) 114812580984SAxel Dörfler return status; 114912580984SAxel Dörfler 115012580984SAxel Dörfler path.Append("vesa"); 115112580984SAxel Dörfler BFile file; 115212580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 115312580984SAxel Dörfler if (status < B_OK) 115412580984SAxel Dörfler return status; 115512580984SAxel Dörfler 115612580984SAxel Dörfler char buffer[256]; 11575084d0d4SAlex Smith snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %" 11585084d0d4SAlex Smith B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel()); 115912580984SAxel Dörfler 116012580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 116112580984SAxel Dörfler if (bytesWritten < B_OK) 116212580984SAxel Dörfler return bytesWritten; 116312580984SAxel Dörfler 116412580984SAxel Dörfler return B_OK; 116512580984SAxel Dörfler } 116612580984SAxel Dörfler 116712580984SAxel Dörfler 1168a10cf76eSAxel Dörfler void 11691fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces() 11701fc4cb1fSAxel Dörfler { 11711fc4cb1fSAxel Dörfler fSupportedColorSpaces = 0; 11721fc4cb1fSAxel Dörfler 11731fc4cb1fSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 11741fc4cb1fSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 11751fc4cb1fSAxel Dörfler if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) { 11761fc4cb1fSAxel Dörfler fSupportedColorSpaces |= 1 << i; 11771fc4cb1fSAxel Dörfler break; 11781fc4cb1fSAxel Dörfler } 11791fc4cb1fSAxel Dörfler } 11801fc4cb1fSAxel Dörfler } 11811fc4cb1fSAxel Dörfler } 11821fc4cb1fSAxel Dörfler 11831fc4cb1fSAxel Dörfler 11841fc4cb1fSAxel Dörfler void 11855de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1186a10cf76eSAxel Dörfler { 118795ef5044SJanus bool applyEnabled = true; 118895ef5044SJanus 118995ef5044SJanus if (fSelected == fActive) { 119095ef5044SJanus applyEnabled = false; 119195ef5044SJanus if (fAllWorkspacesItem->IsMarked()) { 119295ef5044SJanus screen_mode screenMode; 119395ef5044SJanus const int32 workspaceCount = count_workspaces(); 119495ef5044SJanus for (int32 i = 0; i < workspaceCount; i++) { 119595ef5044SJanus fScreenMode.Get(screenMode, i); 119695ef5044SJanus if (screenMode != fSelected) { 119795ef5044SJanus applyEnabled = true; 119895ef5044SJanus break; 119995ef5044SJanus } 120095ef5044SJanus } 120195ef5044SJanus } 120295ef5044SJanus } 120395ef5044SJanus 120495ef5044SJanus fApplyButton->SetEnabled(applyEnabled); 1205b21d610eSAxel Dörfler 1206b21d610eSAxel Dörfler uint32 columns; 1207b21d610eSAxel Dörfler uint32 rows; 1208b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 1209b21d610eSAxel Dörfler 1210b21d610eSAxel Dörfler fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns 1211b21d610eSAxel Dörfler || rows != fOriginalWorkspacesRows 12125de171daSAxel Dörfler || fSelected != fOriginal); 1213a10cf76eSAxel Dörfler } 1214a10cf76eSAxel Dörfler 1215a10cf76eSAxel Dörfler 1216a10cf76eSAxel Dörfler void 12175de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1218abc649b8SWaldemar Kornewald { 1219b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns, 1220b21d610eSAxel Dörfler &fOriginalWorkspacesRows); 1221b21d610eSAxel Dörfler 1222abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1223abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1224abc649b8SWaldemar Kornewald } 1225abc649b8SWaldemar Kornewald 1226abc649b8SWaldemar Kornewald 1227abc649b8SWaldemar Kornewald void 122812966d04SAxel Dörfler ScreenWindow::_UpdateMonitor() 122912966d04SAxel Dörfler { 123012966d04SAxel Dörfler monitor_info info; 123112966d04SAxel Dörfler float diagonalInches; 123212966d04SAxel Dörfler status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches); 123355030977SAxel Dörfler if (status == B_OK) { 12341a8af605SAxel Dörfler char text[512]; 123566ab1666SAxel Dörfler snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor, 123666ab1666SAxel Dörfler info.name[0] ? " " : "", info.name, diagonalInches); 123712966d04SAxel Dörfler 123812966d04SAxel Dörfler fMonitorInfo->SetText(text); 123912966d04SAxel Dörfler 124012966d04SAxel Dörfler if (fMonitorInfo->IsHidden()) 124112966d04SAxel Dörfler fMonitorInfo->Show(); 124255030977SAxel Dörfler } else { 124355030977SAxel Dörfler if (!fMonitorInfo->IsHidden()) 124455030977SAxel Dörfler fMonitorInfo->Hide(); 124555030977SAxel Dörfler } 1246af8f9c31SAxel Dörfler 12478b46ee25SAdrien Destugues // Add info about the graphics device 12488b46ee25SAdrien Destugues 12498b46ee25SAdrien Destugues accelerant_device_info deviceInfo; 12508b46ee25SAdrien Destugues 12518b46ee25SAdrien Destugues if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK) { 12528b46ee25SAdrien Destugues BString deviceString; 12538b46ee25SAdrien Destugues 12548b46ee25SAdrien Destugues if (deviceInfo.name[0] && deviceInfo.chipset[0]) { 12558b46ee25SAdrien Destugues deviceString.SetToFormat("%s (%s)", deviceInfo.name, 12568b46ee25SAdrien Destugues deviceInfo.chipset); 12578b46ee25SAdrien Destugues } else if (deviceInfo.name[0] || deviceInfo.chipset[0]) { 12588b46ee25SAdrien Destugues deviceString 12598b46ee25SAdrien Destugues = deviceInfo.name[0] ? deviceInfo.name : deviceInfo.chipset; 12608b46ee25SAdrien Destugues } 12618b46ee25SAdrien Destugues 12628b46ee25SAdrien Destugues fDeviceInfo->SetText(deviceString); 12638b46ee25SAdrien Destugues } 12648b46ee25SAdrien Destugues 12658b46ee25SAdrien Destugues 126655030977SAxel Dörfler char text[512]; 12671a8af605SAxel Dörfler size_t length = 0; 12681a8af605SAxel Dörfler text[0] = 0; 12691a8af605SAxel Dörfler 127055030977SAxel Dörfler if (status == B_OK) { 1271af8f9c31SAxel Dörfler if (info.min_horizontal_frequency != 0 1272af8f9c31SAxel Dörfler && info.min_vertical_frequency != 0 1273af8f9c31SAxel Dörfler && info.max_pixel_clock != 0) { 12741a8af605SAxel Dörfler length = snprintf(text, sizeof(text), 1275c9e8f97aSAdrien Destugues B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n" 12769c1a9b92SAdrien Destugues "Vertical frequency:\t%lu - %lu Hz\n\n" 1277c9e8f97aSAdrien Destugues "Maximum pixel clock:\t%g MHz"), 12781a8af605SAxel Dörfler info.min_horizontal_frequency, info.max_horizontal_frequency, 12791a8af605SAxel Dörfler info.min_vertical_frequency, info.max_vertical_frequency, 12801a8af605SAxel Dörfler info.max_pixel_clock / 1000.0); 1281af8f9c31SAxel Dörfler } 12821a8af605SAxel Dörfler if (info.serial_number[0] && length < sizeof(text)) { 12831a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 1284c9e8f97aSAdrien Destugues B_TRANSLATE("%sSerial no.: %s"), length ? "\n\n" : "", 12851a8af605SAxel Dörfler info.serial_number); 12861a8af605SAxel Dörfler if (info.produced.week != 0 && info.produced.year != 0 12871a8af605SAxel Dörfler && length < sizeof(text)) { 12881a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 12891a8af605SAxel Dörfler " (%u/%u)", info.produced.week, info.produced.year); 12901a8af605SAxel Dörfler } 12911a8af605SAxel Dörfler } 129255030977SAxel Dörfler } 129361c5c89bSAxel Dörfler 12941a8af605SAxel Dörfler if (text[0]) 12951a8af605SAxel Dörfler fMonitorView->SetToolTip(text); 129612966d04SAxel Dörfler } 129712966d04SAxel Dörfler 129812966d04SAxel Dörfler 129912966d04SAxel Dörfler void 13001fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel() 13011fc4cb1fSAxel Dörfler { 13021fc4cb1fSAxel Dörfler BString string; 1303551c9f15SSiarzhuk Zharski string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel"); 13041fc4cb1fSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 13051fc4cb1fSAxel Dörfler } 13061fc4cb1fSAxel Dörfler 13071fc4cb1fSAxel Dörfler 13081fc4cb1fSAxel Dörfler void 13095de171daSAxel Dörfler ScreenWindow::_Apply() 1310a10cf76eSAxel Dörfler { 1311abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 131261c5c89bSAxel Dörfler fUndoScreenMode.UpdateOriginalModes(); 131361c5c89bSAxel Dörfler 131407184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 131507184a9eSAxel Dörfler if (status == B_OK) { 1316abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1317abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1318abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1319abc649b8SWaldemar Kornewald display_mode newMode; 1320abc649b8SWaldemar Kornewald BScreen screen(this); 1321abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1322abc649b8SWaldemar Kornewald 1323abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1324abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 132595ef5044SJanus const int32 workspaceCount = count_workspaces(); 132695ef5044SJanus for (int32 i = 0; i < workspaceCount; i++) { 1327abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1328abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1329abc649b8SWaldemar Kornewald } 1330199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1331199893c3SAxel Dörfler } else { 1332199893c3SAxel Dörfler if (current_workspace() == 0) 1333199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1334abc649b8SWaldemar Kornewald } 1335abc649b8SWaldemar Kornewald 1336a10cf76eSAxel Dörfler fActive = fSelected; 1337a10cf76eSAxel Dörfler 1338abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 1339*41f43d56SAugustin Cavalier BAlert* window = new AlertWindow(this); 1340*41f43d56SAugustin Cavalier window->Go(NULL); 134107184a9eSAxel Dörfler } else { 134207184a9eSAxel Dörfler char message[256]; 134307184a9eSAxel Dörfler snprintf(message, sizeof(message), 1344c9e8f97aSAdrien Destugues B_TRANSLATE("The screen mode could not be set:\n\t%s\n"), 1345c9e8f97aSAdrien Destugues screen_errors(status)); 1346551c9f15SSiarzhuk Zharski BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message, 1347c9e8f97aSAdrien Destugues B_TRANSLATE("OK"), NULL, NULL, 134807184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 1349aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 135007184a9eSAxel Dörfler alert->Go(); 1351a10cf76eSAxel Dörfler } 135207184a9eSAxel Dörfler } 1353