1a10cf76eSAxel Dörfler /* 27e44de36SRene Gollent * Copyright 2001-2012, Haiku. 3a10cf76eSAxel Dörfler * Distributed under the terms of the MIT License. 4a10cf76eSAxel Dörfler * 5a10cf76eSAxel Dörfler * Authors: 6a10cf76eSAxel Dörfler * Rafael Romo 7a10cf76eSAxel Dörfler * Stefano Ceccherini (burton666@libero.it) 8a10cf76eSAxel Dörfler * Andrew Bachmann 97e44de36SRene Gollent * Rene Gollent, rene@gollent.com 10a10cf76eSAxel Dörfler * Thomas Kurschel 11a10cf76eSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de 12df3f5bacSStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 13b72c4836SAlexandre Deckner * Alexandre Deckner, alex@zappotek.com 14a10cf76eSAxel Dörfler */ 15a10cf76eSAxel Dörfler 16a10cf76eSAxel Dörfler 17b21d610eSAxel Dörfler #include "ScreenWindow.h" 18b21d610eSAxel Dörfler 19b21d610eSAxel Dörfler #include <stdio.h> 20b21d610eSAxel Dörfler #include <stdlib.h> 21b21d610eSAxel Dörfler #include <string.h> 22b21d610eSAxel Dörfler 23b21d610eSAxel Dörfler #include <Alert.h> 24b21d610eSAxel Dörfler #include <Application.h> 25b21d610eSAxel Dörfler #include <Box.h> 26b21d610eSAxel Dörfler #include <Button.h> 27c9e8f97aSAdrien Destugues #include <Catalog.h> 28b21d610eSAxel Dörfler #include <Directory.h> 29b21d610eSAxel Dörfler #include <File.h> 30b21d610eSAxel Dörfler #include <FindDirectory.h> 31b21d610eSAxel Dörfler #include <InterfaceDefs.h> 32b21d610eSAxel Dörfler #include <LayoutBuilder.h> 33b21d610eSAxel Dörfler #include <MenuBar.h> 34b21d610eSAxel Dörfler #include <MenuItem.h> 35b21d610eSAxel Dörfler #include <MenuField.h> 36b21d610eSAxel Dörfler #include <Messenger.h> 37b21d610eSAxel Dörfler #include <Path.h> 38b21d610eSAxel Dörfler #include <PopUpMenu.h> 39b21d610eSAxel Dörfler #include <Screen.h> 40b21d610eSAxel Dörfler #include <String.h> 41b21d610eSAxel Dörfler #include <StringView.h> 42b21d610eSAxel Dörfler #include <Roster.h> 43b21d610eSAxel Dörfler #include <Window.h> 44b21d610eSAxel Dörfler 45b21d610eSAxel Dörfler #include <InterfacePrivate.h> 46b21d610eSAxel Dörfler 47a10cf76eSAxel Dörfler #include "AlertWindow.h" 48a10cf76eSAxel Dörfler #include "Constants.h" 49a10cf76eSAxel Dörfler #include "RefreshWindow.h" 50a10cf76eSAxel Dörfler #include "MonitorView.h" 51a10cf76eSAxel Dörfler #include "ScreenSettings.h" 52a10cf76eSAxel Dörfler #include "Utility.h" 53a10cf76eSAxel Dörfler 54a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant. 55a10cf76eSAxel Dörfler * It's a solution that works with the current BeOS interface that Haiku 56a10cf76eSAxel Dörfler * adopted. 57a10cf76eSAxel Dörfler * However, it's not a nice and clean solution. Don't use this header in any 58a10cf76eSAxel Dörfler * application if you can avoid it. No other driver is using this, or should 59a10cf76eSAxel Dörfler * be using this. 60a10cf76eSAxel Dörfler * It will be replaced as soon as we introduce an updated accelerant interface 61a10cf76eSAxel Dörfler * which may even happen before R1 hits the streets. 62a10cf76eSAxel Dörfler */ 63a10cf76eSAxel Dörfler #include "multimon.h" // the usual: DANGER WILL, ROBINSON! 64a10cf76eSAxel Dörfler 65a10cf76eSAxel Dörfler 66546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 67546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Screen" 68c9e8f97aSAdrien Destugues 69c9e8f97aSAdrien Destugues 7075c92c56SRyan Leavengood const char* kBackgroundsSignature = "application/x-vnd.Haiku-Backgrounds"; 71c5d80d47SAxel Dörfler 72a10cf76eSAxel Dörfler // list of officially supported colour spaces 73a10cf76eSAxel Dörfler static const struct { 74a10cf76eSAxel Dörfler color_space space; 75a10cf76eSAxel Dörfler int32 bits_per_pixel; 76a10cf76eSAxel Dörfler const char* label; 77a10cf76eSAxel Dörfler } kColorSpaces[] = { 7826747978SAdrien Destugues { B_CMAP8, 8, B_TRANSLATE("8 bits/pixel, 256 colors") }, 79c9e8f97aSAdrien Destugues { B_RGB15, 15, B_TRANSLATE("15 bits/pixel, 32768 colors") }, 80c9e8f97aSAdrien Destugues { B_RGB16, 16, B_TRANSLATE("16 bits/pixel, 65536 colors") }, 81c9e8f97aSAdrien Destugues { B_RGB24, 24, B_TRANSLATE("24 bits/pixel, 16 Million colors") }, 82c9e8f97aSAdrien Destugues { B_RGB32, 32, B_TRANSLATE("32 bits/pixel, 16 Million colors") } 83a10cf76eSAxel Dörfler }; 84b21d610eSAxel Dörfler static const int32 kColorSpaceCount 85b21d610eSAxel Dörfler = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]); 86a10cf76eSAxel Dörfler 87a10cf76eSAxel Dörfler // list of standard refresh rates 88a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 }; 89b21d610eSAxel Dörfler static const int32 kRefreshRateCount 90b21d610eSAxel Dörfler = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); 91a10cf76eSAxel Dörfler 92a10cf76eSAxel Dörfler // list of combine modes 93a10cf76eSAxel Dörfler static const struct { 94a10cf76eSAxel Dörfler combine_mode mode; 95a10cf76eSAxel Dörfler const char *name; 96a10cf76eSAxel Dörfler } kCombineModes[] = { 97c9e8f97aSAdrien Destugues { kCombineDisable, B_TRANSLATE("disable") }, 98c9e8f97aSAdrien Destugues { kCombineHorizontally, B_TRANSLATE("horizontally") }, 99c9e8f97aSAdrien Destugues { kCombineVertically, B_TRANSLATE("vertically") } 100a10cf76eSAxel Dörfler }; 101b21d610eSAxel Dörfler static const int32 kCombineModeCount 102b21d610eSAxel Dörfler = sizeof(kCombineModes) / sizeof(kCombineModes[0]); 10329e8a73aSAxel Dörfler 104a10cf76eSAxel Dörfler 105a10cf76eSAxel Dörfler static BString 106a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode) 107a10cf76eSAxel Dörfler { 108a10cf76eSAxel Dörfler switch (mode) { 109a10cf76eSAxel Dörfler case 0: return "disabled"; 110a10cf76eSAxel Dörfler case 1: return "NTSC"; 111a10cf76eSAxel Dörfler case 2: return "NTSC Japan"; 112a10cf76eSAxel Dörfler case 3: return "PAL BDGHI"; 113a10cf76eSAxel Dörfler case 4: return "PAL M"; 114a10cf76eSAxel Dörfler case 5: return "PAL N"; 115a10cf76eSAxel Dörfler case 6: return "SECAM"; 116a10cf76eSAxel Dörfler case 101: return "NTSC 443"; 117a10cf76eSAxel Dörfler case 102: return "PAL 60"; 118a10cf76eSAxel Dörfler case 103: return "PAL NC"; 119a10cf76eSAxel Dörfler default: 120a10cf76eSAxel Dörfler { 121a10cf76eSAxel Dörfler BString name; 122a10cf76eSAxel Dörfler name << "??? (" << mode << ")"; 123a10cf76eSAxel Dörfler 124a10cf76eSAxel Dörfler return name; 125a10cf76eSAxel Dörfler } 126a10cf76eSAxel Dörfler } 127a10cf76eSAxel Dörfler } 128a10cf76eSAxel Dörfler 129a10cf76eSAxel Dörfler 130a10cf76eSAxel Dörfler static void 131a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string) 132a10cf76eSAxel Dörfler { 133a10cf76eSAxel Dörfler string << mode.width << " x " << mode.height; 134a10cf76eSAxel Dörfler } 135a10cf76eSAxel Dörfler 136a10cf76eSAxel Dörfler 137a10cf76eSAxel Dörfler static void 138a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string, 139a10cf76eSAxel Dörfler bool appendUnit = true, bool alwaysWithFraction = false) 140a10cf76eSAxel Dörfler { 1418bf23e3cSAxel Dörfler snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, 1428bf23e3cSAxel Dörfler refresh); 143a10cf76eSAxel Dörfler string.UnlockBuffer(); 144a10cf76eSAxel Dörfler 145a10cf76eSAxel Dörfler if (appendUnit) 146551c9f15SSiarzhuk Zharski string << " " << B_TRANSLATE("Hz"); 147a10cf76eSAxel Dörfler } 148a10cf76eSAxel Dörfler 149a10cf76eSAxel Dörfler 15007184a9eSAxel Dörfler static const char* 15107184a9eSAxel Dörfler screen_errors(status_t status) 15207184a9eSAxel Dörfler { 15307184a9eSAxel Dörfler switch (status) { 15407184a9eSAxel Dörfler case B_ENTRY_NOT_FOUND: 155c9e8f97aSAdrien Destugues return B_TRANSLATE("Unknown mode"); 15607184a9eSAxel Dörfler // TODO: add more? 15707184a9eSAxel Dörfler 15807184a9eSAxel Dörfler default: 15907184a9eSAxel Dörfler return strerror(status); 16007184a9eSAxel Dörfler } 16107184a9eSAxel Dörfler } 16207184a9eSAxel Dörfler 16329e8a73aSAxel Dörfler 1643dfd20c0SStephan Aßmus // #pragma mark - 1653dfd20c0SStephan Aßmus 1663dfd20c0SStephan Aßmus 1675a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings* settings) 168b21d610eSAxel Dörfler : 169560ff447SJonas Sundström BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Screen"), 170958e0ca5SJohn Scipione B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE 171958e0ca5SJohn Scipione | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), 1723f953a72SAxel Dörfler fIsVesa(false), 173199893c3SAxel Dörfler fBootWorkspaceApplied(false), 1747e44de36SRene Gollent fOtherRefresh(NULL), 175294a85aaSRene Gollent fScreenMode(this), 17661c5c89bSAxel Dörfler fUndoScreenMode(this), 177abc649b8SWaldemar Kornewald fModified(false) 178a10cf76eSAxel Dörfler { 179a10cf76eSAxel Dörfler BScreen screen(this); 180a10cf76eSAxel Dörfler 18112580984SAxel Dörfler accelerant_device_info info; 182d1516993SAxel Dörfler if (screen.GetDeviceInfo(&info) == B_OK 183d1516993SAxel Dörfler && !strcasecmp(info.chipset, "VESA")) 18412580984SAxel Dörfler fIsVesa = true; 18512580984SAxel Dörfler 1865de171daSAxel Dörfler _UpdateOriginal(); 1871fc4cb1fSAxel Dörfler _BuildSupportedColorSpaces(); 188a10cf76eSAxel Dörfler fActive = fSelected = fOriginal; 189a10cf76eSAxel Dörfler 1905a78744bSAxel Dörfler fSettings = settings; 1915a78744bSAxel Dörfler 1925a78744bSAxel Dörfler // we need the "Current Workspace" first to get its height 1935a78744bSAxel Dörfler 194c9e8f97aSAdrien Destugues BPopUpMenu *popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), 195c9e8f97aSAdrien Destugues true, true); 196c9e8f97aSAdrien Destugues fAllWorkspacesItem = new BMenuItem(B_TRANSLATE("All workspaces"), 197d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 1985a78744bSAxel Dörfler popUpMenu->AddItem(fAllWorkspacesItem); 199c9e8f97aSAdrien Destugues BMenuItem *item = new BMenuItem(B_TRANSLATE("Current workspace"), 200d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 201b72c4836SAlexandre Deckner 2025a78744bSAxel Dörfler popUpMenu->AddItem(item); 20327c43a2dSRene Gollent fAllWorkspacesItem->SetMarked(true); 2045a78744bSAxel Dörfler 205b21d610eSAxel Dörfler BMenuField* workspaceMenuField = new BMenuField("WorkspaceMenu", NULL, 20610dfe897SAxel Dörfler popUpMenu); 2075a78744bSAxel Dörfler workspaceMenuField->ResizeToPreferred(); 208a10cf76eSAxel Dörfler 209a10cf76eSAxel Dörfler // box on the left with workspace count and monitor view 210a10cf76eSAxel Dörfler 211b21d610eSAxel Dörfler BBox* screenBox = new BBox("screen box"); 2128bf23e3cSAxel Dörfler BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 5.0); 213b21d610eSAxel Dörfler layout->SetInsets(10, 10, 10, 10); 214b21d610eSAxel Dörfler screenBox->SetLayout(layout); 215a10cf76eSAxel Dörfler 21612966d04SAxel Dörfler fMonitorInfo = new BStringView("monitor info", ""); 21712966d04SAxel Dörfler screenBox->AddChild(fMonitorInfo); 21812966d04SAxel Dörfler 219c9e8f97aSAdrien Destugues fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), 220551c9f15SSiarzhuk Zharski "monitor", screen.Frame().IntegerWidth() + 1, 221c9e8f97aSAdrien Destugues screen.Frame().IntegerHeight() + 1); 222b21d610eSAxel Dörfler screenBox->AddChild(fMonitorView); 2235a78744bSAxel Dörfler 224c9e8f97aSAdrien Destugues fColumnsControl = new BTextControl(B_TRANSLATE("Columns:"), "0", 225b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceColumnsChanged)); 226c9e8f97aSAdrien Destugues fRowsControl = new BTextControl(B_TRANSLATE("Rows:"), "0", 227b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceRowsChanged)); 228b21d610eSAxel Dörfler 229b21d610eSAxel Dörfler screenBox->AddChild(BLayoutBuilder::Grid<>(5.0, 5.0) 230c9e8f97aSAdrien Destugues .Add(new BStringView("", B_TRANSLATE("Workspaces")), 0, 0, 3) 231b21d610eSAxel Dörfler .AddTextControl(fColumnsControl, 0, 1, B_ALIGN_RIGHT) 232b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 0, 2, 1) 233b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(true, false)) 234b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(true, true)) 235b21d610eSAxel Dörfler .End() 236b21d610eSAxel Dörfler .AddTextControl(fRowsControl, 0, 2, B_ALIGN_RIGHT) 237b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 0, 2, 2) 238b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(false, false)) 239b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(false, true)) 24025fd5c7bSAlex Wilson .End() 24125fd5c7bSAlex Wilson .View()); 242b21d610eSAxel Dörfler 243b21d610eSAxel Dörfler fBackgroundsButton = new BButton("BackgroundsButton", 244c9e8f97aSAdrien Destugues B_TRANSLATE("Set background" B_UTF8_ELLIPSIS), 245b21d610eSAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 246b21d610eSAxel Dörfler fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 247b21d610eSAxel Dörfler screenBox->AddChild(fBackgroundsButton); 248a10cf76eSAxel Dörfler 249a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 250a10cf76eSAxel Dörfler 251b21d610eSAxel Dörfler BBox* controlsBox = new BBox("controls box"); 252b21d610eSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 25325fd5c7bSAlex Wilson BGroupView* outerControlsView = new BGroupView(B_VERTICAL, 10.0); 25425fd5c7bSAlex Wilson outerControlsView->GroupLayout()->SetInsets(10, 10, 10, 10); 255b21d610eSAxel Dörfler controlsBox->AddChild(outerControlsView); 256a10cf76eSAxel Dörfler 257551c9f15SSiarzhuk Zharski fResolutionMenu = new BPopUpMenu("resolution", true, true); 258a10cf76eSAxel Dörfler 25966ab1666SAxel Dörfler uint16 maxWidth = 0; 26066ab1666SAxel Dörfler uint16 maxHeight = 0; 26166ab1666SAxel Dörfler uint16 previousWidth = 0; 26266ab1666SAxel Dörfler uint16 previousHeight = 0; 263a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 264a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 265a10cf76eSAxel Dörfler 266a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 267a10cf76eSAxel Dörfler continue; 268a10cf76eSAxel Dörfler 269a10cf76eSAxel Dörfler previousWidth = mode.width; 270a10cf76eSAxel Dörfler previousHeight = mode.height; 27166ab1666SAxel Dörfler if (maxWidth < mode.width) 27266ab1666SAxel Dörfler maxWidth = mode.width; 27366ab1666SAxel Dörfler if (maxHeight < mode.height) 27466ab1666SAxel Dörfler maxHeight = mode.height; 275a10cf76eSAxel Dörfler 276a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_RESOLUTION_MSG); 277a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 278a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 279a10cf76eSAxel Dörfler 280a10cf76eSAxel Dörfler BString name; 281a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 282a10cf76eSAxel Dörfler 283a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 284a10cf76eSAxel Dörfler } 285a10cf76eSAxel Dörfler 28666ab1666SAxel Dörfler fMonitorView->SetMaxResolution(maxWidth, maxHeight); 28766ab1666SAxel Dörfler 288c9e8f97aSAdrien Destugues fResolutionField = new BMenuField("ResolutionMenu", 28910dfe897SAxel Dörfler B_TRANSLATE("Resolution:"), fResolutionMenu); 290a10cf76eSAxel Dörfler 291551c9f15SSiarzhuk Zharski fColorsMenu = new BPopUpMenu("colors", true, false); 292a10cf76eSAxel Dörfler 293a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 2941fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 2951fc4cb1fSAxel Dörfler continue; 2961fc4cb1fSAxel Dörfler 297a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_COLORS_MSG); 298a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 299a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 300a10cf76eSAxel Dörfler 3011fc4cb1fSAxel Dörfler BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); 3021fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == screen.ColorSpace()) 3031fc4cb1fSAxel Dörfler fUserSelectedColorSpace = item; 3041fc4cb1fSAxel Dörfler 3051fc4cb1fSAxel Dörfler fColorsMenu->AddItem(item); 306a10cf76eSAxel Dörfler } 307a10cf76eSAxel Dörfler 308c9e8f97aSAdrien Destugues fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"), 30910dfe897SAxel Dörfler fColorsMenu); 310a10cf76eSAxel Dörfler 311551c9f15SSiarzhuk Zharski fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 312a10cf76eSAxel Dörfler 31329e8a73aSAxel Dörfler float min, max; 314ec495b30SRene Gollent if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) { 315ec495b30SRene Gollent // if we couldn't obtain the refresh limits, reset to the default 316ec495b30SRene Gollent // range. Constraints from detected monitors will fine-tune this 317ec495b30SRene Gollent // later. 318ec495b30SRene Gollent min = kRefreshRates[0]; 319ec495b30SRene Gollent max = kRefreshRates[kRefreshRateCount - 1]; 320ec495b30SRene Gollent } 321ec495b30SRene Gollent 322ec495b30SRene Gollent if (min == max) { 32329e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 32429e8a73aSAxel Dörfler // frequency, like the VESA driver 32529e8a73aSAxel Dörfler BString name; 3267e44de36SRene Gollent refresh_rate_to_string(min, name); 327cf076964SRene Gollent BMessage *message = new BMessage(POP_REFRESH_MSG); 328cf076964SRene Gollent message->AddFloat("refresh", min); 329cf076964SRene Gollent BMenuItem *item = new BMenuItem(name.String(), message); 3300efb8b66SJerome Duval fRefreshMenu->AddItem(item); 33129e8a73aSAxel Dörfler item->SetEnabled(false); 33229e8a73aSAxel Dörfler } else { 33370a2b1b5SAxel Dörfler monitor_info info; 33470a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 33570a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 33670a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 33770a2b1b5SAxel Dörfler } 33870a2b1b5SAxel Dörfler 339a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 34070a2b1b5SAxel Dörfler if (kRefreshRates[i] < min || kRefreshRates[i] > max) 34170a2b1b5SAxel Dörfler continue; 34270a2b1b5SAxel Dörfler 343a10cf76eSAxel Dörfler BString name; 344551c9f15SSiarzhuk Zharski name << kRefreshRates[i] << " " << B_TRANSLATE("Hz"); 345a10cf76eSAxel Dörfler 3460efb8b66SJerome Duval BMessage *message = new BMessage(POP_REFRESH_MSG); 347a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 348a10cf76eSAxel Dörfler 349a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 350a10cf76eSAxel Dörfler } 351a10cf76eSAxel Dörfler 352c9e8f97aSAdrien Destugues fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), 3530efb8b66SJerome Duval new BMessage(POP_OTHER_REFRESH_MSG)); 354a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 35529e8a73aSAxel Dörfler } 356a10cf76eSAxel Dörfler 357c9e8f97aSAdrien Destugues fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"), 35810dfe897SAxel Dörfler fRefreshMenu); 359b21d610eSAxel Dörfler 36012580984SAxel Dörfler if (_IsVesa()) 36112580984SAxel Dörfler fRefreshField->Hide(); 362a10cf76eSAxel Dörfler 363a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 364a10cf76eSAxel Dörfler { 365a10cf76eSAxel Dörfler bool dummy; 366a10cf76eSAxel Dörfler uint32 dummy32; 367a10cf76eSAxel Dörfler bool multiMonSupport; 368a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 369a10cf76eSAxel Dörfler bool tvStandardSupport; 370a10cf76eSAxel Dörfler 371a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 372a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 373a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 374a10cf76eSAxel Dörfler 375a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 376a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 377a10cf76eSAxel Dörfler 378551c9f15SSiarzhuk Zharski fCombineMenu = new BPopUpMenu("CombineDisplays", 379c9e8f97aSAdrien Destugues true, true); 380a10cf76eSAxel Dörfler 381a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 3820efb8b66SJerome Duval BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 383a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 384a10cf76eSAxel Dörfler 385d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 386d1516993SAxel Dörfler message)); 387a10cf76eSAxel Dörfler } 388a10cf76eSAxel Dörfler 389b21d610eSAxel Dörfler fCombineField = new BMenuField("CombineMenu", 39010dfe897SAxel Dörfler B_TRANSLATE("Combine displays:"), fCombineMenu); 391a10cf76eSAxel Dörfler 392a10cf76eSAxel Dörfler if (!multiMonSupport) 393df3f5bacSStephan Aßmus fCombineField->Hide(); 394a10cf76eSAxel Dörfler 395551c9f15SSiarzhuk Zharski fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", 396c9e8f97aSAdrien Destugues true, true); 397a10cf76eSAxel Dörfler 398a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 3990efb8b66SJerome Duval BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG); 400a10cf76eSAxel Dörfler message->AddBool("swap", false); 401c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message)); 402a10cf76eSAxel Dörfler 403a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 404a10cf76eSAxel Dörfler message->AddBool("swap", true); 405c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message)); 406a10cf76eSAxel Dörfler 407c9e8f97aSAdrien Destugues fSwapDisplaysField = new BMenuField("SwapMenu", 40810dfe897SAxel Dörfler B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu); 409a10cf76eSAxel Dörfler 410a10cf76eSAxel Dörfler if (!multiMonSupport) 411df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 412a10cf76eSAxel Dörfler 413551c9f15SSiarzhuk Zharski fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", 414c9e8f97aSAdrien Destugues true, true); 415a10cf76eSAxel Dörfler 416a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 417a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 418a10cf76eSAxel Dörfler message->AddBool("use", false); 419c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"), 420c9e8f97aSAdrien Destugues message)); 421a10cf76eSAxel Dörfler 422a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 423a10cf76eSAxel Dörfler message->AddBool("use", true); 424c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"), 425c9e8f97aSAdrien Destugues message)); 426a10cf76eSAxel Dörfler 427b21d610eSAxel Dörfler fUseLaptopPanelField = new BMenuField("UseLaptopPanel", 42810dfe897SAxel Dörfler B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu); 429a10cf76eSAxel Dörfler 430a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 431df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 432a10cf76eSAxel Dörfler 433551c9f15SSiarzhuk Zharski fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 434a10cf76eSAxel Dörfler 435a10cf76eSAxel Dörfler // arbitrary limit 436a10cf76eSAxel Dörfler uint32 i; 437a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 438a10cf76eSAxel Dörfler uint32 mode; 439a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 440a10cf76eSAxel Dörfler break; 441a10cf76eSAxel Dörfler 442a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 443a10cf76eSAxel Dörfler 444a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 445a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 446a10cf76eSAxel Dörfler 447a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 448a10cf76eSAxel Dörfler } 449a10cf76eSAxel Dörfler 450c9e8f97aSAdrien Destugues fTVStandardField = new BMenuField("tv standard", 45110dfe897SAxel Dörfler B_TRANSLATE("Video format:"), fTVStandardMenu); 452df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 453a10cf76eSAxel Dörfler 454b21d610eSAxel Dörfler if (!tvStandardSupport || i == 0) 455df3f5bacSStephan Aßmus fTVStandardField->Hide(); 456a10cf76eSAxel Dörfler } 457a10cf76eSAxel Dörfler 45825fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 45925fd5c7bSAlex Wilson .AddGrid(5.0, 5.0) 460b21d610eSAxel Dörfler .AddMenuField(fResolutionField, 0, 0, B_ALIGN_RIGHT) 461b21d610eSAxel Dörfler .AddMenuField(fColorsField, 0, 1, B_ALIGN_RIGHT) 462b21d610eSAxel Dörfler .AddMenuField(fRefreshField, 0, 2, B_ALIGN_RIGHT) 463b21d610eSAxel Dörfler .AddMenuField(fCombineField, 0, 3, B_ALIGN_RIGHT) 464b21d610eSAxel Dörfler .AddMenuField(fSwapDisplaysField, 0, 4, B_ALIGN_RIGHT) 465b21d610eSAxel Dörfler .AddMenuField(fUseLaptopPanelField, 0, 5, B_ALIGN_RIGHT) 46625fd5c7bSAlex Wilson .AddMenuField(fTVStandardField, 0, 6, B_ALIGN_RIGHT) 46725fd5c7bSAlex Wilson .End(); 468df3f5bacSStephan Aßmus 469abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 470abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 471b21d610eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG));*/ 472a10cf76eSAxel Dörfler 473c9e8f97aSAdrien Destugues fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"), 474df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 475df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 47625fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 477b21d610eSAxel Dörfler .AddGlue() 47825fd5c7bSAlex Wilson .AddGroup(B_HORIZONTAL) 47925fd5c7bSAlex Wilson .AddGlue() 48025fd5c7bSAlex Wilson .Add(fApplyButton); 481b21d610eSAxel Dörfler 482c9e8f97aSAdrien Destugues fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"), 483b21d610eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 484b21d610eSAxel Dörfler fRevertButton->SetEnabled(false); 485b21d610eSAxel Dörfler 48625fd5c7bSAlex Wilson BLayoutBuilder::Group<>(this, B_VERTICAL, 10.0) 487b21d610eSAxel Dörfler .SetInsets(10, 10, 10, 10) 488b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 10.0) 489b21d610eSAxel Dörfler .AddGroup(B_VERTICAL) 490958e0ca5SJohn Scipione .AddStrut(floor(controlsBox->TopBorderOffset() / 16) - 1) 491b21d610eSAxel Dörfler .Add(screenBox) 492b21d610eSAxel Dörfler .End() 493b21d610eSAxel Dörfler .Add(controlsBox) 494b21d610eSAxel Dörfler .End() 495b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 10.0) 496b21d610eSAxel Dörfler .Add(fRevertButton) 497b21d610eSAxel Dörfler .AddGlue(); 498b21d610eSAxel Dörfler 4995de171daSAxel Dörfler _UpdateControls(); 50012966d04SAxel Dörfler _UpdateMonitor(); 501a10cf76eSAxel Dörfler } 502a10cf76eSAxel Dörfler 503a10cf76eSAxel Dörfler 504a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 505a10cf76eSAxel Dörfler { 506a10cf76eSAxel Dörfler delete fSettings; 507a10cf76eSAxel Dörfler } 508a10cf76eSAxel Dörfler 509a10cf76eSAxel Dörfler 510a10cf76eSAxel Dörfler bool 511a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 512a10cf76eSAxel Dörfler { 513a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 514199893c3SAxel Dörfler 515199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 516199893c3SAxel Dörfler screen_mode vesaMode; 517199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 518199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 51912580984SAxel Dörfler if (status < B_OK) { 520c9e8f97aSAdrien Destugues BString warning = B_TRANSLATE("Could not write VESA mode settings" 521c9e8f97aSAdrien Destugues " file:\n\t"); 52212580984SAxel Dörfler warning << strerror(status); 523aed35104SHumdinger BAlert* alert = new BAlert(B_TRANSLATE("Warning"), 524aed35104SHumdinger warning.String(), B_TRANSLATE("OK"), NULL, 525aed35104SHumdinger NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 526aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 527aed35104SHumdinger alert->Go(); 52812580984SAxel Dörfler } 52912580984SAxel Dörfler } 53012580984SAxel Dörfler 531a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 532a10cf76eSAxel Dörfler 533a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 534a10cf76eSAxel Dörfler } 535a10cf76eSAxel Dörfler 536a10cf76eSAxel Dörfler 5375de171daSAxel Dörfler /*! Update resolution list according to combine mode 5381fc4cb1fSAxel Dörfler (some resolutions may not be combinable due to memory restrictions). 539a10cf76eSAxel Dörfler */ 540a10cf76eSAxel Dörfler void 5415de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 542a10cf76eSAxel Dörfler { 543a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 544a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 545a10cf76eSAxel Dörfler 546a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 547a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 548a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 549a10cf76eSAxel Dörfler continue; 550a10cf76eSAxel Dörfler 551a10cf76eSAxel Dörfler BString name; 552a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 553a10cf76eSAxel Dörfler 554a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 555a10cf76eSAxel Dörfler if (item != NULL) 556a10cf76eSAxel Dörfler item->SetEnabled(true); 557a10cf76eSAxel Dörfler } 558a10cf76eSAxel Dörfler } 559a10cf76eSAxel Dörfler 560a10cf76eSAxel Dörfler 5615de171daSAxel Dörfler /*! Update color and refresh options according to current mode 5625de171daSAxel Dörfler (a color space is made active if there is any mode with 5635de171daSAxel Dörfler given resolution and this colour space; same applies for 5645de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 565a10cf76eSAxel Dörfler */ 566a10cf76eSAxel Dörfler void 5675de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 568a10cf76eSAxel Dörfler { 5691fc4cb1fSAxel Dörfler int32 supportsAnything = false; 5701fc4cb1fSAxel Dörfler int32 index = 0; 5711fc4cb1fSAxel Dörfler 572a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 5731fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 5741fc4cb1fSAxel Dörfler continue; 5751fc4cb1fSAxel Dörfler 576a10cf76eSAxel Dörfler bool supported = false; 577a10cf76eSAxel Dörfler 578a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 579a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 580a10cf76eSAxel Dörfler 581a10cf76eSAxel Dörfler if (fSelected.width == mode.width 582a10cf76eSAxel Dörfler && fSelected.height == mode.height 5831fc4cb1fSAxel Dörfler && kColorSpaces[i].space == mode.space 584a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 5851fc4cb1fSAxel Dörfler supportsAnything = true; 586a10cf76eSAxel Dörfler supported = true; 587a10cf76eSAxel Dörfler break; 588a10cf76eSAxel Dörfler } 589a10cf76eSAxel Dörfler } 590a10cf76eSAxel Dörfler 5911fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(index++); 592a10cf76eSAxel Dörfler if (item) 593a10cf76eSAxel Dörfler item->SetEnabled(supported); 594a10cf76eSAxel Dörfler } 5951fc4cb1fSAxel Dörfler 5961fc4cb1fSAxel Dörfler fColorsField->SetEnabled(supportsAnything); 5971fc4cb1fSAxel Dörfler 5981fc4cb1fSAxel Dörfler if (!supportsAnything) 5991fc4cb1fSAxel Dörfler return; 6001fc4cb1fSAxel Dörfler 6011fc4cb1fSAxel Dörfler // Make sure a valid item is selected 6021fc4cb1fSAxel Dörfler 6031fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->FindMarked(); 6041fc4cb1fSAxel Dörfler bool changed = false; 6051fc4cb1fSAxel Dörfler 6061fc4cb1fSAxel Dörfler if (item != fUserSelectedColorSpace) { 6071fc4cb1fSAxel Dörfler if (fUserSelectedColorSpace != NULL 6081fc4cb1fSAxel Dörfler && fUserSelectedColorSpace->IsEnabled()) { 6091fc4cb1fSAxel Dörfler fUserSelectedColorSpace->SetMarked(true); 6101fc4cb1fSAxel Dörfler item = fUserSelectedColorSpace; 6111fc4cb1fSAxel Dörfler changed = true; 6121fc4cb1fSAxel Dörfler } 6131fc4cb1fSAxel Dörfler } 6141fc4cb1fSAxel Dörfler if (item != NULL && !item->IsEnabled()) { 6151fc4cb1fSAxel Dörfler // find the next best item 6161fc4cb1fSAxel Dörfler int32 index = fColorsMenu->IndexOf(item); 6171fc4cb1fSAxel Dörfler bool found = false; 6181fc4cb1fSAxel Dörfler 6191fc4cb1fSAxel Dörfler for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) { 6201fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6211fc4cb1fSAxel Dörfler if (item->IsEnabled()) { 6221fc4cb1fSAxel Dörfler found = true; 6231fc4cb1fSAxel Dörfler break; 6241fc4cb1fSAxel Dörfler } 6251fc4cb1fSAxel Dörfler } 6261fc4cb1fSAxel Dörfler if (!found) { 6271fc4cb1fSAxel Dörfler // search backwards as well 6281fc4cb1fSAxel Dörfler for (int32 i = index - 1; i >= 0; i--) { 6291fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6301fc4cb1fSAxel Dörfler if (item->IsEnabled()) 6311fc4cb1fSAxel Dörfler break; 6321fc4cb1fSAxel Dörfler } 6331fc4cb1fSAxel Dörfler } 6341fc4cb1fSAxel Dörfler 6351fc4cb1fSAxel Dörfler item->SetMarked(true); 6361fc4cb1fSAxel Dörfler changed = true; 6371fc4cb1fSAxel Dörfler } 6381fc4cb1fSAxel Dörfler 6391fc4cb1fSAxel Dörfler if (changed) { 6401fc4cb1fSAxel Dörfler // Update selected space 6411fc4cb1fSAxel Dörfler 6421fc4cb1fSAxel Dörfler BMessage* message = item->Message(); 6431fc4cb1fSAxel Dörfler int32 space; 6441fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) == B_OK) { 6451fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 6461fc4cb1fSAxel Dörfler _UpdateColorLabel(); 6471fc4cb1fSAxel Dörfler } 6481fc4cb1fSAxel Dörfler } 649a10cf76eSAxel Dörfler } 650a10cf76eSAxel Dörfler 651a10cf76eSAxel Dörfler 6525de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 653a10cf76eSAxel Dörfler void 6545de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 655a10cf76eSAxel Dörfler { 65629e8a73aSAxel Dörfler float min, max; 65729e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 65829e8a73aSAxel Dörfler return; 659a10cf76eSAxel Dörfler 66029e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 66129e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 66229e8a73aSAxel Dörfler BMessage* message = item->Message(); 66329e8a73aSAxel Dörfler float refresh; 66429e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 66529e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 666a10cf76eSAxel Dörfler } 667a10cf76eSAxel Dörfler } 668a10cf76eSAxel Dörfler 669a10cf76eSAxel Dörfler 6705de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 671a10cf76eSAxel Dörfler void 6725de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 673a10cf76eSAxel Dörfler { 6747e44de36SRene Gollent for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) { 6757e44de36SRene Gollent BMenuItem* item = fRefreshMenu->ItemAt(i); 6767e44de36SRene Gollent if (item->Message()->FindFloat("refresh") == fSelected.refresh) { 677a10cf76eSAxel Dörfler item->SetMarked(true); 67826747978SAdrien Destugues // "Other" items only contains a refresh rate when active 67926747978SAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 680a10cf76eSAxel Dörfler return; 681a10cf76eSAxel Dörfler } 6827e44de36SRene Gollent } 683a10cf76eSAxel Dörfler 684a10cf76eSAxel Dörfler // this is a non-standard refresh rate 6857e44de36SRene Gollent if (fOtherRefresh != NULL) { 686a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 687a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 688a10cf76eSAxel Dörfler 6897e44de36SRene Gollent BString string; 6907e44de36SRene Gollent refresh_rate_to_string(fSelected.refresh, string); 691a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 692a10cf76eSAxel Dörfler 693c9e8f97aSAdrien Destugues string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS)); 694a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 695a10cf76eSAxel Dörfler } 6967e44de36SRene Gollent } 697a10cf76eSAxel Dörfler 698a10cf76eSAxel Dörfler 699a10cf76eSAxel Dörfler void 7005de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 701a10cf76eSAxel Dörfler { 702a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 703a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 704a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 705a10cf76eSAxel Dörfler 706a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 707a10cf76eSAxel Dörfler } 708a10cf76eSAxel Dörfler 709a10cf76eSAxel Dörfler 710a10cf76eSAxel Dörfler void 7115de171daSAxel Dörfler ScreenWindow::_UpdateControls() 712a10cf76eSAxel Dörfler { 713b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 714b21d610eSAxel Dörfler 715a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 716*c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 717a10cf76eSAxel Dörfler item->SetMarked(true); 718a10cf76eSAxel Dörfler 719a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 720*c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 721a10cf76eSAxel Dörfler item->SetMarked(true); 722a10cf76eSAxel Dörfler 723a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 724a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 725a10cf76eSAxel Dörfler 726a10cf76eSAxel Dörfler uint32 tvStandard; 727a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 728a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 729a10cf76eSAxel Dörfler if (!item->IsMarked()) 730a10cf76eSAxel Dörfler item->SetMarked(true); 731a10cf76eSAxel Dörfler break; 732a10cf76eSAxel Dörfler } 733a10cf76eSAxel Dörfler } 734a10cf76eSAxel Dörfler 7355de171daSAxel Dörfler _CheckResolutionMenu(); 7365de171daSAxel Dörfler _CheckColorMenu(); 7375de171daSAxel Dörfler _CheckRefreshMenu(); 738a10cf76eSAxel Dörfler 739a10cf76eSAxel Dörfler BString string; 740a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 741a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 742a10cf76eSAxel Dörfler 743a10cf76eSAxel Dörfler if (item != NULL) { 744a10cf76eSAxel Dörfler if (!item->IsMarked()) 745a10cf76eSAxel Dörfler item->SetMarked(true); 746a10cf76eSAxel Dörfler } else { 747a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 748a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 749a10cf76eSAxel Dörfler // 1. add a new resolution to list 750a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 751a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 752a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 753a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 754a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 755a10cf76eSAxel Dörfler // 2. choose nearest resolution 756a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 757a10cf76eSAxel Dörfler // 3. choose lowest resolution 758a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 759a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 760a10cf76eSAxel Dörfler if (item) 761a10cf76eSAxel Dörfler item->SetMarked(true); 762a10cf76eSAxel Dörfler 763a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 764a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 765a10cf76eSAxel Dörfler } 766a10cf76eSAxel Dörfler 767a10cf76eSAxel Dörfler // mark active combine mode 768a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 769a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 770a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 771*c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 772a10cf76eSAxel Dörfler item->SetMarked(true); 773a10cf76eSAxel Dörfler break; 774a10cf76eSAxel Dörfler } 775a10cf76eSAxel Dörfler } 776a10cf76eSAxel Dörfler 777a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 778a10cf76eSAxel Dörfler 7791fc4cb1fSAxel Dörfler for (int32 i = 0, index = 0; i < kColorSpaceCount; i++) { 7801fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 7811fc4cb1fSAxel Dörfler continue; 7821fc4cb1fSAxel Dörfler 7831fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 7841fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(index); 785a10cf76eSAxel Dörfler break; 786a10cf76eSAxel Dörfler } 7871fc4cb1fSAxel Dörfler 7881fc4cb1fSAxel Dörfler index++; 789a10cf76eSAxel Dörfler } 790a10cf76eSAxel Dörfler 791*c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 792a10cf76eSAxel Dörfler item->SetMarked(true); 793a10cf76eSAxel Dörfler 7941fc4cb1fSAxel Dörfler _UpdateColorLabel(); 7955de171daSAxel Dörfler _UpdateMonitorView(); 7965de171daSAxel Dörfler _UpdateRefreshControl(); 797a10cf76eSAxel Dörfler 7985de171daSAxel Dörfler _CheckApplyEnabled(); 799a10cf76eSAxel Dörfler } 800a10cf76eSAxel Dörfler 801a10cf76eSAxel Dörfler 80212580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 803a10cf76eSAxel Dörfler void 8045de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 805a10cf76eSAxel Dörfler { 806c491b5adSJohn Scipione _UpdateActiveMode(current_workspace()); 807c491b5adSJohn Scipione } 808c491b5adSJohn Scipione 809c491b5adSJohn Scipione 810c491b5adSJohn Scipione void 811c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace) 812c491b5adSJohn Scipione { 81312580984SAxel Dörfler // Usually, this function gets called after a mode 814a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 815a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 816a10cf76eSAxel Dörfler // what kind of mode we actually got 817c491b5adSJohn Scipione if (fScreenMode.Get(fActive, workspace) == B_OK) { 818a10cf76eSAxel Dörfler fSelected = fActive; 819a10cf76eSAxel Dörfler 82012966d04SAxel Dörfler _UpdateMonitor(); 821c491b5adSJohn Scipione _BuildSupportedColorSpaces(); 8225de171daSAxel Dörfler _UpdateControls(); 823a10cf76eSAxel Dörfler } 824c491b5adSJohn Scipione } 825a10cf76eSAxel Dörfler 826a10cf76eSAxel Dörfler 827a10cf76eSAxel Dörfler void 828b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons() 829b21d610eSAxel Dörfler { 830b21d610eSAxel Dörfler uint32 columns; 831b21d610eSAxel Dörfler uint32 rows; 832b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 833b21d610eSAxel Dörfler 834b21d610eSAxel Dörfler char text[32]; 8355084d0d4SAlex Smith snprintf(text, sizeof(text), "%" B_PRId32, columns); 836b21d610eSAxel Dörfler fColumnsControl->SetText(text); 837b21d610eSAxel Dörfler 8385084d0d4SAlex Smith snprintf(text, sizeof(text), "%" B_PRId32, rows); 839b21d610eSAxel Dörfler fRowsControl->SetText(text); 840b21d610eSAxel Dörfler 841b21d610eSAxel Dörfler _GetColumnRowButton(true, false)->SetEnabled(columns != 1 && rows != 32); 842b21d610eSAxel Dörfler _GetColumnRowButton(true, true)->SetEnabled((columns + 1) * rows < 32); 843b21d610eSAxel Dörfler _GetColumnRowButton(false, false)->SetEnabled(rows != 1 && columns != 32); 844b21d610eSAxel Dörfler _GetColumnRowButton(false, true)->SetEnabled(columns * (rows + 1) < 32); 845b21d610eSAxel Dörfler } 846b21d610eSAxel Dörfler 847b21d610eSAxel Dörfler 848b21d610eSAxel Dörfler void 849a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 850a10cf76eSAxel Dörfler { 851a10cf76eSAxel Dörfler // move window on screen, if necessary 852a10cf76eSAxel Dörfler if (frame.right <= Frame().right 853a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 854a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 855a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 856a10cf76eSAxel Dörfler } 857a10cf76eSAxel Dörfler } 858a10cf76eSAxel Dörfler 859a10cf76eSAxel Dörfler 860a10cf76eSAxel Dörfler void 861a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 862a10cf76eSAxel Dörfler { 863c491b5adSJohn Scipione if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) { 864c491b5adSJohn Scipione _UpdateActiveMode(workspace); 865a10cf76eSAxel Dörfler 8666edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 8676edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 868a10cf76eSAxel Dörfler } 869c491b5adSJohn Scipione } 870a10cf76eSAxel Dörfler 871a10cf76eSAxel Dörfler 872a10cf76eSAxel Dörfler void 873a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 874a10cf76eSAxel Dörfler { 875a10cf76eSAxel Dörfler switch (message->what) { 876a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 8775de171daSAxel Dörfler _CheckApplyEnabled(); 878a10cf76eSAxel Dörfler break; 879a10cf76eSAxel Dörfler 880b21d610eSAxel Dörfler case kMsgWorkspaceLayoutChanged: 881a10cf76eSAxel Dörfler { 882b21d610eSAxel Dörfler int32 deltaX = 0; 883b21d610eSAxel Dörfler int32 deltaY = 0; 884b21d610eSAxel Dörfler message->FindInt32("delta_x", &deltaX); 885b21d610eSAxel Dörfler message->FindInt32("delta_y", &deltaY); 886b21d610eSAxel Dörfler 887b21d610eSAxel Dörfler if (deltaX == 0 && deltaY == 0) 888b21d610eSAxel Dörfler break; 889b21d610eSAxel Dörfler 890b21d610eSAxel Dörfler uint32 newColumns; 891b21d610eSAxel Dörfler uint32 newRows; 892b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&newColumns, &newRows); 893b21d610eSAxel Dörfler 894b21d610eSAxel Dörfler newColumns += deltaX; 895b21d610eSAxel Dörfler newRows += deltaY; 896b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, newRows); 897b21d610eSAxel Dörfler 898b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 8995de171daSAxel Dörfler _CheckApplyEnabled(); 900b21d610eSAxel Dörfler break; 901abc649b8SWaldemar Kornewald } 902b21d610eSAxel Dörfler 903b21d610eSAxel Dörfler case kMsgWorkspaceColumnsChanged: 904b21d610eSAxel Dörfler { 905b21d610eSAxel Dörfler uint32 newColumns = strtoul(fColumnsControl->Text(), NULL, 10); 906b21d610eSAxel Dörfler 907b21d610eSAxel Dörfler uint32 rows; 908b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(NULL, &rows); 909b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, rows); 910b21d610eSAxel Dörfler 911b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 912b21d610eSAxel Dörfler _CheckApplyEnabled(); 913b21d610eSAxel Dörfler break; 914b21d610eSAxel Dörfler } 915b21d610eSAxel Dörfler 916b21d610eSAxel Dörfler case kMsgWorkspaceRowsChanged: 917b21d610eSAxel Dörfler { 918b21d610eSAxel Dörfler uint32 newRows = strtoul(fRowsControl->Text(), NULL, 10); 919b21d610eSAxel Dörfler 920b21d610eSAxel Dörfler uint32 columns; 921b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, NULL); 922b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(columns, newRows); 923b21d610eSAxel Dörfler 924b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 925b21d610eSAxel Dörfler _CheckApplyEnabled(); 926a10cf76eSAxel Dörfler break; 927a10cf76eSAxel Dörfler } 928a10cf76eSAxel Dörfler 929a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 930a10cf76eSAxel Dörfler { 931a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 932a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 933a10cf76eSAxel Dörfler 9345de171daSAxel Dörfler _CheckColorMenu(); 9355de171daSAxel Dörfler _CheckRefreshMenu(); 936a10cf76eSAxel Dörfler 9375de171daSAxel Dörfler _UpdateMonitorView(); 9385de171daSAxel Dörfler _UpdateRefreshControl(); 939a10cf76eSAxel Dörfler 9405de171daSAxel Dörfler _CheckApplyEnabled(); 941a10cf76eSAxel Dörfler break; 942a10cf76eSAxel Dörfler } 943a10cf76eSAxel Dörfler 944a10cf76eSAxel Dörfler case POP_COLORS_MSG: 945a10cf76eSAxel Dörfler { 9461fc4cb1fSAxel Dörfler int32 space; 9471fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) != B_OK) 9481fc4cb1fSAxel Dörfler break; 949a10cf76eSAxel Dörfler 9501fc4cb1fSAxel Dörfler int32 index; 9511fc4cb1fSAxel Dörfler if (message->FindInt32("index", &index) == B_OK 9521fc4cb1fSAxel Dörfler && fColorsMenu->ItemAt(index) != NULL) 9531fc4cb1fSAxel Dörfler fUserSelectedColorSpace = fColorsMenu->ItemAt(index); 9541fc4cb1fSAxel Dörfler 9551fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 9561fc4cb1fSAxel Dörfler _UpdateColorLabel(); 957a10cf76eSAxel Dörfler 9585de171daSAxel Dörfler _CheckApplyEnabled(); 959a10cf76eSAxel Dörfler break; 960a10cf76eSAxel Dörfler } 961a10cf76eSAxel Dörfler 962a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 963a40498e2SWaldemar Kornewald { 964a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 965c9e8f97aSAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 9661fc4cb1fSAxel Dörfler // revert "Other…" label - it might have a refresh rate prefix 967a10cf76eSAxel Dörfler 9685de171daSAxel Dörfler _CheckApplyEnabled(); 969a10cf76eSAxel Dörfler break; 970a40498e2SWaldemar Kornewald } 971a10cf76eSAxel Dörfler 972a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 973a10cf76eSAxel Dörfler { 97429e8a73aSAxel Dörfler // make sure menu shows something useful 9755de171daSAxel Dörfler _UpdateRefreshControl(); 976a10cf76eSAxel Dörfler 97729e8a73aSAxel Dörfler float min = 0, max = 999; 97829e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 97929e8a73aSAxel Dörfler if (min < gMinRefresh) 98029e8a73aSAxel Dörfler min = gMinRefresh; 98129e8a73aSAxel Dörfler if (max > gMaxRefresh) 98229e8a73aSAxel Dörfler max = gMaxRefresh; 98329e8a73aSAxel Dörfler 98470a2b1b5SAxel Dörfler monitor_info info; 98570a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 98670a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 98770a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 98870a2b1b5SAxel Dörfler } 98970a2b1b5SAxel Dörfler 990c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 99170a2b1b5SAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, 99270a2b1b5SAxel Dörfler min, max); 993a10cf76eSAxel Dörfler fRefreshWindow->Show(); 994a10cf76eSAxel Dörfler break; 995a10cf76eSAxel Dörfler } 996a10cf76eSAxel Dörfler 997a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 998a10cf76eSAxel Dörfler { 999a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 1000a10cf76eSAxel Dörfler // select the refresh rate chosen 1001a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1002a10cf76eSAxel Dörfler 10035de171daSAxel Dörfler _UpdateRefreshControl(); 10045de171daSAxel Dörfler _CheckApplyEnabled(); 1005a10cf76eSAxel Dörfler break; 1006a10cf76eSAxel Dörfler } 1007a10cf76eSAxel Dörfler 1008a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 1009a10cf76eSAxel Dörfler { 1010a10cf76eSAxel Dörfler // new combine mode has bee chosen 1011a10cf76eSAxel Dörfler int32 mode; 1012a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 1013a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 1014a10cf76eSAxel Dörfler 10155de171daSAxel Dörfler _CheckResolutionMenu(); 10165de171daSAxel Dörfler _CheckApplyEnabled(); 1017a10cf76eSAxel Dörfler break; 1018a10cf76eSAxel Dörfler } 1019a10cf76eSAxel Dörfler 1020a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 1021a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 10225de171daSAxel Dörfler _CheckApplyEnabled(); 1023a10cf76eSAxel Dörfler break; 1024a10cf76eSAxel Dörfler 1025a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 1026a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 10275de171daSAxel Dörfler _CheckApplyEnabled(); 1028a10cf76eSAxel Dörfler break; 1029a10cf76eSAxel Dörfler 1030a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 1031a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 10325de171daSAxel Dörfler _CheckApplyEnabled(); 1033a10cf76eSAxel Dörfler break; 1034a10cf76eSAxel Dörfler 1035df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 10366f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 10376f095d6aSRyan Leavengood app_info info; 10386f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 10396f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 10406f095d6aSRyan Leavengood } 1041df3f5bacSStephan Aßmus break; 1042df3f5bacSStephan Aßmus 1043a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 1044a10cf76eSAxel Dörfler { 10454be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 1046a10cf76eSAxel Dörfler fSelected.width = 640; 1047a10cf76eSAxel Dörfler fSelected.height = 480; 1048a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 1049a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 1050a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 1051a10cf76eSAxel Dörfler fSelected.swap_displays = false; 1052a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 1053a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 1054a10cf76eSAxel Dörfler 1055b21d610eSAxel Dörfler // TODO: workspace defaults 1056abc649b8SWaldemar Kornewald 10575de171daSAxel Dörfler _UpdateControls(); 1058a10cf76eSAxel Dörfler break; 1059a10cf76eSAxel Dörfler } 1060a10cf76eSAxel Dörfler 106110e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 106261c5c89bSAxel Dörfler fUndoScreenMode.Revert(); 10635de171daSAxel Dörfler _UpdateActiveMode(); 1064abc649b8SWaldemar Kornewald break; 1065abc649b8SWaldemar Kornewald 1066abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 1067abc649b8SWaldemar Kornewald { 1068abc649b8SWaldemar Kornewald fModified = false; 1069199893c3SAxel Dörfler fBootWorkspaceApplied = false; 1070abc649b8SWaldemar Kornewald 1071b21d610eSAxel Dörfler // ScreenMode::Revert() assumes that we first set the correct 1072b21d610eSAxel Dörfler // number of workspaces 1073b21d610eSAxel Dörfler 1074b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns, 1075b21d610eSAxel Dörfler fOriginalWorkspacesRows); 1076b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 1077b21d610eSAxel Dörfler 1078a10cf76eSAxel Dörfler fScreenMode.Revert(); 10795de171daSAxel Dörfler _UpdateActiveMode(); 1080a10cf76eSAxel Dörfler break; 1081abc649b8SWaldemar Kornewald } 1082a10cf76eSAxel Dörfler 1083a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 10845de171daSAxel Dörfler _Apply(); 1085a10cf76eSAxel Dörfler break; 1086a10cf76eSAxel Dörfler 1087abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 1088abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 1089abc649b8SWaldemar Kornewald fModified = true; 10905de171daSAxel Dörfler _UpdateActiveMode(); 1091a10cf76eSAxel Dörfler break; 1092a10cf76eSAxel Dörfler 1093a10cf76eSAxel Dörfler default: 1094a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 1095a10cf76eSAxel Dörfler break; 1096a10cf76eSAxel Dörfler } 1097a10cf76eSAxel Dörfler } 1098a10cf76eSAxel Dörfler 1099a10cf76eSAxel Dörfler 110012580984SAxel Dörfler status_t 110112580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 110212580984SAxel Dörfler { 110312580984SAxel Dörfler BPath path; 110412580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 110512580984SAxel Dörfler if (status < B_OK) 110612580984SAxel Dörfler return status; 110712580984SAxel Dörfler 110812580984SAxel Dörfler path.Append("kernel/drivers"); 110912580984SAxel Dörfler status = create_directory(path.Path(), 0755); 111012580984SAxel Dörfler if (status < B_OK) 111112580984SAxel Dörfler return status; 111212580984SAxel Dörfler 111312580984SAxel Dörfler path.Append("vesa"); 111412580984SAxel Dörfler BFile file; 111512580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 111612580984SAxel Dörfler if (status < B_OK) 111712580984SAxel Dörfler return status; 111812580984SAxel Dörfler 111912580984SAxel Dörfler char buffer[256]; 11205084d0d4SAlex Smith snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %" 11215084d0d4SAlex Smith B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel()); 112212580984SAxel Dörfler 112312580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 112412580984SAxel Dörfler if (bytesWritten < B_OK) 112512580984SAxel Dörfler return bytesWritten; 112612580984SAxel Dörfler 112712580984SAxel Dörfler return B_OK; 112812580984SAxel Dörfler } 112912580984SAxel Dörfler 113012580984SAxel Dörfler 1131b21d610eSAxel Dörfler BButton* 1132b21d610eSAxel Dörfler ScreenWindow::_CreateColumnRowButton(bool columns, bool plus) 1133b21d610eSAxel Dörfler { 1134b21d610eSAxel Dörfler BMessage* message = new BMessage(kMsgWorkspaceLayoutChanged); 1135b21d610eSAxel Dörfler message->AddInt32("delta_x", columns ? (plus ? 1 : -1) : 0); 1136b21d610eSAxel Dörfler message->AddInt32("delta_y", !columns ? (plus ? 1 : -1) : 0); 1137b21d610eSAxel Dörfler 1138b21d610eSAxel Dörfler BButton* button = new BButton(plus ? "+" : "-", message); 1139b21d610eSAxel Dörfler button->SetFontSize(be_plain_font->Size() * 0.9); 1140b21d610eSAxel Dörfler 1141b21d610eSAxel Dörfler BSize size = button->MinSize(); 1142b21d610eSAxel Dörfler size.width = button->StringWidth("+") + 16; 1143b21d610eSAxel Dörfler button->SetExplicitMinSize(size); 1144b21d610eSAxel Dörfler button->SetExplicitMaxSize(size); 1145b21d610eSAxel Dörfler 1146b21d610eSAxel Dörfler fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)] = button; 1147b21d610eSAxel Dörfler return button; 1148b21d610eSAxel Dörfler } 1149b21d610eSAxel Dörfler 1150b21d610eSAxel Dörfler 1151b21d610eSAxel Dörfler BButton* 1152b21d610eSAxel Dörfler ScreenWindow::_GetColumnRowButton(bool columns, bool plus) 1153b21d610eSAxel Dörfler { 1154b21d610eSAxel Dörfler return fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)]; 1155b21d610eSAxel Dörfler } 1156b21d610eSAxel Dörfler 1157b21d610eSAxel Dörfler 1158a10cf76eSAxel Dörfler void 11591fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces() 11601fc4cb1fSAxel Dörfler { 11611fc4cb1fSAxel Dörfler fSupportedColorSpaces = 0; 11621fc4cb1fSAxel Dörfler 11631fc4cb1fSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 11641fc4cb1fSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 11651fc4cb1fSAxel Dörfler if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) { 11661fc4cb1fSAxel Dörfler fSupportedColorSpaces |= 1 << i; 11671fc4cb1fSAxel Dörfler break; 11681fc4cb1fSAxel Dörfler } 11691fc4cb1fSAxel Dörfler } 11701fc4cb1fSAxel Dörfler } 11711fc4cb1fSAxel Dörfler } 11721fc4cb1fSAxel Dörfler 11731fc4cb1fSAxel Dörfler 11741fc4cb1fSAxel Dörfler void 11755de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1176a10cf76eSAxel Dörfler { 117727c43a2dSRene Gollent fApplyButton->SetEnabled(fSelected != fActive 117827c43a2dSRene Gollent || fAllWorkspacesItem->IsMarked()); 1179b21d610eSAxel Dörfler 1180b21d610eSAxel Dörfler uint32 columns; 1181b21d610eSAxel Dörfler uint32 rows; 1182b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 1183b21d610eSAxel Dörfler 1184b21d610eSAxel Dörfler fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns 1185b21d610eSAxel Dörfler || rows != fOriginalWorkspacesRows 11865de171daSAxel Dörfler || fSelected != fOriginal); 1187a10cf76eSAxel Dörfler } 1188a10cf76eSAxel Dörfler 1189a10cf76eSAxel Dörfler 1190a10cf76eSAxel Dörfler void 11915de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1192abc649b8SWaldemar Kornewald { 1193b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns, 1194b21d610eSAxel Dörfler &fOriginalWorkspacesRows); 1195b21d610eSAxel Dörfler 1196abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1197abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1198abc649b8SWaldemar Kornewald } 1199abc649b8SWaldemar Kornewald 1200abc649b8SWaldemar Kornewald 1201abc649b8SWaldemar Kornewald void 120212966d04SAxel Dörfler ScreenWindow::_UpdateMonitor() 120312966d04SAxel Dörfler { 120412966d04SAxel Dörfler monitor_info info; 120512966d04SAxel Dörfler float diagonalInches; 120612966d04SAxel Dörfler status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches); 120755030977SAxel Dörfler if (status == B_OK) { 12081a8af605SAxel Dörfler char text[512]; 120966ab1666SAxel Dörfler snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor, 121066ab1666SAxel Dörfler info.name[0] ? " " : "", info.name, diagonalInches); 121112966d04SAxel Dörfler 121212966d04SAxel Dörfler fMonitorInfo->SetText(text); 121312966d04SAxel Dörfler 121412966d04SAxel Dörfler if (fMonitorInfo->IsHidden()) 121512966d04SAxel Dörfler fMonitorInfo->Show(); 121655030977SAxel Dörfler } else { 121755030977SAxel Dörfler if (!fMonitorInfo->IsHidden()) 121855030977SAxel Dörfler fMonitorInfo->Hide(); 121955030977SAxel Dörfler } 1220af8f9c31SAxel Dörfler 122155030977SAxel Dörfler char text[512]; 12221a8af605SAxel Dörfler size_t length = 0; 12231a8af605SAxel Dörfler text[0] = 0; 12241a8af605SAxel Dörfler 122555030977SAxel Dörfler if (status == B_OK) { 1226af8f9c31SAxel Dörfler if (info.min_horizontal_frequency != 0 1227af8f9c31SAxel Dörfler && info.min_vertical_frequency != 0 1228af8f9c31SAxel Dörfler && info.max_pixel_clock != 0) { 12291a8af605SAxel Dörfler length = snprintf(text, sizeof(text), 1230c9e8f97aSAdrien Destugues B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n" 12319c1a9b92SAdrien Destugues "Vertical frequency:\t%lu - %lu Hz\n\n" 1232c9e8f97aSAdrien Destugues "Maximum pixel clock:\t%g MHz"), 12331a8af605SAxel Dörfler info.min_horizontal_frequency, info.max_horizontal_frequency, 12341a8af605SAxel Dörfler info.min_vertical_frequency, info.max_vertical_frequency, 12351a8af605SAxel Dörfler info.max_pixel_clock / 1000.0); 1236af8f9c31SAxel Dörfler } 12371a8af605SAxel Dörfler if (info.serial_number[0] && length < sizeof(text)) { 12381a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 1239c9e8f97aSAdrien Destugues B_TRANSLATE("%sSerial no.: %s"), length ? "\n\n" : "", 12401a8af605SAxel Dörfler info.serial_number); 12411a8af605SAxel Dörfler if (info.produced.week != 0 && info.produced.year != 0 12421a8af605SAxel Dörfler && length < sizeof(text)) { 12431a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 12441a8af605SAxel Dörfler " (%u/%u)", info.produced.week, info.produced.year); 12451a8af605SAxel Dörfler } 12461a8af605SAxel Dörfler } 124755030977SAxel Dörfler } 124861c5c89bSAxel Dörfler 124961c5c89bSAxel Dörfler // Add info about the graphics device 125061c5c89bSAxel Dörfler 125161c5c89bSAxel Dörfler accelerant_device_info deviceInfo; 125261c5c89bSAxel Dörfler if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK 125361c5c89bSAxel Dörfler && length < sizeof(text)) { 125461c5c89bSAxel Dörfler if (deviceInfo.name[0] && deviceInfo.chipset[0]) { 125561c5c89bSAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 125661c5c89bSAxel Dörfler "%s%s (%s)", length != 0 ? "\n\n" : "", deviceInfo.name, 125761c5c89bSAxel Dörfler deviceInfo.chipset); 125861c5c89bSAxel Dörfler } else if (deviceInfo.name[0] || deviceInfo.chipset[0]) { 125961c5c89bSAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 126061c5c89bSAxel Dörfler "%s%s", length != 0 ? "\n\n" : "", deviceInfo.name[0] 126161c5c89bSAxel Dörfler ? deviceInfo.name : deviceInfo.chipset); 126261c5c89bSAxel Dörfler } 126361c5c89bSAxel Dörfler } 126461c5c89bSAxel Dörfler 12651a8af605SAxel Dörfler if (text[0]) 12661a8af605SAxel Dörfler fMonitorView->SetToolTip(text); 126712966d04SAxel Dörfler } 126812966d04SAxel Dörfler 126912966d04SAxel Dörfler 127012966d04SAxel Dörfler void 12711fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel() 12721fc4cb1fSAxel Dörfler { 12731fc4cb1fSAxel Dörfler BString string; 1274551c9f15SSiarzhuk Zharski string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel"); 12751fc4cb1fSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 12761fc4cb1fSAxel Dörfler } 12771fc4cb1fSAxel Dörfler 12781fc4cb1fSAxel Dörfler 12791fc4cb1fSAxel Dörfler void 12805de171daSAxel Dörfler ScreenWindow::_Apply() 1281a10cf76eSAxel Dörfler { 1282abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 128361c5c89bSAxel Dörfler fUndoScreenMode.UpdateOriginalModes(); 128461c5c89bSAxel Dörfler 128507184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 128607184a9eSAxel Dörfler if (status == B_OK) { 1287abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1288abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1289abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1290abc649b8SWaldemar Kornewald display_mode newMode; 1291abc649b8SWaldemar Kornewald BScreen screen(this); 1292abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1293abc649b8SWaldemar Kornewald 1294abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1295abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 1296abc649b8SWaldemar Kornewald for (int32 i = 0; i < count_workspaces(); i++) { 1297abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1298abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1299abc649b8SWaldemar Kornewald } 1300199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1301199893c3SAxel Dörfler } else { 1302199893c3SAxel Dörfler if (current_workspace() == 0) 1303199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1304abc649b8SWaldemar Kornewald } 1305abc649b8SWaldemar Kornewald 1306a10cf76eSAxel Dörfler fActive = fSelected; 1307a10cf76eSAxel Dörfler 1308abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 1309a10cf76eSAxel Dörfler BWindow* window = new AlertWindow(this); 1310a10cf76eSAxel Dörfler window->Show(); 131107184a9eSAxel Dörfler } else { 131207184a9eSAxel Dörfler char message[256]; 131307184a9eSAxel Dörfler snprintf(message, sizeof(message), 1314c9e8f97aSAdrien Destugues B_TRANSLATE("The screen mode could not be set:\n\t%s\n"), 1315c9e8f97aSAdrien Destugues screen_errors(status)); 1316551c9f15SSiarzhuk Zharski BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message, 1317c9e8f97aSAdrien Destugues B_TRANSLATE("OK"), NULL, NULL, 131807184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 1319aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 132007184a9eSAxel Dörfler alert->Go(); 1321a10cf76eSAxel Dörfler } 132207184a9eSAxel Dörfler } 1323