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> 22b21d610eSAxel Dörfler #include <string.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 224c9e8f97aSAdrien Destugues fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), 225551c9f15SSiarzhuk Zharski "monitor", screen.Frame().IntegerWidth() + 1, 226c9e8f97aSAdrien Destugues screen.Frame().IntegerHeight() + 1); 227b21d610eSAxel Dörfler screenBox->AddChild(fMonitorView); 2285a78744bSAxel Dörfler 229e1c88201SJohn Scipione BStringView* workspaces = new BStringView("workspaces", 230e1c88201SJohn Scipione B_TRANSLATE("Workspaces")); 231e1c88201SJohn Scipione workspaces->SetAlignment(B_ALIGN_CENTER); 232e1c88201SJohn Scipione 233c9e8f97aSAdrien Destugues fColumnsControl = new BTextControl(B_TRANSLATE("Columns:"), "0", 234b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceColumnsChanged)); 235e1c88201SJohn Scipione fColumnsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 236c9e8f97aSAdrien Destugues fRowsControl = new BTextControl(B_TRANSLATE("Rows:"), "0", 237b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceRowsChanged)); 238e1c88201SJohn Scipione fRowsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 239b21d610eSAxel Dörfler 240e1c88201SJohn Scipione float tiny = be_control_look->DefaultItemSpacing() / 4; 241e1c88201SJohn Scipione screenBox->AddChild(BLayoutBuilder::Group<>() 242e1c88201SJohn Scipione .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING) 243e1c88201SJohn Scipione .Add(workspaces) 244e1c88201SJohn Scipione .AddGrid(0.0, tiny) 245e1c88201SJohn Scipione // columns 246e1c88201SJohn Scipione .Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0) 247e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut( 248e1c88201SJohn Scipione B_USE_SMALL_SPACING), 1, 0) 249e1c88201SJohn Scipione .Add(fColumnsControl->CreateTextViewLayoutItem(), 2, 0) 250e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 0) 251e1c88201SJohn Scipione .Add(_CreateColumnRowButton(true, false), 4, 0) 252e1c88201SJohn Scipione .Add(_CreateColumnRowButton(true, true), 5, 0) 253e1c88201SJohn Scipione // rows 254e1c88201SJohn Scipione .Add(fRowsControl->CreateLabelLayoutItem(), 0, 1) 255e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut( 256e1c88201SJohn Scipione B_USE_SMALL_SPACING), 1, 1) 257e1c88201SJohn Scipione .Add(fRowsControl->CreateTextViewLayoutItem(), 2, 1) 258e1c88201SJohn Scipione .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 1) 259e1c88201SJohn Scipione .Add(_CreateColumnRowButton(false, false), 4, 1) 260e1c88201SJohn Scipione .Add(_CreateColumnRowButton(false, true), 5, 1) 261b21d610eSAxel Dörfler .End() 26225fd5c7bSAlex Wilson .End() 26325fd5c7bSAlex Wilson .View()); 264b21d610eSAxel Dörfler 265b21d610eSAxel Dörfler fBackgroundsButton = new BButton("BackgroundsButton", 266c9e8f97aSAdrien Destugues B_TRANSLATE("Set background" B_UTF8_ELLIPSIS), 267b21d610eSAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 268b21d610eSAxel Dörfler fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 269b21d610eSAxel Dörfler screenBox->AddChild(fBackgroundsButton); 270a10cf76eSAxel Dörfler 271a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 272a10cf76eSAxel Dörfler 273b21d610eSAxel Dörfler BBox* controlsBox = new BBox("controls box"); 274b21d610eSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 275*6048f541SJohn Scipione BGroupView* outerControlsView = new BGroupView(B_VERTICAL); 276*6048f541SJohn Scipione outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING, 277*6048f541SJohn Scipione B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING); 278b21d610eSAxel Dörfler controlsBox->AddChild(outerControlsView); 279a10cf76eSAxel Dörfler 280551c9f15SSiarzhuk Zharski fResolutionMenu = new BPopUpMenu("resolution", true, true); 281a10cf76eSAxel Dörfler 28266ab1666SAxel Dörfler uint16 maxWidth = 0; 28366ab1666SAxel Dörfler uint16 maxHeight = 0; 28466ab1666SAxel Dörfler uint16 previousWidth = 0; 28566ab1666SAxel Dörfler uint16 previousHeight = 0; 286a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 287a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 288a10cf76eSAxel Dörfler 289a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 290a10cf76eSAxel Dörfler continue; 291a10cf76eSAxel Dörfler 292a10cf76eSAxel Dörfler previousWidth = mode.width; 293a10cf76eSAxel Dörfler previousHeight = mode.height; 29466ab1666SAxel Dörfler if (maxWidth < mode.width) 29566ab1666SAxel Dörfler maxWidth = mode.width; 29666ab1666SAxel Dörfler if (maxHeight < mode.height) 29766ab1666SAxel Dörfler maxHeight = mode.height; 298a10cf76eSAxel Dörfler 299a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_RESOLUTION_MSG); 300a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 301a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 302a10cf76eSAxel Dörfler 303a10cf76eSAxel Dörfler BString name; 304a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 305a10cf76eSAxel Dörfler 306a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 307a10cf76eSAxel Dörfler } 308a10cf76eSAxel Dörfler 30966ab1666SAxel Dörfler fMonitorView->SetMaxResolution(maxWidth, maxHeight); 31066ab1666SAxel Dörfler 311c9e8f97aSAdrien Destugues fResolutionField = new BMenuField("ResolutionMenu", 31210dfe897SAxel Dörfler B_TRANSLATE("Resolution:"), fResolutionMenu); 313*6048f541SJohn Scipione fResolutionField->SetAlignment(B_ALIGN_RIGHT); 314a10cf76eSAxel Dörfler 315551c9f15SSiarzhuk Zharski fColorsMenu = new BPopUpMenu("colors", true, false); 316a10cf76eSAxel Dörfler 317a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 3181fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 3191fc4cb1fSAxel Dörfler continue; 3201fc4cb1fSAxel Dörfler 321a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_COLORS_MSG); 322a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 323a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 324a10cf76eSAxel Dörfler 3251fc4cb1fSAxel Dörfler BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); 3261fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == screen.ColorSpace()) 3271fc4cb1fSAxel Dörfler fUserSelectedColorSpace = item; 3281fc4cb1fSAxel Dörfler 3291fc4cb1fSAxel Dörfler fColorsMenu->AddItem(item); 330a10cf76eSAxel Dörfler } 331a10cf76eSAxel Dörfler 332c9e8f97aSAdrien Destugues fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"), 33310dfe897SAxel Dörfler fColorsMenu); 334*6048f541SJohn Scipione fColorsField->SetAlignment(B_ALIGN_RIGHT); 335a10cf76eSAxel Dörfler 336551c9f15SSiarzhuk Zharski fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 337a10cf76eSAxel Dörfler 33829e8a73aSAxel Dörfler float min, max; 339ec495b30SRene Gollent if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) { 340ec495b30SRene Gollent // if we couldn't obtain the refresh limits, reset to the default 341ec495b30SRene Gollent // range. Constraints from detected monitors will fine-tune this 342ec495b30SRene Gollent // later. 343ec495b30SRene Gollent min = kRefreshRates[0]; 344ec495b30SRene Gollent max = kRefreshRates[kRefreshRateCount - 1]; 345ec495b30SRene Gollent } 346ec495b30SRene Gollent 347ec495b30SRene Gollent if (min == max) { 34829e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 34929e8a73aSAxel Dörfler // frequency, like the VESA driver 35029e8a73aSAxel Dörfler BString name; 3517e44de36SRene Gollent refresh_rate_to_string(min, name); 352cf076964SRene Gollent BMessage *message = new BMessage(POP_REFRESH_MSG); 353cf076964SRene Gollent message->AddFloat("refresh", min); 354cf076964SRene Gollent BMenuItem *item = new BMenuItem(name.String(), message); 3550efb8b66SJerome Duval fRefreshMenu->AddItem(item); 35629e8a73aSAxel Dörfler item->SetEnabled(false); 35729e8a73aSAxel Dörfler } else { 35870a2b1b5SAxel Dörfler monitor_info info; 35970a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 36070a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 36170a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 36270a2b1b5SAxel Dörfler } 36370a2b1b5SAxel Dörfler 364a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 36570a2b1b5SAxel Dörfler if (kRefreshRates[i] < min || kRefreshRates[i] > max) 36670a2b1b5SAxel Dörfler continue; 36770a2b1b5SAxel Dörfler 368a10cf76eSAxel Dörfler BString name; 369551c9f15SSiarzhuk Zharski name << kRefreshRates[i] << " " << B_TRANSLATE("Hz"); 370a10cf76eSAxel Dörfler 3710efb8b66SJerome Duval BMessage *message = new BMessage(POP_REFRESH_MSG); 372a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 373a10cf76eSAxel Dörfler 374a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 375a10cf76eSAxel Dörfler } 376a10cf76eSAxel Dörfler 377c9e8f97aSAdrien Destugues fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), 3780efb8b66SJerome Duval new BMessage(POP_OTHER_REFRESH_MSG)); 379a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 38029e8a73aSAxel Dörfler } 381a10cf76eSAxel Dörfler 382c9e8f97aSAdrien Destugues fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"), 38310dfe897SAxel Dörfler fRefreshMenu); 384*6048f541SJohn Scipione fRefreshField->SetAlignment(B_ALIGN_RIGHT); 385b21d610eSAxel Dörfler 38612580984SAxel Dörfler if (_IsVesa()) 38712580984SAxel Dörfler fRefreshField->Hide(); 388a10cf76eSAxel Dörfler 389a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 390a10cf76eSAxel Dörfler { 391a10cf76eSAxel Dörfler bool dummy; 392a10cf76eSAxel Dörfler uint32 dummy32; 393a10cf76eSAxel Dörfler bool multiMonSupport; 394a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 395a10cf76eSAxel Dörfler bool tvStandardSupport; 396a10cf76eSAxel Dörfler 397a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 398a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 399a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 400a10cf76eSAxel Dörfler 401a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 402a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 403a10cf76eSAxel Dörfler 404551c9f15SSiarzhuk Zharski fCombineMenu = new BPopUpMenu("CombineDisplays", 405c9e8f97aSAdrien Destugues true, true); 406a10cf76eSAxel Dörfler 407a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 4080efb8b66SJerome Duval BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 409a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 410a10cf76eSAxel Dörfler 411d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 412d1516993SAxel Dörfler message)); 413a10cf76eSAxel Dörfler } 414a10cf76eSAxel Dörfler 415b21d610eSAxel Dörfler fCombineField = new BMenuField("CombineMenu", 41610dfe897SAxel Dörfler B_TRANSLATE("Combine displays:"), fCombineMenu); 417*6048f541SJohn Scipione fCombineField->SetAlignment(B_ALIGN_RIGHT); 418a10cf76eSAxel Dörfler 419a10cf76eSAxel Dörfler if (!multiMonSupport) 420df3f5bacSStephan Aßmus fCombineField->Hide(); 421a10cf76eSAxel Dörfler 422551c9f15SSiarzhuk Zharski fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", 423c9e8f97aSAdrien Destugues true, true); 424a10cf76eSAxel Dörfler 425a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 4260efb8b66SJerome Duval BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG); 427a10cf76eSAxel Dörfler message->AddBool("swap", false); 428c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message)); 429a10cf76eSAxel Dörfler 430a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 431a10cf76eSAxel Dörfler message->AddBool("swap", true); 432c9e8f97aSAdrien Destugues fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message)); 433a10cf76eSAxel Dörfler 434c9e8f97aSAdrien Destugues fSwapDisplaysField = new BMenuField("SwapMenu", 43510dfe897SAxel Dörfler B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu); 436*6048f541SJohn Scipione fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT); 437a10cf76eSAxel Dörfler 438a10cf76eSAxel Dörfler if (!multiMonSupport) 439df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 440a10cf76eSAxel Dörfler 441551c9f15SSiarzhuk Zharski fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", 442c9e8f97aSAdrien Destugues true, true); 443a10cf76eSAxel Dörfler 444a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 445a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 446a10cf76eSAxel Dörfler message->AddBool("use", false); 447c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"), 448c9e8f97aSAdrien Destugues message)); 449a10cf76eSAxel Dörfler 450a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 451a10cf76eSAxel Dörfler message->AddBool("use", true); 452c9e8f97aSAdrien Destugues fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"), 453c9e8f97aSAdrien Destugues message)); 454a10cf76eSAxel Dörfler 455b21d610eSAxel Dörfler fUseLaptopPanelField = new BMenuField("UseLaptopPanel", 45610dfe897SAxel Dörfler B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu); 457*6048f541SJohn Scipione fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT); 458a10cf76eSAxel Dörfler 459a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 460df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 461a10cf76eSAxel Dörfler 462551c9f15SSiarzhuk Zharski fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 463a10cf76eSAxel Dörfler 464a10cf76eSAxel Dörfler // arbitrary limit 465a10cf76eSAxel Dörfler uint32 i; 466a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 467a10cf76eSAxel Dörfler uint32 mode; 468a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 469a10cf76eSAxel Dörfler break; 470a10cf76eSAxel Dörfler 471a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 472a10cf76eSAxel Dörfler 473a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 474a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 475a10cf76eSAxel Dörfler 476a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 477a10cf76eSAxel Dörfler } 478a10cf76eSAxel Dörfler 479c9e8f97aSAdrien Destugues fTVStandardField = new BMenuField("tv standard", 48010dfe897SAxel Dörfler B_TRANSLATE("Video format:"), fTVStandardMenu); 481df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 482a10cf76eSAxel Dörfler 483b21d610eSAxel Dörfler if (!tvStandardSupport || i == 0) 484df3f5bacSStephan Aßmus fTVStandardField->Hide(); 485a10cf76eSAxel Dörfler } 486a10cf76eSAxel Dörfler 48725fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 488*6048f541SJohn Scipione .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 489*6048f541SJohn Scipione .Add(fResolutionField->CreateLabelLayoutItem(), 0, 0) 490*6048f541SJohn Scipione .Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0) 491*6048f541SJohn Scipione .Add(fColorsField->CreateLabelLayoutItem(), 0, 1) 492*6048f541SJohn Scipione .Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1) 493*6048f541SJohn Scipione .Add(fRefreshField->CreateLabelLayoutItem(), 0, 2) 494*6048f541SJohn Scipione .Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2) 495*6048f541SJohn Scipione .Add(fCombineField->CreateLabelLayoutItem(), 0, 3) 496*6048f541SJohn Scipione .Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3) 497*6048f541SJohn Scipione .Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4) 498*6048f541SJohn Scipione .Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4) 499*6048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5) 500*6048f541SJohn Scipione .Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5) 501*6048f541SJohn Scipione .Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6) 502*6048f541SJohn Scipione .Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6) 50325fd5c7bSAlex Wilson .End(); 504df3f5bacSStephan Aßmus 505abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 506abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 507b21d610eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG));*/ 508a10cf76eSAxel Dörfler 509c9e8f97aSAdrien Destugues fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"), 510df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 511df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 51225fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 513b21d610eSAxel Dörfler .AddGlue() 51425fd5c7bSAlex Wilson .AddGroup(B_HORIZONTAL) 51525fd5c7bSAlex Wilson .AddGlue() 51625fd5c7bSAlex Wilson .Add(fApplyButton); 517b21d610eSAxel Dörfler 518c9e8f97aSAdrien Destugues fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"), 519b21d610eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 520b21d610eSAxel Dörfler fRevertButton->SetEnabled(false); 521b21d610eSAxel Dörfler 5224666484fSJohn Scipione BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) 5234666484fSJohn Scipione .AddGroup(B_HORIZONTAL) 52483cc66b3SJohn Scipione .AddGroup(B_VERTICAL, 0) 52583cc66b3SJohn Scipione .AddStrut(floorf(controlsBox->TopBorderOffset()) - 1) 526b21d610eSAxel Dörfler .Add(screenBox) 52783cc66b3SJohn Scipione .End() 528b21d610eSAxel Dörfler .Add(controlsBox) 529b21d610eSAxel Dörfler .End() 5304666484fSJohn Scipione .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 531b21d610eSAxel Dörfler .Add(fRevertButton) 5324666484fSJohn Scipione .AddGlue() 5334666484fSJohn Scipione .End() 5344666484fSJohn Scipione .SetInsets(B_USE_DEFAULT_SPACING); 535b21d610eSAxel Dörfler 5365de171daSAxel Dörfler _UpdateControls(); 53712966d04SAxel Dörfler _UpdateMonitor(); 538a10cf76eSAxel Dörfler } 539a10cf76eSAxel Dörfler 540a10cf76eSAxel Dörfler 541a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 542a10cf76eSAxel Dörfler { 543a10cf76eSAxel Dörfler delete fSettings; 544a10cf76eSAxel Dörfler } 545a10cf76eSAxel Dörfler 546a10cf76eSAxel Dörfler 547a10cf76eSAxel Dörfler bool 548a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 549a10cf76eSAxel Dörfler { 550a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 551199893c3SAxel Dörfler 552199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 553199893c3SAxel Dörfler screen_mode vesaMode; 554199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 555199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 55612580984SAxel Dörfler if (status < B_OK) { 557c9e8f97aSAdrien Destugues BString warning = B_TRANSLATE("Could not write VESA mode settings" 558c9e8f97aSAdrien Destugues " file:\n\t"); 55912580984SAxel Dörfler warning << strerror(status); 560aed35104SHumdinger BAlert* alert = new BAlert(B_TRANSLATE("Warning"), 561aed35104SHumdinger warning.String(), B_TRANSLATE("OK"), NULL, 562aed35104SHumdinger NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 563aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 564aed35104SHumdinger alert->Go(); 56512580984SAxel Dörfler } 56612580984SAxel Dörfler } 56712580984SAxel Dörfler 568a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 569a10cf76eSAxel Dörfler 570a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 571a10cf76eSAxel Dörfler } 572a10cf76eSAxel Dörfler 573a10cf76eSAxel Dörfler 5745de171daSAxel Dörfler /*! Update resolution list according to combine mode 5751fc4cb1fSAxel Dörfler (some resolutions may not be combinable due to memory restrictions). 576a10cf76eSAxel Dörfler */ 577a10cf76eSAxel Dörfler void 5785de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 579a10cf76eSAxel Dörfler { 580a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 581a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 582a10cf76eSAxel Dörfler 583a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 584a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 585a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 586a10cf76eSAxel Dörfler continue; 587a10cf76eSAxel Dörfler 588a10cf76eSAxel Dörfler BString name; 589a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 590a10cf76eSAxel Dörfler 591a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 592a10cf76eSAxel Dörfler if (item != NULL) 593a10cf76eSAxel Dörfler item->SetEnabled(true); 594a10cf76eSAxel Dörfler } 595a10cf76eSAxel Dörfler } 596a10cf76eSAxel Dörfler 597a10cf76eSAxel Dörfler 5985de171daSAxel Dörfler /*! Update color and refresh options according to current mode 5995de171daSAxel Dörfler (a color space is made active if there is any mode with 6005de171daSAxel Dörfler given resolution and this colour space; same applies for 6015de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 602a10cf76eSAxel Dörfler */ 603a10cf76eSAxel Dörfler void 6045de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 605a10cf76eSAxel Dörfler { 6061fc4cb1fSAxel Dörfler int32 supportsAnything = false; 6071fc4cb1fSAxel Dörfler int32 index = 0; 6081fc4cb1fSAxel Dörfler 609a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 6101fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 6111fc4cb1fSAxel Dörfler continue; 6121fc4cb1fSAxel Dörfler 613a10cf76eSAxel Dörfler bool supported = false; 614a10cf76eSAxel Dörfler 615a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 616a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 617a10cf76eSAxel Dörfler 618a10cf76eSAxel Dörfler if (fSelected.width == mode.width 619a10cf76eSAxel Dörfler && fSelected.height == mode.height 6201fc4cb1fSAxel Dörfler && kColorSpaces[i].space == mode.space 621a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 6221fc4cb1fSAxel Dörfler supportsAnything = true; 623a10cf76eSAxel Dörfler supported = true; 624a10cf76eSAxel Dörfler break; 625a10cf76eSAxel Dörfler } 626a10cf76eSAxel Dörfler } 627a10cf76eSAxel Dörfler 6281fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(index++); 629a10cf76eSAxel Dörfler if (item) 630a10cf76eSAxel Dörfler item->SetEnabled(supported); 631a10cf76eSAxel Dörfler } 6321fc4cb1fSAxel Dörfler 6331fc4cb1fSAxel Dörfler fColorsField->SetEnabled(supportsAnything); 6341fc4cb1fSAxel Dörfler 6351fc4cb1fSAxel Dörfler if (!supportsAnything) 6361fc4cb1fSAxel Dörfler return; 6371fc4cb1fSAxel Dörfler 6381fc4cb1fSAxel Dörfler // Make sure a valid item is selected 6391fc4cb1fSAxel Dörfler 6401fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->FindMarked(); 6411fc4cb1fSAxel Dörfler bool changed = false; 6421fc4cb1fSAxel Dörfler 6431fc4cb1fSAxel Dörfler if (item != fUserSelectedColorSpace) { 6441fc4cb1fSAxel Dörfler if (fUserSelectedColorSpace != NULL 6451fc4cb1fSAxel Dörfler && fUserSelectedColorSpace->IsEnabled()) { 6461fc4cb1fSAxel Dörfler fUserSelectedColorSpace->SetMarked(true); 6471fc4cb1fSAxel Dörfler item = fUserSelectedColorSpace; 6481fc4cb1fSAxel Dörfler changed = true; 6491fc4cb1fSAxel Dörfler } 6501fc4cb1fSAxel Dörfler } 6511fc4cb1fSAxel Dörfler if (item != NULL && !item->IsEnabled()) { 6521fc4cb1fSAxel Dörfler // find the next best item 6531fc4cb1fSAxel Dörfler int32 index = fColorsMenu->IndexOf(item); 6541fc4cb1fSAxel Dörfler bool found = false; 6551fc4cb1fSAxel Dörfler 6561fc4cb1fSAxel Dörfler for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) { 6571fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6581fc4cb1fSAxel Dörfler if (item->IsEnabled()) { 6591fc4cb1fSAxel Dörfler found = true; 6601fc4cb1fSAxel Dörfler break; 6611fc4cb1fSAxel Dörfler } 6621fc4cb1fSAxel Dörfler } 6631fc4cb1fSAxel Dörfler if (!found) { 6641fc4cb1fSAxel Dörfler // search backwards as well 6651fc4cb1fSAxel Dörfler for (int32 i = index - 1; i >= 0; i--) { 6661fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6671fc4cb1fSAxel Dörfler if (item->IsEnabled()) 6681fc4cb1fSAxel Dörfler break; 6691fc4cb1fSAxel Dörfler } 6701fc4cb1fSAxel Dörfler } 6711fc4cb1fSAxel Dörfler 6721fc4cb1fSAxel Dörfler item->SetMarked(true); 6731fc4cb1fSAxel Dörfler changed = true; 6741fc4cb1fSAxel Dörfler } 6751fc4cb1fSAxel Dörfler 6761fc4cb1fSAxel Dörfler if (changed) { 6771fc4cb1fSAxel Dörfler // Update selected space 6781fc4cb1fSAxel Dörfler 6791fc4cb1fSAxel Dörfler BMessage* message = item->Message(); 6801fc4cb1fSAxel Dörfler int32 space; 6811fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) == B_OK) { 6821fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 6831fc4cb1fSAxel Dörfler _UpdateColorLabel(); 6841fc4cb1fSAxel Dörfler } 6851fc4cb1fSAxel Dörfler } 686a10cf76eSAxel Dörfler } 687a10cf76eSAxel Dörfler 688a10cf76eSAxel Dörfler 6895de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 690a10cf76eSAxel Dörfler void 6915de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 692a10cf76eSAxel Dörfler { 69329e8a73aSAxel Dörfler float min, max; 69429e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 69529e8a73aSAxel Dörfler return; 696a10cf76eSAxel Dörfler 69729e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 69829e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 69929e8a73aSAxel Dörfler BMessage* message = item->Message(); 70029e8a73aSAxel Dörfler float refresh; 70129e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 70229e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 703a10cf76eSAxel Dörfler } 704a10cf76eSAxel Dörfler } 705a10cf76eSAxel Dörfler 706a10cf76eSAxel Dörfler 7075de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 708a10cf76eSAxel Dörfler void 7095de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 710a10cf76eSAxel Dörfler { 7117e44de36SRene Gollent for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) { 7127e44de36SRene Gollent BMenuItem* item = fRefreshMenu->ItemAt(i); 7137e44de36SRene Gollent if (item->Message()->FindFloat("refresh") == fSelected.refresh) { 714a10cf76eSAxel Dörfler item->SetMarked(true); 71526747978SAdrien Destugues // "Other" items only contains a refresh rate when active 71626747978SAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 717a10cf76eSAxel Dörfler return; 718a10cf76eSAxel Dörfler } 7197e44de36SRene Gollent } 720a10cf76eSAxel Dörfler 721a10cf76eSAxel Dörfler // this is a non-standard refresh rate 7227e44de36SRene Gollent if (fOtherRefresh != NULL) { 723a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 724a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 725a10cf76eSAxel Dörfler 7267e44de36SRene Gollent BString string; 7277e44de36SRene Gollent refresh_rate_to_string(fSelected.refresh, string); 728a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 729a10cf76eSAxel Dörfler 730c9e8f97aSAdrien Destugues string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS)); 731a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 732a10cf76eSAxel Dörfler } 7337e44de36SRene Gollent } 734a10cf76eSAxel Dörfler 735a10cf76eSAxel Dörfler 736a10cf76eSAxel Dörfler void 7375de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 738a10cf76eSAxel Dörfler { 739a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 740a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 741a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 742a10cf76eSAxel Dörfler 743a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 744a10cf76eSAxel Dörfler } 745a10cf76eSAxel Dörfler 746a10cf76eSAxel Dörfler 747a10cf76eSAxel Dörfler void 7485de171daSAxel Dörfler ScreenWindow::_UpdateControls() 749a10cf76eSAxel Dörfler { 750b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 751b21d610eSAxel Dörfler 752a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 753c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 754a10cf76eSAxel Dörfler item->SetMarked(true); 755a10cf76eSAxel Dörfler 756a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 757c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 758a10cf76eSAxel Dörfler item->SetMarked(true); 759a10cf76eSAxel Dörfler 760a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 761a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 762a10cf76eSAxel Dörfler 763a10cf76eSAxel Dörfler uint32 tvStandard; 764a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 765a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 766a10cf76eSAxel Dörfler if (!item->IsMarked()) 767a10cf76eSAxel Dörfler item->SetMarked(true); 768a10cf76eSAxel Dörfler break; 769a10cf76eSAxel Dörfler } 770a10cf76eSAxel Dörfler } 771a10cf76eSAxel Dörfler 7725de171daSAxel Dörfler _CheckResolutionMenu(); 7735de171daSAxel Dörfler _CheckColorMenu(); 7745de171daSAxel Dörfler _CheckRefreshMenu(); 775a10cf76eSAxel Dörfler 776a10cf76eSAxel Dörfler BString string; 777a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 778a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 779a10cf76eSAxel Dörfler 780a10cf76eSAxel Dörfler if (item != NULL) { 781a10cf76eSAxel Dörfler if (!item->IsMarked()) 782a10cf76eSAxel Dörfler item->SetMarked(true); 783a10cf76eSAxel Dörfler } else { 784a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 785a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 786a10cf76eSAxel Dörfler // 1. add a new resolution to list 787a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 788a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 789a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 790a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 791a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 792a10cf76eSAxel Dörfler // 2. choose nearest resolution 793a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 794a10cf76eSAxel Dörfler // 3. choose lowest resolution 795a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 796a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 797a10cf76eSAxel Dörfler if (item) 798a10cf76eSAxel Dörfler item->SetMarked(true); 799a10cf76eSAxel Dörfler 800a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 801a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 802a10cf76eSAxel Dörfler } 803a10cf76eSAxel Dörfler 804a10cf76eSAxel Dörfler // mark active combine mode 805a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 806a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 807a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 808c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 809a10cf76eSAxel Dörfler item->SetMarked(true); 810a10cf76eSAxel Dörfler break; 811a10cf76eSAxel Dörfler } 812a10cf76eSAxel Dörfler } 813a10cf76eSAxel Dörfler 814a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 815a10cf76eSAxel Dörfler 8161fc4cb1fSAxel Dörfler for (int32 i = 0, index = 0; i < kColorSpaceCount; i++) { 8171fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 8181fc4cb1fSAxel Dörfler continue; 8191fc4cb1fSAxel Dörfler 8201fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 8211fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(index); 822a10cf76eSAxel Dörfler break; 823a10cf76eSAxel Dörfler } 8241fc4cb1fSAxel Dörfler 8251fc4cb1fSAxel Dörfler index++; 826a10cf76eSAxel Dörfler } 827a10cf76eSAxel Dörfler 828c33a865cSJohn Scipione if (item != NULL && !item->IsMarked()) 829a10cf76eSAxel Dörfler item->SetMarked(true); 830a10cf76eSAxel Dörfler 8311fc4cb1fSAxel Dörfler _UpdateColorLabel(); 8325de171daSAxel Dörfler _UpdateMonitorView(); 8335de171daSAxel Dörfler _UpdateRefreshControl(); 834a10cf76eSAxel Dörfler 8355de171daSAxel Dörfler _CheckApplyEnabled(); 836a10cf76eSAxel Dörfler } 837a10cf76eSAxel Dörfler 838a10cf76eSAxel Dörfler 83912580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 840a10cf76eSAxel Dörfler void 8415de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 842a10cf76eSAxel Dörfler { 843c491b5adSJohn Scipione _UpdateActiveMode(current_workspace()); 844c491b5adSJohn Scipione } 845c491b5adSJohn Scipione 846c491b5adSJohn Scipione 847c491b5adSJohn Scipione void 848c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace) 849c491b5adSJohn Scipione { 85012580984SAxel Dörfler // Usually, this function gets called after a mode 851a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 852a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 853a10cf76eSAxel Dörfler // what kind of mode we actually got 854c491b5adSJohn Scipione if (fScreenMode.Get(fActive, workspace) == B_OK) { 855a10cf76eSAxel Dörfler fSelected = fActive; 856a10cf76eSAxel Dörfler 85712966d04SAxel Dörfler _UpdateMonitor(); 858c491b5adSJohn Scipione _BuildSupportedColorSpaces(); 8595de171daSAxel Dörfler _UpdateControls(); 860a10cf76eSAxel Dörfler } 861c491b5adSJohn Scipione } 862a10cf76eSAxel Dörfler 863a10cf76eSAxel Dörfler 864a10cf76eSAxel Dörfler void 865b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons() 866b21d610eSAxel Dörfler { 867b21d610eSAxel Dörfler uint32 columns; 868b21d610eSAxel Dörfler uint32 rows; 869b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 870b21d610eSAxel Dörfler 871b21d610eSAxel Dörfler char text[32]; 8725084d0d4SAlex Smith snprintf(text, sizeof(text), "%" B_PRId32, columns); 873b21d610eSAxel Dörfler fColumnsControl->SetText(text); 874b21d610eSAxel Dörfler 8755084d0d4SAlex Smith snprintf(text, sizeof(text), "%" B_PRId32, rows); 876b21d610eSAxel Dörfler fRowsControl->SetText(text); 877b21d610eSAxel Dörfler 878b21d610eSAxel Dörfler _GetColumnRowButton(true, false)->SetEnabled(columns != 1 && rows != 32); 879b21d610eSAxel Dörfler _GetColumnRowButton(true, true)->SetEnabled((columns + 1) * rows < 32); 880b21d610eSAxel Dörfler _GetColumnRowButton(false, false)->SetEnabled(rows != 1 && columns != 32); 881b21d610eSAxel Dörfler _GetColumnRowButton(false, true)->SetEnabled(columns * (rows + 1) < 32); 882b21d610eSAxel Dörfler } 883b21d610eSAxel Dörfler 884b21d610eSAxel Dörfler 885b21d610eSAxel Dörfler void 886a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 887a10cf76eSAxel Dörfler { 888a10cf76eSAxel Dörfler // move window on screen, if necessary 889a10cf76eSAxel Dörfler if (frame.right <= Frame().right 890a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 891a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 892a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 893a10cf76eSAxel Dörfler } 894a10cf76eSAxel Dörfler } 895a10cf76eSAxel Dörfler 896a10cf76eSAxel Dörfler 897a10cf76eSAxel Dörfler void 898a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 899a10cf76eSAxel Dörfler { 900c491b5adSJohn Scipione if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) { 901c491b5adSJohn Scipione _UpdateActiveMode(workspace); 902a10cf76eSAxel Dörfler 9036edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 9046edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 905a10cf76eSAxel Dörfler } 906c491b5adSJohn Scipione } 907a10cf76eSAxel Dörfler 908a10cf76eSAxel Dörfler 909a10cf76eSAxel Dörfler void 910a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 911a10cf76eSAxel Dörfler { 912a10cf76eSAxel Dörfler switch (message->what) { 913a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 9145de171daSAxel Dörfler _CheckApplyEnabled(); 915a10cf76eSAxel Dörfler break; 916a10cf76eSAxel Dörfler 917b21d610eSAxel Dörfler case kMsgWorkspaceLayoutChanged: 918a10cf76eSAxel Dörfler { 919b21d610eSAxel Dörfler int32 deltaX = 0; 920b21d610eSAxel Dörfler int32 deltaY = 0; 921b21d610eSAxel Dörfler message->FindInt32("delta_x", &deltaX); 922b21d610eSAxel Dörfler message->FindInt32("delta_y", &deltaY); 923b21d610eSAxel Dörfler 924b21d610eSAxel Dörfler if (deltaX == 0 && deltaY == 0) 925b21d610eSAxel Dörfler break; 926b21d610eSAxel Dörfler 927b21d610eSAxel Dörfler uint32 newColumns; 928b21d610eSAxel Dörfler uint32 newRows; 929b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&newColumns, &newRows); 930b21d610eSAxel Dörfler 931b21d610eSAxel Dörfler newColumns += deltaX; 932b21d610eSAxel Dörfler newRows += deltaY; 933b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, newRows); 934b21d610eSAxel Dörfler 935b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 9365de171daSAxel Dörfler _CheckApplyEnabled(); 937b21d610eSAxel Dörfler break; 938abc649b8SWaldemar Kornewald } 939b21d610eSAxel Dörfler 940b21d610eSAxel Dörfler case kMsgWorkspaceColumnsChanged: 941b21d610eSAxel Dörfler { 942b21d610eSAxel Dörfler uint32 newColumns = strtoul(fColumnsControl->Text(), NULL, 10); 943b21d610eSAxel Dörfler 944b21d610eSAxel Dörfler uint32 rows; 945b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(NULL, &rows); 946b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, rows); 947b21d610eSAxel Dörfler 948b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 949b21d610eSAxel Dörfler _CheckApplyEnabled(); 950b21d610eSAxel Dörfler break; 951b21d610eSAxel Dörfler } 952b21d610eSAxel Dörfler 953b21d610eSAxel Dörfler case kMsgWorkspaceRowsChanged: 954b21d610eSAxel Dörfler { 955b21d610eSAxel Dörfler uint32 newRows = strtoul(fRowsControl->Text(), NULL, 10); 956b21d610eSAxel Dörfler 957b21d610eSAxel Dörfler uint32 columns; 958b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, NULL); 959b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(columns, newRows); 960b21d610eSAxel Dörfler 961b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 962b21d610eSAxel Dörfler _CheckApplyEnabled(); 963a10cf76eSAxel Dörfler break; 964a10cf76eSAxel Dörfler } 965a10cf76eSAxel Dörfler 966a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 967a10cf76eSAxel Dörfler { 968a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 969a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 970a10cf76eSAxel Dörfler 9715de171daSAxel Dörfler _CheckColorMenu(); 9725de171daSAxel Dörfler _CheckRefreshMenu(); 973a10cf76eSAxel Dörfler 9745de171daSAxel Dörfler _UpdateMonitorView(); 9755de171daSAxel Dörfler _UpdateRefreshControl(); 976a10cf76eSAxel Dörfler 9775de171daSAxel Dörfler _CheckApplyEnabled(); 978a10cf76eSAxel Dörfler break; 979a10cf76eSAxel Dörfler } 980a10cf76eSAxel Dörfler 981a10cf76eSAxel Dörfler case POP_COLORS_MSG: 982a10cf76eSAxel Dörfler { 9831fc4cb1fSAxel Dörfler int32 space; 9841fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) != B_OK) 9851fc4cb1fSAxel Dörfler break; 986a10cf76eSAxel Dörfler 9871fc4cb1fSAxel Dörfler int32 index; 9881fc4cb1fSAxel Dörfler if (message->FindInt32("index", &index) == B_OK 9891fc4cb1fSAxel Dörfler && fColorsMenu->ItemAt(index) != NULL) 9901fc4cb1fSAxel Dörfler fUserSelectedColorSpace = fColorsMenu->ItemAt(index); 9911fc4cb1fSAxel Dörfler 9921fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 9931fc4cb1fSAxel Dörfler _UpdateColorLabel(); 994a10cf76eSAxel Dörfler 9955de171daSAxel Dörfler _CheckApplyEnabled(); 996a10cf76eSAxel Dörfler break; 997a10cf76eSAxel Dörfler } 998a10cf76eSAxel Dörfler 999a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 1000a40498e2SWaldemar Kornewald { 1001a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1002c9e8f97aSAdrien Destugues fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS)); 10031fc4cb1fSAxel Dörfler // revert "Other…" label - it might have a refresh rate prefix 1004a10cf76eSAxel Dörfler 10055de171daSAxel Dörfler _CheckApplyEnabled(); 1006a10cf76eSAxel Dörfler break; 1007a40498e2SWaldemar Kornewald } 1008a10cf76eSAxel Dörfler 1009a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 1010a10cf76eSAxel Dörfler { 101129e8a73aSAxel Dörfler // make sure menu shows something useful 10125de171daSAxel Dörfler _UpdateRefreshControl(); 1013a10cf76eSAxel Dörfler 101429e8a73aSAxel Dörfler float min = 0, max = 999; 101529e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 101629e8a73aSAxel Dörfler if (min < gMinRefresh) 101729e8a73aSAxel Dörfler min = gMinRefresh; 101829e8a73aSAxel Dörfler if (max > gMaxRefresh) 101929e8a73aSAxel Dörfler max = gMaxRefresh; 102029e8a73aSAxel Dörfler 102170a2b1b5SAxel Dörfler monitor_info info; 102270a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 102370a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 102470a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 102570a2b1b5SAxel Dörfler } 102670a2b1b5SAxel Dörfler 1027c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 102870a2b1b5SAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, 102970a2b1b5SAxel Dörfler min, max); 1030a10cf76eSAxel Dörfler fRefreshWindow->Show(); 1031a10cf76eSAxel Dörfler break; 1032a10cf76eSAxel Dörfler } 1033a10cf76eSAxel Dörfler 1034a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 1035a10cf76eSAxel Dörfler { 1036a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 1037a10cf76eSAxel Dörfler // select the refresh rate chosen 1038a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 1039a10cf76eSAxel Dörfler 10405de171daSAxel Dörfler _UpdateRefreshControl(); 10415de171daSAxel Dörfler _CheckApplyEnabled(); 1042a10cf76eSAxel Dörfler break; 1043a10cf76eSAxel Dörfler } 1044a10cf76eSAxel Dörfler 1045a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 1046a10cf76eSAxel Dörfler { 1047a10cf76eSAxel Dörfler // new combine mode has bee chosen 1048a10cf76eSAxel Dörfler int32 mode; 1049a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 1050a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 1051a10cf76eSAxel Dörfler 10525de171daSAxel Dörfler _CheckResolutionMenu(); 10535de171daSAxel Dörfler _CheckApplyEnabled(); 1054a10cf76eSAxel Dörfler break; 1055a10cf76eSAxel Dörfler } 1056a10cf76eSAxel Dörfler 1057a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 1058a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 10595de171daSAxel Dörfler _CheckApplyEnabled(); 1060a10cf76eSAxel Dörfler break; 1061a10cf76eSAxel Dörfler 1062a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 1063a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 10645de171daSAxel Dörfler _CheckApplyEnabled(); 1065a10cf76eSAxel Dörfler break; 1066a10cf76eSAxel Dörfler 1067a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 1068a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 10695de171daSAxel Dörfler _CheckApplyEnabled(); 1070a10cf76eSAxel Dörfler break; 1071a10cf76eSAxel Dörfler 1072df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 10736f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 10746f095d6aSRyan Leavengood app_info info; 10756f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 10766f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 10776f095d6aSRyan Leavengood } 1078df3f5bacSStephan Aßmus break; 1079df3f5bacSStephan Aßmus 1080a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 1081a10cf76eSAxel Dörfler { 10824be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 1083a10cf76eSAxel Dörfler fSelected.width = 640; 1084a10cf76eSAxel Dörfler fSelected.height = 480; 1085a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 1086a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 1087a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 1088a10cf76eSAxel Dörfler fSelected.swap_displays = false; 1089a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 1090a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 1091a10cf76eSAxel Dörfler 1092b21d610eSAxel Dörfler // TODO: workspace defaults 1093abc649b8SWaldemar Kornewald 10945de171daSAxel Dörfler _UpdateControls(); 1095a10cf76eSAxel Dörfler break; 1096a10cf76eSAxel Dörfler } 1097a10cf76eSAxel Dörfler 109810e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 109961c5c89bSAxel Dörfler fUndoScreenMode.Revert(); 11005de171daSAxel Dörfler _UpdateActiveMode(); 1101abc649b8SWaldemar Kornewald break; 1102abc649b8SWaldemar Kornewald 1103abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 1104abc649b8SWaldemar Kornewald { 1105abc649b8SWaldemar Kornewald fModified = false; 1106199893c3SAxel Dörfler fBootWorkspaceApplied = false; 1107abc649b8SWaldemar Kornewald 1108b21d610eSAxel Dörfler // ScreenMode::Revert() assumes that we first set the correct 1109b21d610eSAxel Dörfler // number of workspaces 1110b21d610eSAxel Dörfler 1111b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns, 1112b21d610eSAxel Dörfler fOriginalWorkspacesRows); 1113b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 1114b21d610eSAxel Dörfler 1115a10cf76eSAxel Dörfler fScreenMode.Revert(); 11165de171daSAxel Dörfler _UpdateActiveMode(); 1117a10cf76eSAxel Dörfler break; 1118abc649b8SWaldemar Kornewald } 1119a10cf76eSAxel Dörfler 1120a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 11215de171daSAxel Dörfler _Apply(); 1122a10cf76eSAxel Dörfler break; 1123a10cf76eSAxel Dörfler 1124abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 1125abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 1126abc649b8SWaldemar Kornewald fModified = true; 11275de171daSAxel Dörfler _UpdateActiveMode(); 1128a10cf76eSAxel Dörfler break; 1129a10cf76eSAxel Dörfler 1130a10cf76eSAxel Dörfler default: 1131a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 1132a10cf76eSAxel Dörfler break; 1133a10cf76eSAxel Dörfler } 1134a10cf76eSAxel Dörfler } 1135a10cf76eSAxel Dörfler 1136a10cf76eSAxel Dörfler 113712580984SAxel Dörfler status_t 113812580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 113912580984SAxel Dörfler { 114012580984SAxel Dörfler BPath path; 114112580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 114212580984SAxel Dörfler if (status < B_OK) 114312580984SAxel Dörfler return status; 114412580984SAxel Dörfler 114512580984SAxel Dörfler path.Append("kernel/drivers"); 114612580984SAxel Dörfler status = create_directory(path.Path(), 0755); 114712580984SAxel Dörfler if (status < B_OK) 114812580984SAxel Dörfler return status; 114912580984SAxel Dörfler 115012580984SAxel Dörfler path.Append("vesa"); 115112580984SAxel Dörfler BFile file; 115212580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 115312580984SAxel Dörfler if (status < B_OK) 115412580984SAxel Dörfler return status; 115512580984SAxel Dörfler 115612580984SAxel Dörfler char buffer[256]; 11575084d0d4SAlex Smith snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %" 11585084d0d4SAlex Smith B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel()); 115912580984SAxel Dörfler 116012580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 116112580984SAxel Dörfler if (bytesWritten < B_OK) 116212580984SAxel Dörfler return bytesWritten; 116312580984SAxel Dörfler 116412580984SAxel Dörfler return B_OK; 116512580984SAxel Dörfler } 116612580984SAxel Dörfler 116712580984SAxel Dörfler 1168b21d610eSAxel Dörfler BButton* 1169b21d610eSAxel Dörfler ScreenWindow::_CreateColumnRowButton(bool columns, bool plus) 1170b21d610eSAxel Dörfler { 1171b21d610eSAxel Dörfler BMessage* message = new BMessage(kMsgWorkspaceLayoutChanged); 1172b21d610eSAxel Dörfler message->AddInt32("delta_x", columns ? (plus ? 1 : -1) : 0); 1173b21d610eSAxel Dörfler message->AddInt32("delta_y", !columns ? (plus ? 1 : -1) : 0); 1174b21d610eSAxel Dörfler 1175b21d610eSAxel Dörfler BButton* button = new BButton(plus ? "+" : "-", message); 1176b21d610eSAxel Dörfler button->SetFontSize(be_plain_font->Size() * 0.9); 1177b21d610eSAxel Dörfler 1178b21d610eSAxel Dörfler BSize size = button->MinSize(); 1179b21d610eSAxel Dörfler size.width = button->StringWidth("+") + 16; 1180b21d610eSAxel Dörfler button->SetExplicitMinSize(size); 1181b21d610eSAxel Dörfler button->SetExplicitMaxSize(size); 1182b21d610eSAxel Dörfler 1183b21d610eSAxel Dörfler fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)] = button; 1184b21d610eSAxel Dörfler return button; 1185b21d610eSAxel Dörfler } 1186b21d610eSAxel Dörfler 1187b21d610eSAxel Dörfler 1188b21d610eSAxel Dörfler BButton* 1189b21d610eSAxel Dörfler ScreenWindow::_GetColumnRowButton(bool columns, bool plus) 1190b21d610eSAxel Dörfler { 1191b21d610eSAxel Dörfler return fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)]; 1192b21d610eSAxel Dörfler } 1193b21d610eSAxel Dörfler 1194b21d610eSAxel Dörfler 1195a10cf76eSAxel Dörfler void 11961fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces() 11971fc4cb1fSAxel Dörfler { 11981fc4cb1fSAxel Dörfler fSupportedColorSpaces = 0; 11991fc4cb1fSAxel Dörfler 12001fc4cb1fSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 12011fc4cb1fSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 12021fc4cb1fSAxel Dörfler if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) { 12031fc4cb1fSAxel Dörfler fSupportedColorSpaces |= 1 << i; 12041fc4cb1fSAxel Dörfler break; 12051fc4cb1fSAxel Dörfler } 12061fc4cb1fSAxel Dörfler } 12071fc4cb1fSAxel Dörfler } 12081fc4cb1fSAxel Dörfler } 12091fc4cb1fSAxel Dörfler 12101fc4cb1fSAxel Dörfler 12111fc4cb1fSAxel Dörfler void 12125de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1213a10cf76eSAxel Dörfler { 121427c43a2dSRene Gollent fApplyButton->SetEnabled(fSelected != fActive 121527c43a2dSRene Gollent || fAllWorkspacesItem->IsMarked()); 1216b21d610eSAxel Dörfler 1217b21d610eSAxel Dörfler uint32 columns; 1218b21d610eSAxel Dörfler uint32 rows; 1219b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 1220b21d610eSAxel Dörfler 1221b21d610eSAxel Dörfler fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns 1222b21d610eSAxel Dörfler || rows != fOriginalWorkspacesRows 12235de171daSAxel Dörfler || fSelected != fOriginal); 1224a10cf76eSAxel Dörfler } 1225a10cf76eSAxel Dörfler 1226a10cf76eSAxel Dörfler 1227a10cf76eSAxel Dörfler void 12285de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1229abc649b8SWaldemar Kornewald { 1230b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns, 1231b21d610eSAxel Dörfler &fOriginalWorkspacesRows); 1232b21d610eSAxel Dörfler 1233abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1234abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1235abc649b8SWaldemar Kornewald } 1236abc649b8SWaldemar Kornewald 1237abc649b8SWaldemar Kornewald 1238abc649b8SWaldemar Kornewald void 123912966d04SAxel Dörfler ScreenWindow::_UpdateMonitor() 124012966d04SAxel Dörfler { 124112966d04SAxel Dörfler monitor_info info; 124212966d04SAxel Dörfler float diagonalInches; 124312966d04SAxel Dörfler status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches); 124455030977SAxel Dörfler if (status == B_OK) { 12451a8af605SAxel Dörfler char text[512]; 124666ab1666SAxel Dörfler snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor, 124766ab1666SAxel Dörfler info.name[0] ? " " : "", info.name, diagonalInches); 124812966d04SAxel Dörfler 124912966d04SAxel Dörfler fMonitorInfo->SetText(text); 125012966d04SAxel Dörfler 125112966d04SAxel Dörfler if (fMonitorInfo->IsHidden()) 125212966d04SAxel Dörfler fMonitorInfo->Show(); 125355030977SAxel Dörfler } else { 125455030977SAxel Dörfler if (!fMonitorInfo->IsHidden()) 125555030977SAxel Dörfler fMonitorInfo->Hide(); 125655030977SAxel Dörfler } 1257af8f9c31SAxel Dörfler 125855030977SAxel Dörfler char text[512]; 12591a8af605SAxel Dörfler size_t length = 0; 12601a8af605SAxel Dörfler text[0] = 0; 12611a8af605SAxel Dörfler 126255030977SAxel Dörfler if (status == B_OK) { 1263af8f9c31SAxel Dörfler if (info.min_horizontal_frequency != 0 1264af8f9c31SAxel Dörfler && info.min_vertical_frequency != 0 1265af8f9c31SAxel Dörfler && info.max_pixel_clock != 0) { 12661a8af605SAxel Dörfler length = snprintf(text, sizeof(text), 1267c9e8f97aSAdrien Destugues B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n" 12689c1a9b92SAdrien Destugues "Vertical frequency:\t%lu - %lu Hz\n\n" 1269c9e8f97aSAdrien Destugues "Maximum pixel clock:\t%g MHz"), 12701a8af605SAxel Dörfler info.min_horizontal_frequency, info.max_horizontal_frequency, 12711a8af605SAxel Dörfler info.min_vertical_frequency, info.max_vertical_frequency, 12721a8af605SAxel Dörfler info.max_pixel_clock / 1000.0); 1273af8f9c31SAxel Dörfler } 12741a8af605SAxel Dörfler if (info.serial_number[0] && length < sizeof(text)) { 12751a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 1276c9e8f97aSAdrien Destugues B_TRANSLATE("%sSerial no.: %s"), length ? "\n\n" : "", 12771a8af605SAxel Dörfler info.serial_number); 12781a8af605SAxel Dörfler if (info.produced.week != 0 && info.produced.year != 0 12791a8af605SAxel Dörfler && length < sizeof(text)) { 12801a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 12811a8af605SAxel Dörfler " (%u/%u)", info.produced.week, info.produced.year); 12821a8af605SAxel Dörfler } 12831a8af605SAxel Dörfler } 128455030977SAxel Dörfler } 128561c5c89bSAxel Dörfler 128661c5c89bSAxel Dörfler // Add info about the graphics device 128761c5c89bSAxel Dörfler 128861c5c89bSAxel Dörfler accelerant_device_info deviceInfo; 128961c5c89bSAxel Dörfler if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK 129061c5c89bSAxel Dörfler && length < sizeof(text)) { 129161c5c89bSAxel Dörfler if (deviceInfo.name[0] && deviceInfo.chipset[0]) { 129261c5c89bSAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 129361c5c89bSAxel Dörfler "%s%s (%s)", length != 0 ? "\n\n" : "", deviceInfo.name, 129461c5c89bSAxel Dörfler deviceInfo.chipset); 129561c5c89bSAxel Dörfler } else if (deviceInfo.name[0] || deviceInfo.chipset[0]) { 129661c5c89bSAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 129761c5c89bSAxel Dörfler "%s%s", length != 0 ? "\n\n" : "", deviceInfo.name[0] 129861c5c89bSAxel Dörfler ? deviceInfo.name : deviceInfo.chipset); 129961c5c89bSAxel Dörfler } 130061c5c89bSAxel Dörfler } 130161c5c89bSAxel Dörfler 13021a8af605SAxel Dörfler if (text[0]) 13031a8af605SAxel Dörfler fMonitorView->SetToolTip(text); 130412966d04SAxel Dörfler } 130512966d04SAxel Dörfler 130612966d04SAxel Dörfler 130712966d04SAxel Dörfler void 13081fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel() 13091fc4cb1fSAxel Dörfler { 13101fc4cb1fSAxel Dörfler BString string; 1311551c9f15SSiarzhuk Zharski string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel"); 13121fc4cb1fSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 13131fc4cb1fSAxel Dörfler } 13141fc4cb1fSAxel Dörfler 13151fc4cb1fSAxel Dörfler 13161fc4cb1fSAxel Dörfler void 13175de171daSAxel Dörfler ScreenWindow::_Apply() 1318a10cf76eSAxel Dörfler { 1319abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 132061c5c89bSAxel Dörfler fUndoScreenMode.UpdateOriginalModes(); 132161c5c89bSAxel Dörfler 132207184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 132307184a9eSAxel Dörfler if (status == B_OK) { 1324abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1325abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1326abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1327abc649b8SWaldemar Kornewald display_mode newMode; 1328abc649b8SWaldemar Kornewald BScreen screen(this); 1329abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1330abc649b8SWaldemar Kornewald 1331abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1332abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 1333abc649b8SWaldemar Kornewald for (int32 i = 0; i < count_workspaces(); i++) { 1334abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1335abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1336abc649b8SWaldemar Kornewald } 1337199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1338199893c3SAxel Dörfler } else { 1339199893c3SAxel Dörfler if (current_workspace() == 0) 1340199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1341abc649b8SWaldemar Kornewald } 1342abc649b8SWaldemar Kornewald 1343a10cf76eSAxel Dörfler fActive = fSelected; 1344a10cf76eSAxel Dörfler 1345abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 1346a10cf76eSAxel Dörfler BWindow* window = new AlertWindow(this); 1347a10cf76eSAxel Dörfler window->Show(); 134807184a9eSAxel Dörfler } else { 134907184a9eSAxel Dörfler char message[256]; 135007184a9eSAxel Dörfler snprintf(message, sizeof(message), 1351c9e8f97aSAdrien Destugues B_TRANSLATE("The screen mode could not be set:\n\t%s\n"), 1352c9e8f97aSAdrien Destugues screen_errors(status)); 1353551c9f15SSiarzhuk Zharski BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message, 1354c9e8f97aSAdrien Destugues B_TRANSLATE("OK"), NULL, NULL, 135507184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 1356aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 135707184a9eSAxel Dörfler alert->Go(); 1358a10cf76eSAxel Dörfler } 135907184a9eSAxel Dörfler } 1360