1a10cf76eSAxel Dörfler /* 2e1c88201SJohn Scipione * Copyright 2001-2013, Haiku, Inc. 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> 43b21d610eSAxel Dörfler #include <String.h> 44b21d610eSAxel Dörfler #include <StringView.h> 45b21d610eSAxel Dörfler #include <Roster.h> 46b21d610eSAxel Dörfler #include <Window.h> 47b21d610eSAxel Dörfler 48b21d610eSAxel Dörfler #include <InterfacePrivate.h> 49b21d610eSAxel Dörfler 50a10cf76eSAxel Dörfler #include "AlertWindow.h" 51a10cf76eSAxel Dörfler #include "Constants.h" 52a10cf76eSAxel Dörfler #include "RefreshWindow.h" 53a10cf76eSAxel Dörfler #include "MonitorView.h" 54a10cf76eSAxel Dörfler #include "ScreenSettings.h" 55a10cf76eSAxel Dörfler #include "Utility.h" 56a10cf76eSAxel Dörfler 57a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant. 58a10cf76eSAxel Dörfler * It's a solution that works with the current BeOS interface that Haiku 59a10cf76eSAxel Dörfler * adopted. 60a10cf76eSAxel Dörfler * However, it's not a nice and clean solution. Don't use this header in any 61a10cf76eSAxel Dörfler * application if you can avoid it. No other driver is using this, or should 62a10cf76eSAxel Dörfler * be using this. 63a10cf76eSAxel Dörfler * It will be replaced as soon as we introduce an updated accelerant interface 64a10cf76eSAxel Dörfler * which may even happen before R1 hits the streets. 65a10cf76eSAxel Dörfler */ 66a10cf76eSAxel Dörfler #include "multimon.h" // the usual: DANGER WILL, ROBINSON! 67a10cf76eSAxel Dörfler 68a10cf76eSAxel Dörfler 69546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 70546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Screen" 71c9e8f97aSAdrien Destugues 72c9e8f97aSAdrien Destugues 7375c92c56SRyan Leavengood const char* kBackgroundsSignature = "application/x-vnd.Haiku-Backgrounds"; 74c5d80d47SAxel Dörfler 75a10cf76eSAxel Dörfler // list of officially supported colour spaces 76a10cf76eSAxel Dörfler static const struct { 77a10cf76eSAxel Dörfler color_space space; 78a10cf76eSAxel Dörfler int32 bits_per_pixel; 79a10cf76eSAxel Dörfler const char* label; 80a10cf76eSAxel Dörfler } kColorSpaces[] = { 8126747978SAdrien Destugues { B_CMAP8, 8, B_TRANSLATE("8 bits/pixel, 256 colors") }, 82c9e8f97aSAdrien Destugues { B_RGB15, 15, B_TRANSLATE("15 bits/pixel, 32768 colors") }, 83c9e8f97aSAdrien Destugues { B_RGB16, 16, B_TRANSLATE("16 bits/pixel, 65536 colors") }, 84c9e8f97aSAdrien Destugues { B_RGB24, 24, B_TRANSLATE("24 bits/pixel, 16 Million colors") }, 85c9e8f97aSAdrien Destugues { B_RGB32, 32, B_TRANSLATE("32 bits/pixel, 16 Million colors") } 86a10cf76eSAxel Dörfler }; 87b21d610eSAxel Dörfler static const int32 kColorSpaceCount 88b21d610eSAxel Dörfler = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]); 89a10cf76eSAxel Dörfler 90a10cf76eSAxel Dörfler // list of standard refresh rates 91a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 }; 92b21d610eSAxel Dörfler static const int32 kRefreshRateCount 93b21d610eSAxel Dörfler = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); 94a10cf76eSAxel Dörfler 95a10cf76eSAxel Dörfler // list of combine modes 96a10cf76eSAxel Dörfler static const struct { 97a10cf76eSAxel Dörfler combine_mode mode; 98a10cf76eSAxel Dörfler const char *name; 99a10cf76eSAxel Dörfler } kCombineModes[] = { 100c9e8f97aSAdrien Destugues { kCombineDisable, B_TRANSLATE("disable") }, 101c9e8f97aSAdrien Destugues { kCombineHorizontally, B_TRANSLATE("horizontally") }, 102c9e8f97aSAdrien Destugues { kCombineVertically, B_TRANSLATE("vertically") } 103a10cf76eSAxel Dörfler }; 104b21d610eSAxel Dörfler static const int32 kCombineModeCount 105b21d610eSAxel Dörfler = sizeof(kCombineModes) / sizeof(kCombineModes[0]); 10629e8a73aSAxel Dörfler 107a10cf76eSAxel Dörfler 108a10cf76eSAxel Dörfler static BString 109a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode) 110a10cf76eSAxel Dörfler { 111a10cf76eSAxel Dörfler switch (mode) { 112a10cf76eSAxel Dörfler case 0: return "disabled"; 113a10cf76eSAxel Dörfler case 1: return "NTSC"; 114a10cf76eSAxel Dörfler case 2: return "NTSC Japan"; 115a10cf76eSAxel Dörfler case 3: return "PAL BDGHI"; 116a10cf76eSAxel Dörfler case 4: return "PAL M"; 117a10cf76eSAxel Dörfler case 5: return "PAL N"; 118a10cf76eSAxel Dörfler case 6: return "SECAM"; 119a10cf76eSAxel Dörfler case 101: return "NTSC 443"; 120a10cf76eSAxel Dörfler case 102: return "PAL 60"; 121a10cf76eSAxel Dörfler case 103: return "PAL NC"; 122a10cf76eSAxel Dörfler default: 123a10cf76eSAxel Dörfler { 124a10cf76eSAxel Dörfler BString name; 125a10cf76eSAxel Dörfler name << "??? (" << mode << ")"; 126a10cf76eSAxel Dörfler 127a10cf76eSAxel Dörfler return name; 128a10cf76eSAxel Dörfler } 129a10cf76eSAxel Dörfler } 130a10cf76eSAxel Dörfler } 131a10cf76eSAxel Dörfler 132a10cf76eSAxel Dörfler 133a10cf76eSAxel Dörfler static void 134a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string) 135a10cf76eSAxel Dörfler { 136a10cf76eSAxel Dörfler string << mode.width << " x " << mode.height; 137a10cf76eSAxel Dörfler } 138a10cf76eSAxel Dörfler 139a10cf76eSAxel Dörfler 140a10cf76eSAxel Dörfler static void 141a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string, 142a10cf76eSAxel Dörfler bool appendUnit = true, bool alwaysWithFraction = false) 143a10cf76eSAxel Dörfler { 1448bf23e3cSAxel Dörfler snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, 1458bf23e3cSAxel Dörfler refresh); 146a10cf76eSAxel Dörfler string.UnlockBuffer(); 147a10cf76eSAxel Dörfler 148a10cf76eSAxel Dörfler if (appendUnit) 149551c9f15SSiarzhuk Zharski string << " " << B_TRANSLATE("Hz"); 150a10cf76eSAxel Dörfler } 151a10cf76eSAxel Dörfler 152a10cf76eSAxel Dörfler 15307184a9eSAxel Dörfler static const char* 15407184a9eSAxel Dörfler screen_errors(status_t status) 15507184a9eSAxel Dörfler { 15607184a9eSAxel Dörfler switch (status) { 15707184a9eSAxel Dörfler case B_ENTRY_NOT_FOUND: 158c9e8f97aSAdrien Destugues return B_TRANSLATE("Unknown mode"); 15907184a9eSAxel Dörfler // TODO: add more? 16007184a9eSAxel Dörfler 16107184a9eSAxel Dörfler default: 16207184a9eSAxel Dörfler return strerror(status); 16307184a9eSAxel Dörfler } 16407184a9eSAxel Dörfler } 16507184a9eSAxel Dörfler 16629e8a73aSAxel Dörfler 1673dfd20c0SStephan Aßmus // #pragma mark - 1683dfd20c0SStephan Aßmus 1693dfd20c0SStephan Aßmus 1705a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings* settings) 171b21d610eSAxel Dörfler : 172560ff447SJonas Sundström BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Screen"), 173958e0ca5SJohn Scipione B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE 174958e0ca5SJohn Scipione | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), 1753f953a72SAxel Dörfler fIsVesa(false), 176199893c3SAxel Dörfler fBootWorkspaceApplied(false), 1777e44de36SRene Gollent fOtherRefresh(NULL), 178294a85aaSRene Gollent fScreenMode(this), 17961c5c89bSAxel Dörfler fUndoScreenMode(this), 180abc649b8SWaldemar Kornewald fModified(false) 181a10cf76eSAxel Dörfler { 182a10cf76eSAxel Dörfler BScreen screen(this); 183a10cf76eSAxel Dörfler 18412580984SAxel Dörfler accelerant_device_info info; 185d1516993SAxel Dörfler if (screen.GetDeviceInfo(&info) == B_OK 186d1516993SAxel Dörfler && !strcasecmp(info.chipset, "VESA")) 18712580984SAxel Dörfler fIsVesa = true; 18812580984SAxel Dörfler 1895de171daSAxel Dörfler _UpdateOriginal(); 1901fc4cb1fSAxel Dörfler _BuildSupportedColorSpaces(); 191a10cf76eSAxel Dörfler fActive = fSelected = fOriginal; 192a10cf76eSAxel Dörfler 1935a78744bSAxel Dörfler fSettings = settings; 1945a78744bSAxel Dörfler 1955a78744bSAxel Dörfler // we need the "Current Workspace" first to get its height 1965a78744bSAxel Dörfler 197c9e8f97aSAdrien Destugues BPopUpMenu *popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), 198c9e8f97aSAdrien Destugues true, true); 199c9e8f97aSAdrien Destugues fAllWorkspacesItem = new BMenuItem(B_TRANSLATE("All workspaces"), 200d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 2015a78744bSAxel Dörfler popUpMenu->AddItem(fAllWorkspacesItem); 202c9e8f97aSAdrien Destugues BMenuItem *item = new BMenuItem(B_TRANSLATE("Current workspace"), 203d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 204b72c4836SAlexandre Deckner 2055a78744bSAxel Dörfler popUpMenu->AddItem(item); 20627c43a2dSRene Gollent fAllWorkspacesItem->SetMarked(true); 2075a78744bSAxel Dörfler 208b21d610eSAxel Dörfler BMenuField* workspaceMenuField = new BMenuField("WorkspaceMenu", NULL, 20910dfe897SAxel Dörfler popUpMenu); 2105a78744bSAxel Dörfler workspaceMenuField->ResizeToPreferred(); 211a10cf76eSAxel Dörfler 212a10cf76eSAxel Dörfler // box on the left with workspace count and monitor view 213a10cf76eSAxel Dörfler 214b21d610eSAxel Dörfler BBox* screenBox = new BBox("screen box"); 215e1c88201SJohn Scipione BGroupLayout* layout = new BGroupLayout(B_VERTICAL, B_USE_SMALL_SPACING); 216e1c88201SJohn Scipione layout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 217e1c88201SJohn Scipione B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); 218b21d610eSAxel Dörfler screenBox->SetLayout(layout); 219a10cf76eSAxel Dörfler 22012966d04SAxel Dörfler fMonitorInfo = new BStringView("monitor info", ""); 221e1c88201SJohn Scipione fMonitorInfo->SetAlignment(B_ALIGN_CENTER); 22212966d04SAxel Dörfler screenBox->AddChild(fMonitorInfo); 22312966d04SAxel Dörfler 224*8b46ee25SAdrien Destugues fDeviceInfo = new BStringView("monitor info", ""); 225*8b46ee25SAdrien Destugues fDeviceInfo->SetAlignment(B_ALIGN_CENTER); 226*8b46ee25SAdrien Destugues screenBox->AddChild(fDeviceInfo); 227*8b46ee25SAdrien Destugues 228c9e8f97aSAdrien Destugues fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), 229551c9f15SSiarzhuk Zharski "monitor", screen.Frame().IntegerWidth() + 1, 230c9e8f97aSAdrien Destugues screen.Frame().IntegerHeight() + 1); 231b21d610eSAxel Dörfler screenBox->AddChild(fMonitorView); 2325a78744bSAxel Dörfler 233e1c88201SJohn Scipione BStringView* workspaces = new BStringView("workspaces", 234e1c88201SJohn Scipione B_TRANSLATE("Workspaces")); 235e1c88201SJohn Scipione workspaces->SetAlignment(B_ALIGN_CENTER); 236e1c88201SJohn Scipione 237c9e8f97aSAdrien Destugues fColumnsControl = new BTextControl(B_TRANSLATE("Columns:"), "0", 238b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceColumnsChanged)); 239e1c88201SJohn Scipione fColumnsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 240c9e8f97aSAdrien Destugues fRowsControl = new BTextControl(B_TRANSLATE("Rows:"), "0", 241b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceRowsChanged)); 242e1c88201SJohn Scipione fRowsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 243b21d610eSAxel Dörfler 244e1c88201SJohn Scipione float tiny = be_control_look->DefaultItemSpacing() / 4; 245e1c88201SJohn Scipione screenBox->AddChild(BLayoutBuilder::Group<>() 246e1c88201SJohn Scipione .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING) 247e1c88201SJohn Scipione .Add(workspaces) 248e1c88201SJohn Scipione .AddGrid(0.0, tiny) 249e1c88201SJohn Scipione // columns 250e1c88201SJohn Scipione .Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0) 251e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut( 252e1c88201SJohn Scipione B_USE_SMALL_SPACING), 1, 0) 253e1c88201SJohn Scipione .Add(fColumnsControl->CreateTextViewLayoutItem(), 2, 0) 254e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 0) 255e1c88201SJohn Scipione .Add(_CreateColumnRowButton(true, false), 4, 0) 256e1c88201SJohn Scipione .Add(_CreateColumnRowButton(true, true), 5, 0) 257e1c88201SJohn Scipione // rows 258e1c88201SJohn Scipione .Add(fRowsControl->CreateLabelLayoutItem(), 0, 1) 259e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut( 260e1c88201SJohn Scipione B_USE_SMALL_SPACING), 1, 1) 261e1c88201SJohn Scipione .Add(fRowsControl->CreateTextViewLayoutItem(), 2, 1) 262e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 1) 263e1c88201SJohn Scipione .Add(_CreateColumnRowButton(false, false), 4, 1) 264e1c88201SJohn Scipione .Add(_CreateColumnRowButton(false, true), 5, 1) 265b21d610eSAxel Dörfler .End() 26625fd5c7bSAlex Wilson .End() 26725fd5c7bSAlex Wilson .View()); 268b21d610eSAxel Dörfler 269b21d610eSAxel Dörfler fBackgroundsButton = new BButton("BackgroundsButton", 270c9e8f97aSAdrien Destugues B_TRANSLATE("Set background" B_UTF8_ELLIPSIS), 271b21d610eSAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 272b21d610eSAxel Dörfler fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 273b21d610eSAxel Dörfler screenBox->AddChild(fBackgroundsButton); 274a10cf76eSAxel Dörfler 275a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 276a10cf76eSAxel Dörfler 277b21d610eSAxel Dörfler BBox* controlsBox = new BBox("controls box"); 278b21d610eSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 2796048f541SJohn Scipione BGroupView* outerControlsView = new BGroupView(B_VERTICAL); 2806048f541SJohn Scipione outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING, 2816048f541SJohn Scipione B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); 282b21d610eSAxel Dörfler controlsBox->AddChild(outerControlsView); 283a10cf76eSAxel Dörfler 284551c9f15SSiarzhuk Zharski fResolutionMenu = new BPopUpMenu("resolution", true, true); 285a10cf76eSAxel Dörfler 28666ab1666SAxel Dörfler uint16 maxWidth = 0; 28766ab1666SAxel Dörfler uint16 maxHeight = 0; 28866ab1666SAxel Dörfler uint16 previousWidth = 0; 28966ab1666SAxel Dörfler uint16 previousHeight = 0; 290a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 291a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 292a10cf76eSAxel Dörfler 293a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 294a10cf76eSAxel Dörfler continue; 295a10cf76eSAxel Dörfler 296a10cf76eSAxel Dörfler previousWidth = mode.width; 297a10cf76eSAxel Dörfler previousHeight = mode.height; 29866ab1666SAxel Dörfler if (maxWidth < mode.width) 29966ab1666SAxel Dörfler maxWidth = mode.width; 30066ab1666SAxel Dörfler if (maxHeight < mode.height) 30166ab1666SAxel Dörfler maxHeight = mode.height; 302a10cf76eSAxel Dörfler 303a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_RESOLUTION_MSG); 304a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 305a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 306a10cf76eSAxel Dörfler 307a10cf76eSAxel Dörfler BString name; 308a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 309a10cf76eSAxel Dörfler 310a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 311a10cf76eSAxel Dörfler } 312a10cf76eSAxel Dörfler 31366ab1666SAxel Dörfler fMonitorView->SetMaxResolution(maxWidth, maxHeight); 31466ab1666SAxel Dörfler 315c9e8f97aSAdrien Destugues fResolutionField = new BMenuField("ResolutionMenu", 31610dfe897SAxel Dörfler B_TRANSLATE("Resolution:"), fResolutionMenu); 3176048f541SJohn Scipione fResolutionField->SetAlignment(B_ALIGN_RIGHT); 318a10cf76eSAxel Dörfler 319551c9f15SSiarzhuk Zharski fColorsMenu = new BPopUpMenu("colors", true, false); 320a10cf76eSAxel Dörfler 321a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 3221fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 3231fc4cb1fSAxel Dörfler continue; 3241fc4cb1fSAxel Dörfler 325a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_COLORS_MSG); 326a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 327a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 328a10cf76eSAxel Dörfler 3291fc4cb1fSAxel Dörfler BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); 3301fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == screen.ColorSpace()) 3311fc4cb1fSAxel Dörfler fUserSelectedColorSpace = item; 3321fc4cb1fSAxel Dörfler 3331fc4cb1fSAxel Dörfler fColorsMenu->AddItem(item); 334a10cf76eSAxel Dörfler } 335a10cf76eSAxel Dörfler 336c9e8f97aSAdrien Destugues fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"), 33710dfe897SAxel Dörfler fColorsMenu); 3386048f541SJohn Scipione fColorsField->SetAlignment(B_ALIGN_RIGHT); 339a10cf76eSAxel Dörfler 340551c9f15SSiarzhuk Zharski fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 341a10cf76eSAxel Dörfler 34229e8a73aSAxel Dörfler float min, max; 343ec495b30SRene Gollent if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) { 344ec495b30SRene Gollent // if we couldn't obtain the refresh limits, reset to the default 345ec495b30SRene Gollent // range. Constraints from detected monitors will fine-tune this 346ec495b30SRene Gollent // later. 347ec495b30SRene Gollent min = kRefreshRates[0]; 348ec495b30SRene Gollent max = kRefreshRates[kRefreshRateCount - 1]; 349ec495b30SRene Gollent } 350ec495b30SRene Gollent 351ec495b30SRene Gollent if (min == max) { 35229e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 35329e8a73aSAxel Dörfler // frequency, like the VESA driver 35429e8a73aSAxel Dörfler BString name; 3557e44de36SRene Gollent refresh_rate_to_string(min, name); 356cf076964SRene Gollent BMessage *message = new BMessage(POP_REFRESH_MSG); 357cf076964SRene Gollent message->AddFloat("refresh", min); 358cf076964SRene Gollent BMenuItem *item = new BMenuItem(name.String(), message); 3590efb8b66SJerome Duval fRefreshMenu->AddItem(item); 36029e8a73aSAxel Dörfler item->SetEnabled(false); 36129e8a73aSAxel Dörfler } else { 36270a2b1b5SAxel Dörfler monitor_info info; 36370a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 36470a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 36570a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 36670a2b1b5SAxel Dörfler } 36770a2b1b5SAxel Dörfler 368a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 36970a2b1b5SAxel Dörfler if (kRefreshRates[i] < min || kRefreshRates[i] > max) 37070a2b1b5SAxel Dörfler continue; 37170a2b1b5SAxel Dörfler 372a10cf76eSAxel Dörfler BString name; 373551c9f15SSiarzhuk Zharski name << kRefreshRates[i] << " " << B_TRANSLATE("Hz"); 374a10cf76eSAxel Dörfler 3750efb8b66SJerome Duval BMessage *message = new BMessage(POP_REFRESH_MSG); 376a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 377a10cf76eSAxel Dörfler 378a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 379a10cf76eSAxel Dörfler } 380a10cf76eSAxel Dörfler 381c9e8f97aSAdrien Destugues fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), 3820efb8b66SJerome Duval new BMessage(POP_OTHER_REFRESH_MSG)); 383a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 38429e8a73aSAxel Dörfler } 385a10cf76eSAxel Dörfler 386c9e8f97aSAdrien Destugues fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"), 38710dfe897SAxel Dörfler fRefreshMenu); 3886048f541SJohn Scipione fRefreshField->SetAlignment(B_ALIGN_RIGHT); 389b21d610eSAxel Dörfler 39012580984SAxel Dörfler if (_IsVesa()) 39112580984SAxel Dörfler fRefreshField->Hide(); 392a10cf76eSAxel Dörfler 393a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 394a10cf76eSAxel Dörfler { 395a10cf76eSAxel Dörfler bool dummy; 396a10cf76eSAxel Dörfler uint32 dummy32; 397a10cf76eSAxel Dörfler bool multiMonSupport; 398a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 399a10cf76eSAxel Dörfler bool tvStandardSupport; 400a10cf76eSAxel Dörfler 401a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 402a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 403a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 404a10cf76eSAxel Dörfler 405a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 406a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 407a10cf76eSAxel Dörfler 408551c9f15SSiarzhuk Zharski fCombineMenu = new BPopUpMenu("CombineDisplays", 409c9e8f97aSAdrien Destugues true, true); 410a10cf76eSAxel Dörfler 411a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 4120efb8b66SJerome Duval BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 413a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 414a10cf76eSAxel Dörfler 415d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 416d1516993SAxel Dörfler message)); 417a10cf76eSAxel Dörfler } 418a10cf76eSAxel Dörfler 419b21d610eSAxel Dörfler fCombineField = new BMenuField("CombineMenu", 42010dfe897SAxel Dörfler B_TRANSLATE("Combine displays:"), fCombineMenu); 4216048f541SJohn Scipione fCombineField->SetAlignment(B_ALIGN_RIGHT); 422a10cf76eSAxel Dörfler 423a10cf76eSAxel Dörfler if (!multiMonSupport) 424df3f5bacSStephan Aßmus fCombineField->Hide(); 425a10cf76eSAxel Dörfler 426551c9f15SSiarzhuk Zharski fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", 427c9e8f97aSAdrien Destugues true, true); 428a10cf76eSAxel Dörfler 429a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 4300efb8b66SJerome Duval BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG); 431a10cf76eSAxel Dörfler message->AddBool("swap", false); 432c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message)); 433a10cf76eSAxel Dörfler 434a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 435a10cf76eSAxel Dörfler message->AddBool("swap", true); 436c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message)); 437a10cf76eSAxel Dörfler 438c9e8f97aSAdrien Destugues fSwapDisplaysField = new BMenuField("SwapMenu", 43910dfe897SAxel Dörfler B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu); 4406048f541SJohn Scipione fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT); 441a10cf76eSAxel Dörfler 442a10cf76eSAxel Dörfler if (!multiMonSupport) 443df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 444a10cf76eSAxel Dörfler 445551c9f15SSiarzhuk Zharski fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", 446c9e8f97aSAdrien Destugues true, true); 447a10cf76eSAxel Dörfler 448a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 449a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 450a10cf76eSAxel Dörfler message->AddBool("use", false); 451c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"), 452c9e8f97aSAdrien Destugues message)); 453a10cf76eSAxel Dörfler 454a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 455a10cf76eSAxel Dörfler message->AddBool("use", true); 456c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"), 457c9e8f97aSAdrien Destugues message)); 458a10cf76eSAxel Dörfler 459b21d610eSAxel Dörfler fUseLaptopPanelField = new BMenuField("UseLaptopPanel", 46010dfe897SAxel Dörfler B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu); 4616048f541SJohn Scipione fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT); 462a10cf76eSAxel Dörfler 463a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 464df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 465a10cf76eSAxel Dörfler 466551c9f15SSiarzhuk Zharski fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 467a10cf76eSAxel Dörfler 468a10cf76eSAxel Dörfler // arbitrary limit 469a10cf76eSAxel Dörfler uint32 i; 470a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 471a10cf76eSAxel Dörfler uint32 mode; 472a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 473a10cf76eSAxel Dörfler break; 474a10cf76eSAxel Dörfler 475a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 476a10cf76eSAxel Dörfler 477a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 478a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 479a10cf76eSAxel Dörfler 480a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 481a10cf76eSAxel Dörfler } 482a10cf76eSAxel Dörfler 483c9e8f97aSAdrien Destugues fTVStandardField = new BMenuField("tv standard", 48410dfe897SAxel Dörfler B_TRANSLATE("Video format:"), fTVStandardMenu); 485df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 486a10cf76eSAxel Dörfler 487b21d610eSAxel Dörfler if (!tvStandardSupport || i == 0) 488df3f5bacSStephan Aßmus fTVStandardField->Hide(); 489a10cf76eSAxel Dörfler } 490a10cf76eSAxel Dörfler 49125fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 4926048f541SJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 4936048f541SJohn Scipione .Add(fResolutionField->CreateLabelLayoutItem(), 0, 0) 4946048f541SJohn Scipione .Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0) 4956048f541SJohn Scipione .Add(fColorsField->CreateLabelLayoutItem(), 0, 1) 4966048f541SJohn Scipione .Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1) 4976048f541SJohn Scipione .Add(fRefreshField->CreateLabelLayoutItem(), 0, 2) 4986048f541SJohn Scipione .Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2) 4996048f541SJohn Scipione .Add(fCombineField->CreateLabelLayoutItem(), 0, 3) 5006048f541SJohn Scipione .Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3) 5016048f541SJohn Scipione .Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4) 5026048f541SJohn Scipione .Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4) 5036048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5) 5046048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5) 5056048f541SJohn Scipione .Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6) 5066048f541SJohn Scipione .Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6) 50725fd5c7bSAlex Wilson .End(); 508df3f5bacSStephan Aßmus 509abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 510abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 511b21d610eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG));*/ 512a10cf76eSAxel Dörfler 513c9e8f97aSAdrien Destugues fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"), 514df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 515df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 51625fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 517b21d610eSAxel Dörfler .AddGlue() 51825fd5c7bSAlex Wilson .AddGroup(B_HORIZONTAL) 51925fd5c7bSAlex Wilson .AddGlue() 52025fd5c7bSAlex Wilson .Add(fApplyButton); 521b21d610eSAxel Dörfler 522c9e8f97aSAdrien Destugues fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"), 523b21d610eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 524b21d610eSAxel Dörfler fRevertButton->SetEnabled(false); 525b21d610eSAxel Dörfler 5264666484fSJohn Scipione BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) 5274666484fSJohn Scipione .AddGroup(B_HORIZONTAL) 52883cc66b3SJohn Scipione .AddGroup(B_VERTICAL, 0) 52983cc66b3SJohn Scipione .AddStrut(floorf(controlsBox->TopBorderOffset()) - 1) 530b21d610eSAxel Dörfler .Add(screenBox) 53183cc66b3SJohn Scipione .End() 532b21d610eSAxel Dörfler .Add(controlsBox) 533b21d610eSAxel Dörfler .End() 5344666484fSJohn Scipione .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 535b21d610eSAxel Dörfler .Add(fRevertButton) 5364666484fSJohn Scipione .AddGlue() 5374666484fSJohn Scipione .End() 5384666484fSJohn Scipione .SetInsets(B_USE_DEFAULT_SPACING); 539b21d610eSAxel Dörfler 5405de171daSAxel Dörfler _UpdateControls(); 54112966d04SAxel Dörfler _UpdateMonitor(); 542a10cf76eSAxel Dörfler } 543a10cf76eSAxel Dörfler 544a10cf76eSAxel Dörfler 545a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 546a10cf76eSAxel Dörfler { 547a10cf76eSAxel Dörfler delete fSettings; 548a10cf76eSAxel Dörfler } 549a10cf76eSAxel Dörfler 550a10cf76eSAxel Dörfler 551a10cf76eSAxel Dörfler bool 552a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 553a10cf76eSAxel Dörfler { 554a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 555199893c3SAxel Dörfler 556199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 557199893c3SAxel Dörfler screen_mode vesaMode; 558199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 559199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 56012580984SAxel Dörfler if (status < B_OK) { 561c9e8f97aSAdrien Destugues BString warning = B_TRANSLATE("Could not write VESA mode settings" 562c9e8f97aSAdrien Destugues " file:\n\t"); 56312580984SAxel Dörfler warning << strerror(status); 564aed35104SHumdinger BAlert* alert = new BAlert(B_TRANSLATE("Warning"), 565aed35104SHumdinger warning.String(), B_TRANSLATE("OK"), NULL, 566aed35104SHumdinger NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 567aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 568aed35104SHumdinger alert->Go(); 56912580984SAxel Dörfler } 57012580984SAxel Dörfler } 57112580984SAxel Dörfler 572a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 573a10cf76eSAxel Dörfler 574a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 575a10cf76eSAxel Dörfler } 576a10cf76eSAxel Dörfler 577a10cf76eSAxel Dörfler 5785de171daSAxel Dörfler /*! Update resolution list according to combine mode 5791fc4cb1fSAxel Dörfler (some resolutions may not be combinable due to memory restrictions). 580a10cf76eSAxel Dörfler */ 581a10cf76eSAxel Dörfler void 5825de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 583a10cf76eSAxel Dörfler { 584a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 585a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 586a10cf76eSAxel Dörfler 587a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 588a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 589a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 590a10cf76eSAxel Dörfler continue; 591a10cf76eSAxel Dörfler 592a10cf76eSAxel Dörfler BString name; 593a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 594a10cf76eSAxel Dörfler 595a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 596a10cf76eSAxel Dörfler if (item != NULL) 597a10cf76eSAxel Dörfler item->SetEnabled(true); 598a10cf76eSAxel Dörfler } 599a10cf76eSAxel Dörfler } 600a10cf76eSAxel Dörfler 601a10cf76eSAxel Dörfler 6025de171daSAxel Dörfler /*! Update color and refresh options according to current mode 6035de171daSAxel Dörfler (a color space is made active if there is any mode with 6045de171daSAxel Dörfler given resolution and this colour space; same applies for 6055de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 606a10cf76eSAxel Dörfler */ 607a10cf76eSAxel Dörfler void 6085de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 609a10cf76eSAxel Dörfler { 6101fc4cb1fSAxel Dörfler int32 supportsAnything = false; 6111fc4cb1fSAxel Dörfler int32 index = 0; 6121fc4cb1fSAxel Dörfler 613a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 6141fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 6151fc4cb1fSAxel Dörfler continue; 6161fc4cb1fSAxel Dörfler 617a10cf76eSAxel Dörfler bool supported = false; 618a10cf76eSAxel Dörfler 619a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 620a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 621a10cf76eSAxel Dörfler 622a10cf76eSAxel Dörfler if (fSelected.width == mode.width 623a10cf76eSAxel Dörfler && fSelected.height == mode.height 6241fc4cb1fSAxel Dörfler && kColorSpaces[i].space == mode.space 625a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 6261fc4cb1fSAxel Dörfler supportsAnything = true; 627a10cf76eSAxel Dörfler supported = true; 628a10cf76eSAxel Dörfler break; 629a10cf76eSAxel Dörfler } 630a10cf76eSAxel Dörfler } 631a10cf76eSAxel Dörfler 6321fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(index++); 633a10cf76eSAxel Dörfler if (item) 634a10cf76eSAxel Dörfler item->SetEnabled(supported); 635a10cf76eSAxel Dörfler } 6361fc4cb1fSAxel Dörfler 6371fc4cb1fSAxel Dörfler fColorsField->SetEnabled(supportsAnything); 6381fc4cb1fSAxel Dörfler 6391fc4cb1fSAxel Dörfler if (!supportsAnything) 6401fc4cb1fSAxel Dörfler return; 6411fc4cb1fSAxel Dörfler 6421fc4cb1fSAxel Dörfler // Make sure a valid item is selected 6431fc4cb1fSAxel Dörfler 6441fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->FindMarked(); 6451fc4cb1fSAxel Dörfler bool changed = false; 6461fc4cb1fSAxel Dörfler 6471fc4cb1fSAxel Dörfler if (item != fUserSelectedColorSpace) { 6481fc4cb1fSAxel Dörfler if (fUserSelectedColorSpace != NULL 6491fc4cb1fSAxel Dörfler && fUserSelectedColorSpace->IsEnabled()) { 6501fc4cb1fSAxel Dörfler fUserSelectedColorSpace->SetMarked(true); 6511fc4cb1fSAxel Dörfler item = fUserSelectedColorSpace; 6521fc4cb1fSAxel Dörfler changed = true; 6531fc4cb1fSAxel Dörfler } 6541fc4cb1fSAxel Dörfler } 6551fc4cb1fSAxel Dörfler if (item != NULL && !item->IsEnabled()) { 6561fc4cb1fSAxel Dörfler // find the next best item 6571fc4cb1fSAxel Dörfler int32 index = fColorsMenu->IndexOf(item); 6581fc4cb1fSAxel Dörfler bool found = false; 6591fc4cb1fSAxel Dörfler 6601fc4cb1fSAxel Dörfler for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) { 6611fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6621fc4cb1fSAxel Dörfler if (item->IsEnabled()) { 6631fc4cb1fSAxel Dörfler found = true; 6641fc4cb1fSAxel Dörfler break; 6651fc4cb1fSAxel Dörfler } 6661fc4cb1fSAxel Dörfler } 6671fc4cb1fSAxel Dörfler if (!found) { 6681fc4cb1fSAxel Dörfler // search backwards as well 6691fc4cb1fSAxel Dörfler for (int32 i = index - 1; i >= 0; i--) { 6701fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6711fc4cb1fSAxel Dörfler if (item->IsEnabled()) 6721fc4cb1fSAxel Dörfler break; 6731fc4cb1fSAxel Dörfler } 6741fc4cb1fSAxel Dörfler } 6751fc4cb1fSAxel Dörfler 6761fc4cb1fSAxel Dörfler item->SetMarked(true); 6771fc4cb1fSAxel Dörfler changed = true; 6781fc4cb1fSAxel Dörfler } 6791fc4cb1fSAxel Dörfler 6801fc4cb1fSAxel Dörfler if (changed) { 6811fc4cb1fSAxel Dörfler // Update selected space 6821fc4cb1fSAxel Dörfler 6831fc4cb1fSAxel Dörfler BMessage* message = item->Message(); 6841fc4cb1fSAxel Dörfler int32 space; 6851fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) == B_OK) { 6861fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 6871fc4cb1fSAxel Dörfler _UpdateColorLabel(); 6881fc4cb1fSAxel Dörfler } 6891fc4cb1fSAxel Dörfler } 690a10cf76eSAxel Dörfler } 691a10cf76eSAxel Dörfler 692a10cf76eSAxel Dörfler 6935de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 694a10cf76eSAxel Dörfler void 6955de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 696a10cf76eSAxel Dörfler { 69729e8a73aSAxel Dörfler float min, max; 69829e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 69929e8a73aSAxel Dörfler return; 700a10cf76eSAxel Dörfler 70129e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 70229e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 70329e8a73aSAxel Dörfler BMessage* message = item->Message(); 70429e8a73aSAxel Dörfler float refresh; 70529e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 70629e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 707a10cf76eSAxel Dörfler } 708a10cf76eSAxel Dörfler } 709a10cf76eSAxel Dörfler 710a10cf76eSAxel Dörfler 7115de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 712a10cf76eSAxel Dörfler void 7135de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 714a10cf76eSAxel Dörfler { 7157e44de36SRene Gollent for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) { 7167e44de36SRene Gollent BMenuItem* item = fRefreshMenu->ItemAt(i); 7177e44de36SRene Gollent if (item->Message()->FindFloat("refresh") == fSelected.refresh) { 718a10cf76eSAxel Dörfler item->SetMarked(true); 71926747978SAdrien Destugues // "Other" items only contains a refresh rate when active 72026747978SAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 721a10cf76eSAxel Dörfler return; 722a10cf76eSAxel Dörfler } 7237e44de36SRene Gollent } 724a10cf76eSAxel Dörfler 725a10cf76eSAxel Dörfler // this is a non-standard refresh rate 7267e44de36SRene Gollent if (fOtherRefresh != NULL) { 727a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 728a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 729a10cf76eSAxel Dörfler 7307e44de36SRene Gollent BString string; 7317e44de36SRene Gollent refresh_rate_to_string(fSelected.refresh, string); 732a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 733a10cf76eSAxel Dörfler 734c9e8f97aSAdrien Destugues string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS)); 735a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 736a10cf76eSAxel Dörfler } 7377e44de36SRene Gollent } 738a10cf76eSAxel Dörfler 739a10cf76eSAxel Dörfler 740a10cf76eSAxel Dörfler void 7415de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 742a10cf76eSAxel Dörfler { 743a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 744a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 745a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 746a10cf76eSAxel Dörfler 747a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 748a10cf76eSAxel Dörfler } 749a10cf76eSAxel Dörfler 750a10cf76eSAxel Dörfler 751a10cf76eSAxel Dörfler void 7525de171daSAxel Dörfler ScreenWindow::_UpdateControls() 753a10cf76eSAxel Dörfler { 754b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 755b21d610eSAxel Dörfler 756a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 757c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 758a10cf76eSAxel Dörfler item->SetMarked(true); 759a10cf76eSAxel Dörfler 760a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 761c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 762a10cf76eSAxel Dörfler item->SetMarked(true); 763a10cf76eSAxel Dörfler 764a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 765a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 766a10cf76eSAxel Dörfler 767a10cf76eSAxel Dörfler uint32 tvStandard; 768a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 769a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 770a10cf76eSAxel Dörfler if (!item->IsMarked()) 771a10cf76eSAxel Dörfler item->SetMarked(true); 772a10cf76eSAxel Dörfler break; 773a10cf76eSAxel Dörfler } 774a10cf76eSAxel Dörfler } 775a10cf76eSAxel Dörfler 7765de171daSAxel Dörfler _CheckResolutionMenu(); 7775de171daSAxel Dörfler _CheckColorMenu(); 7785de171daSAxel Dörfler _CheckRefreshMenu(); 779a10cf76eSAxel Dörfler 780a10cf76eSAxel Dörfler BString string; 781a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 782a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 783a10cf76eSAxel Dörfler 784a10cf76eSAxel Dörfler if (item != NULL) { 785a10cf76eSAxel Dörfler if (!item->IsMarked()) 786a10cf76eSAxel Dörfler item->SetMarked(true); 787a10cf76eSAxel Dörfler } else { 788a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 789a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 790a10cf76eSAxel Dörfler // 1. add a new resolution to list 791a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 792a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 793a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 794a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 795a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 796a10cf76eSAxel Dörfler // 2. choose nearest resolution 797a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 798a10cf76eSAxel Dörfler // 3. choose lowest resolution 799a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 800a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 801a10cf76eSAxel Dörfler if (item) 802a10cf76eSAxel Dörfler item->SetMarked(true); 803a10cf76eSAxel Dörfler 804a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 805a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 806a10cf76eSAxel Dörfler } 807a10cf76eSAxel Dörfler 808a10cf76eSAxel Dörfler // mark active combine mode 809a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 810a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 811a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 812c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 813a10cf76eSAxel Dörfler item->SetMarked(true); 814a10cf76eSAxel Dörfler break; 815a10cf76eSAxel Dörfler } 816a10cf76eSAxel Dörfler } 817a10cf76eSAxel Dörfler 818a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 819a10cf76eSAxel Dörfler 8201fc4cb1fSAxel Dörfler for (int32 i = 0, index = 0; i < kColorSpaceCount; i++) { 8211fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 8221fc4cb1fSAxel Dörfler continue; 8231fc4cb1fSAxel Dörfler 8241fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 8251fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(index); 826a10cf76eSAxel Dörfler break; 827a10cf76eSAxel Dörfler } 8281fc4cb1fSAxel Dörfler 8291fc4cb1fSAxel Dörfler index++; 830a10cf76eSAxel Dörfler } 831a10cf76eSAxel Dörfler 832c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 833a10cf76eSAxel Dörfler item->SetMarked(true); 834a10cf76eSAxel Dörfler 8351fc4cb1fSAxel Dörfler _UpdateColorLabel(); 8365de171daSAxel Dörfler _UpdateMonitorView(); 8375de171daSAxel Dörfler _UpdateRefreshControl(); 838a10cf76eSAxel Dörfler 8395de171daSAxel Dörfler _CheckApplyEnabled(); 840a10cf76eSAxel Dörfler } 841a10cf76eSAxel Dörfler 842a10cf76eSAxel Dörfler 84312580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 844a10cf76eSAxel Dörfler void 8455de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 846a10cf76eSAxel Dörfler { 847c491b5adSJohn Scipione _UpdateActiveMode(current_workspace()); 848c491b5adSJohn Scipione } 849c491b5adSJohn Scipione 850c491b5adSJohn Scipione 851c491b5adSJohn Scipione void 852c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace) 853c491b5adSJohn Scipione { 85412580984SAxel Dörfler // Usually, this function gets called after a mode 855a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 856a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 857a10cf76eSAxel Dörfler // what kind of mode we actually got 858c491b5adSJohn Scipione if (fScreenMode.Get(fActive, workspace) == B_OK) { 859a10cf76eSAxel Dörfler fSelected = fActive; 860a10cf76eSAxel Dörfler 86112966d04SAxel Dörfler _UpdateMonitor(); 862c491b5adSJohn Scipione _BuildSupportedColorSpaces(); 8635de171daSAxel Dörfler _UpdateControls(); 864a10cf76eSAxel Dörfler } 865c491b5adSJohn Scipione } 866a10cf76eSAxel Dörfler 867a10cf76eSAxel Dörfler 868a10cf76eSAxel Dörfler void 869b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons() 870b21d610eSAxel Dörfler { 871b21d610eSAxel Dörfler uint32 columns; 872b21d610eSAxel Dörfler uint32 rows; 873b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 874b21d610eSAxel Dörfler 875b21d610eSAxel Dörfler char text[32]; 8765084d0d4SAlex Smith snprintf(text, sizeof(text), "%" B_PRId32, columns); 877b21d610eSAxel Dörfler fColumnsControl->SetText(text); 878b21d610eSAxel Dörfler 8795084d0d4SAlex Smith snprintf(text, sizeof(text), "%" B_PRId32, rows); 880b21d610eSAxel Dörfler fRowsControl->SetText(text); 881b21d610eSAxel Dörfler 882b21d610eSAxel Dörfler _GetColumnRowButton(true, false)->SetEnabled(columns != 1 && rows != 32); 883b21d610eSAxel Dörfler _GetColumnRowButton(true, true)->SetEnabled((columns + 1) * rows < 32); 884b21d610eSAxel Dörfler _GetColumnRowButton(false, false)->SetEnabled(rows != 1 && columns != 32); 885b21d610eSAxel Dörfler _GetColumnRowButton(false, true)->SetEnabled(columns * (rows + 1) < 32); 886b21d610eSAxel Dörfler } 887b21d610eSAxel Dörfler 888b21d610eSAxel Dörfler 889b21d610eSAxel Dörfler void 890a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 891a10cf76eSAxel Dörfler { 892a10cf76eSAxel Dörfler // move window on screen, if necessary 893a10cf76eSAxel Dörfler if (frame.right <= Frame().right 894a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 895a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 896a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 897a10cf76eSAxel Dörfler } 898a10cf76eSAxel Dörfler } 899a10cf76eSAxel Dörfler 900a10cf76eSAxel Dörfler 901a10cf76eSAxel Dörfler void 902a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 903a10cf76eSAxel Dörfler { 904c491b5adSJohn Scipione if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) { 905c491b5adSJohn Scipione _UpdateActiveMode(workspace); 906a10cf76eSAxel Dörfler 9076edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 9086edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 909a10cf76eSAxel Dörfler } 910c491b5adSJohn Scipione } 911a10cf76eSAxel Dörfler 912a10cf76eSAxel Dörfler 913a10cf76eSAxel Dörfler void 914a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 915a10cf76eSAxel Dörfler { 916a10cf76eSAxel Dörfler switch (message->what) { 917a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 9185de171daSAxel Dörfler _CheckApplyEnabled(); 919a10cf76eSAxel Dörfler break; 920a10cf76eSAxel Dörfler 921b21d610eSAxel Dörfler case kMsgWorkspaceLayoutChanged: 922a10cf76eSAxel Dörfler { 923b21d610eSAxel Dörfler int32 deltaX = 0; 924b21d610eSAxel Dörfler int32 deltaY = 0; 925b21d610eSAxel Dörfler message->FindInt32("delta_x", &deltaX); 926b21d610eSAxel Dörfler message->FindInt32("delta_y", &deltaY); 927b21d610eSAxel Dörfler 928b21d610eSAxel Dörfler if (deltaX == 0 && deltaY == 0) 929b21d610eSAxel Dörfler break; 930b21d610eSAxel Dörfler 931b21d610eSAxel Dörfler uint32 newColumns; 932b21d610eSAxel Dörfler uint32 newRows; 933b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&newColumns, &newRows); 934b21d610eSAxel Dörfler 935b21d610eSAxel Dörfler newColumns += deltaX; 936b21d610eSAxel Dörfler newRows += deltaY; 937b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, newRows); 938b21d610eSAxel Dörfler 939b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 9405de171daSAxel Dörfler _CheckApplyEnabled(); 941b21d610eSAxel Dörfler break; 942abc649b8SWaldemar Kornewald } 943b21d610eSAxel Dörfler 944b21d610eSAxel Dörfler case kMsgWorkspaceColumnsChanged: 945b21d610eSAxel Dörfler { 946b21d610eSAxel Dörfler uint32 newColumns = strtoul(fColumnsControl->Text(), NULL, 10); 947b21d610eSAxel Dörfler 948b21d610eSAxel Dörfler uint32 rows; 949b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(NULL, &rows); 950b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, rows); 951b21d610eSAxel Dörfler 952b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 953b21d610eSAxel Dörfler _CheckApplyEnabled(); 954b21d610eSAxel Dörfler break; 955b21d610eSAxel Dörfler } 956b21d610eSAxel Dörfler 957b21d610eSAxel Dörfler case kMsgWorkspaceRowsChanged: 958b21d610eSAxel Dörfler { 959b21d610eSAxel Dörfler uint32 newRows = strtoul(fRowsControl->Text(), NULL, 10); 960b21d610eSAxel Dörfler 961b21d610eSAxel Dörfler uint32 columns; 962b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, NULL); 963b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(columns, newRows); 964b21d610eSAxel Dörfler 965b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 966b21d610eSAxel Dörfler _CheckApplyEnabled(); 967a10cf76eSAxel Dörfler break; 968a10cf76eSAxel Dörfler } 969a10cf76eSAxel Dörfler 970a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 971a10cf76eSAxel Dörfler { 972a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 973a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 974a10cf76eSAxel Dörfler 9755de171daSAxel Dörfler _CheckColorMenu(); 9765de171daSAxel Dörfler _CheckRefreshMenu(); 977a10cf76eSAxel Dörfler 9785de171daSAxel Dörfler _UpdateMonitorView(); 9795de171daSAxel Dörfler _UpdateRefreshControl(); 980a10cf76eSAxel Dörfler 9815de171daSAxel Dörfler _CheckApplyEnabled(); 982a10cf76eSAxel Dörfler break; 983a10cf76eSAxel Dörfler } 984a10cf76eSAxel Dörfler 985a10cf76eSAxel Dörfler case POP_COLORS_MSG: 986a10cf76eSAxel Dörfler { 9871fc4cb1fSAxel Dörfler int32 space; 9881fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) != B_OK) 9891fc4cb1fSAxel Dörfler break; 990a10cf76eSAxel Dörfler 9911fc4cb1fSAxel Dörfler int32 index; 9921fc4cb1fSAxel Dörfler if (message->FindInt32("index", &index) == B_OK 9931fc4cb1fSAxel Dörfler && fColorsMenu->ItemAt(index) != NULL) 9941fc4cb1fSAxel Dörfler fUserSelectedColorSpace = fColorsMenu->ItemAt(index); 9951fc4cb1fSAxel Dörfler 9961fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 9971fc4cb1fSAxel Dörfler _UpdateColorLabel(); 998a10cf76eSAxel Dörfler 9995de171daSAxel Dörfler _CheckApplyEnabled(); 1000a10cf76eSAxel Dörfler break; 1001a10cf76eSAxel Dörfler } 1002a10cf76eSAxel Dörfler 1003a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 1004a40498e2SWaldemar Kornewald { 1005a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1006c9e8f97aSAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 10071fc4cb1fSAxel Dörfler // revert "Other…" label - it might have a refresh rate prefix 1008a10cf76eSAxel Dörfler 10095de171daSAxel Dörfler _CheckApplyEnabled(); 1010a10cf76eSAxel Dörfler break; 1011a40498e2SWaldemar Kornewald } 1012a10cf76eSAxel Dörfler 1013a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 1014a10cf76eSAxel Dörfler { 101529e8a73aSAxel Dörfler // make sure menu shows something useful 10165de171daSAxel Dörfler _UpdateRefreshControl(); 1017a10cf76eSAxel Dörfler 101829e8a73aSAxel Dörfler float min = 0, max = 999; 101929e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 102029e8a73aSAxel Dörfler if (min < gMinRefresh) 102129e8a73aSAxel Dörfler min = gMinRefresh; 102229e8a73aSAxel Dörfler if (max > gMaxRefresh) 102329e8a73aSAxel Dörfler max = gMaxRefresh; 102429e8a73aSAxel Dörfler 102570a2b1b5SAxel Dörfler monitor_info info; 102670a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 102770a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 102870a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 102970a2b1b5SAxel Dörfler } 103070a2b1b5SAxel Dörfler 1031c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 103270a2b1b5SAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, 103370a2b1b5SAxel Dörfler min, max); 1034a10cf76eSAxel Dörfler fRefreshWindow->Show(); 1035a10cf76eSAxel Dörfler break; 1036a10cf76eSAxel Dörfler } 1037a10cf76eSAxel Dörfler 1038a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 1039a10cf76eSAxel Dörfler { 1040a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 1041a10cf76eSAxel Dörfler // select the refresh rate chosen 1042a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1043a10cf76eSAxel Dörfler 10445de171daSAxel Dörfler _UpdateRefreshControl(); 10455de171daSAxel Dörfler _CheckApplyEnabled(); 1046a10cf76eSAxel Dörfler break; 1047a10cf76eSAxel Dörfler } 1048a10cf76eSAxel Dörfler 1049a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 1050a10cf76eSAxel Dörfler { 1051a10cf76eSAxel Dörfler // new combine mode has bee chosen 1052a10cf76eSAxel Dörfler int32 mode; 1053a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 1054a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 1055a10cf76eSAxel Dörfler 10565de171daSAxel Dörfler _CheckResolutionMenu(); 10575de171daSAxel Dörfler _CheckApplyEnabled(); 1058a10cf76eSAxel Dörfler break; 1059a10cf76eSAxel Dörfler } 1060a10cf76eSAxel Dörfler 1061a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 1062a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 10635de171daSAxel Dörfler _CheckApplyEnabled(); 1064a10cf76eSAxel Dörfler break; 1065a10cf76eSAxel Dörfler 1066a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 1067a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 10685de171daSAxel Dörfler _CheckApplyEnabled(); 1069a10cf76eSAxel Dörfler break; 1070a10cf76eSAxel Dörfler 1071a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 1072a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 10735de171daSAxel Dörfler _CheckApplyEnabled(); 1074a10cf76eSAxel Dörfler break; 1075a10cf76eSAxel Dörfler 1076df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 10776f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 10786f095d6aSRyan Leavengood app_info info; 10796f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 10806f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 10816f095d6aSRyan Leavengood } 1082df3f5bacSStephan Aßmus break; 1083df3f5bacSStephan Aßmus 1084a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 1085a10cf76eSAxel Dörfler { 10864be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 1087a10cf76eSAxel Dörfler fSelected.width = 640; 1088a10cf76eSAxel Dörfler fSelected.height = 480; 1089a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 1090a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 1091a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 1092a10cf76eSAxel Dörfler fSelected.swap_displays = false; 1093a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 1094a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 1095a10cf76eSAxel Dörfler 1096b21d610eSAxel Dörfler // TODO: workspace defaults 1097abc649b8SWaldemar Kornewald 10985de171daSAxel Dörfler _UpdateControls(); 1099a10cf76eSAxel Dörfler break; 1100a10cf76eSAxel Dörfler } 1101a10cf76eSAxel Dörfler 110210e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 110361c5c89bSAxel Dörfler fUndoScreenMode.Revert(); 11045de171daSAxel Dörfler _UpdateActiveMode(); 1105abc649b8SWaldemar Kornewald break; 1106abc649b8SWaldemar Kornewald 1107abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 1108abc649b8SWaldemar Kornewald { 1109abc649b8SWaldemar Kornewald fModified = false; 1110199893c3SAxel Dörfler fBootWorkspaceApplied = false; 1111abc649b8SWaldemar Kornewald 1112b21d610eSAxel Dörfler // ScreenMode::Revert() assumes that we first set the correct 1113b21d610eSAxel Dörfler // number of workspaces 1114b21d610eSAxel Dörfler 1115b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns, 1116b21d610eSAxel Dörfler fOriginalWorkspacesRows); 1117b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 1118b21d610eSAxel Dörfler 1119a10cf76eSAxel Dörfler fScreenMode.Revert(); 11205de171daSAxel Dörfler _UpdateActiveMode(); 1121a10cf76eSAxel Dörfler break; 1122abc649b8SWaldemar Kornewald } 1123a10cf76eSAxel Dörfler 1124a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 11255de171daSAxel Dörfler _Apply(); 1126a10cf76eSAxel Dörfler break; 1127a10cf76eSAxel Dörfler 1128abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 1129abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 1130abc649b8SWaldemar Kornewald fModified = true; 11315de171daSAxel Dörfler _UpdateActiveMode(); 1132a10cf76eSAxel Dörfler break; 1133a10cf76eSAxel Dörfler 1134a10cf76eSAxel Dörfler default: 1135a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 1136a10cf76eSAxel Dörfler break; 1137a10cf76eSAxel Dörfler } 1138a10cf76eSAxel Dörfler } 1139a10cf76eSAxel Dörfler 1140a10cf76eSAxel Dörfler 114112580984SAxel Dörfler status_t 114212580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 114312580984SAxel Dörfler { 114412580984SAxel Dörfler BPath path; 114512580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 114612580984SAxel Dörfler if (status < B_OK) 114712580984SAxel Dörfler return status; 114812580984SAxel Dörfler 114912580984SAxel Dörfler path.Append("kernel/drivers"); 115012580984SAxel Dörfler status = create_directory(path.Path(), 0755); 115112580984SAxel Dörfler if (status < B_OK) 115212580984SAxel Dörfler return status; 115312580984SAxel Dörfler 115412580984SAxel Dörfler path.Append("vesa"); 115512580984SAxel Dörfler BFile file; 115612580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 115712580984SAxel Dörfler if (status < B_OK) 115812580984SAxel Dörfler return status; 115912580984SAxel Dörfler 116012580984SAxel Dörfler char buffer[256]; 11615084d0d4SAlex Smith snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %" 11625084d0d4SAlex Smith B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel()); 116312580984SAxel Dörfler 116412580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 116512580984SAxel Dörfler if (bytesWritten < B_OK) 116612580984SAxel Dörfler return bytesWritten; 116712580984SAxel Dörfler 116812580984SAxel Dörfler return B_OK; 116912580984SAxel Dörfler } 117012580984SAxel Dörfler 117112580984SAxel Dörfler 1172b21d610eSAxel Dörfler BButton* 1173b21d610eSAxel Dörfler ScreenWindow::_CreateColumnRowButton(bool columns, bool plus) 1174b21d610eSAxel Dörfler { 1175b21d610eSAxel Dörfler BMessage* message = new BMessage(kMsgWorkspaceLayoutChanged); 1176b21d610eSAxel Dörfler message->AddInt32("delta_x", columns ? (plus ? 1 : -1) : 0); 1177b21d610eSAxel Dörfler message->AddInt32("delta_y", !columns ? (plus ? 1 : -1) : 0); 1178b21d610eSAxel Dörfler 1179a2bf375cSJohn Scipione BButton* button = new BButton(plus ? "+" : "\xe2\x88\x92", message); 1180b21d610eSAxel Dörfler button->SetFontSize(be_plain_font->Size() * 0.9); 1181b21d610eSAxel Dörfler 1182b21d610eSAxel Dörfler BSize size = button->MinSize(); 1183b21d610eSAxel Dörfler size.width = button->StringWidth("+") + 16; 1184b21d610eSAxel Dörfler button->SetExplicitMinSize(size); 1185b21d610eSAxel Dörfler button->SetExplicitMaxSize(size); 1186b21d610eSAxel Dörfler 1187b21d610eSAxel Dörfler fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)] = button; 1188b21d610eSAxel Dörfler return button; 1189b21d610eSAxel Dörfler } 1190b21d610eSAxel Dörfler 1191b21d610eSAxel Dörfler 1192b21d610eSAxel Dörfler BButton* 1193b21d610eSAxel Dörfler ScreenWindow::_GetColumnRowButton(bool columns, bool plus) 1194b21d610eSAxel Dörfler { 1195b21d610eSAxel Dörfler return fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)]; 1196b21d610eSAxel Dörfler } 1197b21d610eSAxel Dörfler 1198b21d610eSAxel Dörfler 1199a10cf76eSAxel Dörfler void 12001fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces() 12011fc4cb1fSAxel Dörfler { 12021fc4cb1fSAxel Dörfler fSupportedColorSpaces = 0; 12031fc4cb1fSAxel Dörfler 12041fc4cb1fSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 12051fc4cb1fSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 12061fc4cb1fSAxel Dörfler if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) { 12071fc4cb1fSAxel Dörfler fSupportedColorSpaces |= 1 << i; 12081fc4cb1fSAxel Dörfler break; 12091fc4cb1fSAxel Dörfler } 12101fc4cb1fSAxel Dörfler } 12111fc4cb1fSAxel Dörfler } 12121fc4cb1fSAxel Dörfler } 12131fc4cb1fSAxel Dörfler 12141fc4cb1fSAxel Dörfler 12151fc4cb1fSAxel Dörfler void 12165de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1217a10cf76eSAxel Dörfler { 121827c43a2dSRene Gollent fApplyButton->SetEnabled(fSelected != fActive 121927c43a2dSRene Gollent || fAllWorkspacesItem->IsMarked()); 1220b21d610eSAxel Dörfler 1221b21d610eSAxel Dörfler uint32 columns; 1222b21d610eSAxel Dörfler uint32 rows; 1223b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 1224b21d610eSAxel Dörfler 1225b21d610eSAxel Dörfler fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns 1226b21d610eSAxel Dörfler || rows != fOriginalWorkspacesRows 12275de171daSAxel Dörfler || fSelected != fOriginal); 1228a10cf76eSAxel Dörfler } 1229a10cf76eSAxel Dörfler 1230a10cf76eSAxel Dörfler 1231a10cf76eSAxel Dörfler void 12325de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1233abc649b8SWaldemar Kornewald { 1234b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns, 1235b21d610eSAxel Dörfler &fOriginalWorkspacesRows); 1236b21d610eSAxel Dörfler 1237abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1238abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1239abc649b8SWaldemar Kornewald } 1240abc649b8SWaldemar Kornewald 1241abc649b8SWaldemar Kornewald 1242abc649b8SWaldemar Kornewald void 124312966d04SAxel Dörfler ScreenWindow::_UpdateMonitor() 124412966d04SAxel Dörfler { 124512966d04SAxel Dörfler monitor_info info; 124612966d04SAxel Dörfler float diagonalInches; 124712966d04SAxel Dörfler status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches); 124855030977SAxel Dörfler if (status == B_OK) { 12491a8af605SAxel Dörfler char text[512]; 125066ab1666SAxel Dörfler snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor, 125166ab1666SAxel Dörfler info.name[0] ? " " : "", info.name, diagonalInches); 125212966d04SAxel Dörfler 125312966d04SAxel Dörfler fMonitorInfo->SetText(text); 125412966d04SAxel Dörfler 125512966d04SAxel Dörfler if (fMonitorInfo->IsHidden()) 125612966d04SAxel Dörfler fMonitorInfo->Show(); 125755030977SAxel Dörfler } else { 125855030977SAxel Dörfler if (!fMonitorInfo->IsHidden()) 125955030977SAxel Dörfler fMonitorInfo->Hide(); 126055030977SAxel Dörfler } 1261af8f9c31SAxel Dörfler 1262*8b46ee25SAdrien Destugues // Add info about the graphics device 1263*8b46ee25SAdrien Destugues 1264*8b46ee25SAdrien Destugues accelerant_device_info deviceInfo; 1265*8b46ee25SAdrien Destugues 1266*8b46ee25SAdrien Destugues if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK) { 1267*8b46ee25SAdrien Destugues BString deviceString; 1268*8b46ee25SAdrien Destugues 1269*8b46ee25SAdrien Destugues if (deviceInfo.name[0] && deviceInfo.chipset[0]) { 1270*8b46ee25SAdrien Destugues deviceString.SetToFormat("%s (%s)", deviceInfo.name, 1271*8b46ee25SAdrien Destugues deviceInfo.chipset); 1272*8b46ee25SAdrien Destugues } else if (deviceInfo.name[0] || deviceInfo.chipset[0]) { 1273*8b46ee25SAdrien Destugues deviceString 1274*8b46ee25SAdrien Destugues = deviceInfo.name[0] ? deviceInfo.name : deviceInfo.chipset; 1275*8b46ee25SAdrien Destugues } 1276*8b46ee25SAdrien Destugues 1277*8b46ee25SAdrien Destugues fDeviceInfo->SetText(deviceString); 1278*8b46ee25SAdrien Destugues } 1279*8b46ee25SAdrien Destugues 1280*8b46ee25SAdrien Destugues 128155030977SAxel Dörfler char text[512]; 12821a8af605SAxel Dörfler size_t length = 0; 12831a8af605SAxel Dörfler text[0] = 0; 12841a8af605SAxel Dörfler 128555030977SAxel Dörfler if (status == B_OK) { 1286af8f9c31SAxel Dörfler if (info.min_horizontal_frequency != 0 1287af8f9c31SAxel Dörfler && info.min_vertical_frequency != 0 1288af8f9c31SAxel Dörfler && info.max_pixel_clock != 0) { 12891a8af605SAxel Dörfler length = snprintf(text, sizeof(text), 1290c9e8f97aSAdrien Destugues B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n" 12919c1a9b92SAdrien Destugues "Vertical frequency:\t%lu - %lu Hz\n\n" 1292c9e8f97aSAdrien Destugues "Maximum pixel clock:\t%g MHz"), 12931a8af605SAxel Dörfler info.min_horizontal_frequency, info.max_horizontal_frequency, 12941a8af605SAxel Dörfler info.min_vertical_frequency, info.max_vertical_frequency, 12951a8af605SAxel Dörfler info.max_pixel_clock / 1000.0); 1296af8f9c31SAxel Dörfler } 12971a8af605SAxel Dörfler if (info.serial_number[0] && length < sizeof(text)) { 12981a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 1299c9e8f97aSAdrien Destugues B_TRANSLATE("%sSerial no.: %s"), length ? "\n\n" : "", 13001a8af605SAxel Dörfler info.serial_number); 13011a8af605SAxel Dörfler if (info.produced.week != 0 && info.produced.year != 0 13021a8af605SAxel Dörfler && length < sizeof(text)) { 13031a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 13041a8af605SAxel Dörfler " (%u/%u)", info.produced.week, info.produced.year); 13051a8af605SAxel Dörfler } 13061a8af605SAxel Dörfler } 130755030977SAxel Dörfler } 130861c5c89bSAxel Dörfler 13091a8af605SAxel Dörfler if (text[0]) 13101a8af605SAxel Dörfler fMonitorView->SetToolTip(text); 131112966d04SAxel Dörfler } 131212966d04SAxel Dörfler 131312966d04SAxel Dörfler 131412966d04SAxel Dörfler void 13151fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel() 13161fc4cb1fSAxel Dörfler { 13171fc4cb1fSAxel Dörfler BString string; 1318551c9f15SSiarzhuk Zharski string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel"); 13191fc4cb1fSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 13201fc4cb1fSAxel Dörfler } 13211fc4cb1fSAxel Dörfler 13221fc4cb1fSAxel Dörfler 13231fc4cb1fSAxel Dörfler void 13245de171daSAxel Dörfler ScreenWindow::_Apply() 1325a10cf76eSAxel Dörfler { 1326abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 132761c5c89bSAxel Dörfler fUndoScreenMode.UpdateOriginalModes(); 132861c5c89bSAxel Dörfler 132907184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 133007184a9eSAxel Dörfler if (status == B_OK) { 1331abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1332abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1333abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1334abc649b8SWaldemar Kornewald display_mode newMode; 1335abc649b8SWaldemar Kornewald BScreen screen(this); 1336abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1337abc649b8SWaldemar Kornewald 1338abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1339abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 1340abc649b8SWaldemar Kornewald for (int32 i = 0; i < count_workspaces(); i++) { 1341abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1342abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1343abc649b8SWaldemar Kornewald } 1344199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1345199893c3SAxel Dörfler } else { 1346199893c3SAxel Dörfler if (current_workspace() == 0) 1347199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1348abc649b8SWaldemar Kornewald } 1349abc649b8SWaldemar Kornewald 1350a10cf76eSAxel Dörfler fActive = fSelected; 1351a10cf76eSAxel Dörfler 1352abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 1353a10cf76eSAxel Dörfler BWindow* window = new AlertWindow(this); 1354a10cf76eSAxel Dörfler window->Show(); 135507184a9eSAxel Dörfler } else { 135607184a9eSAxel Dörfler char message[256]; 135707184a9eSAxel Dörfler snprintf(message, sizeof(message), 1358c9e8f97aSAdrien Destugues B_TRANSLATE("The screen mode could not be set:\n\t%s\n"), 1359c9e8f97aSAdrien Destugues screen_errors(status)); 1360551c9f15SSiarzhuk Zharski BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message, 1361c9e8f97aSAdrien Destugues B_TRANSLATE("OK"), NULL, NULL, 136207184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 1363aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 136407184a9eSAxel Dörfler alert->Go(); 1365a10cf76eSAxel Dörfler } 136607184a9eSAxel Dörfler } 1367