1a10cf76eSAxel Dörfler /* 2b21d610eSAxel Dörfler * Copyright 2001-2009, Haiku. 3a10cf76eSAxel Dörfler * Distributed under the terms of the MIT License. 4a10cf76eSAxel Dörfler * 5a10cf76eSAxel Dörfler * Authors: 6a10cf76eSAxel Dörfler * Rafael Romo 7a10cf76eSAxel Dörfler * Stefano Ceccherini (burton666@libero.it) 8a10cf76eSAxel Dörfler * Andrew Bachmann 9a10cf76eSAxel Dörfler * Thomas Kurschel 10a10cf76eSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de 11df3f5bacSStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 12b72c4836SAlexandre Deckner * Alexandre Deckner, alex@zappotek.com 13a10cf76eSAxel Dörfler */ 14a10cf76eSAxel Dörfler 15a10cf76eSAxel Dörfler 16b21d610eSAxel Dörfler #include "ScreenWindow.h" 17b21d610eSAxel Dörfler 18b21d610eSAxel Dörfler #include <stdio.h> 19b21d610eSAxel Dörfler #include <stdlib.h> 20b21d610eSAxel Dörfler #include <string.h> 21b21d610eSAxel Dörfler 22b21d610eSAxel Dörfler #include <Alert.h> 23b21d610eSAxel Dörfler #include <Application.h> 24b21d610eSAxel Dörfler #include <Box.h> 25b21d610eSAxel Dörfler #include <Button.h> 26b21d610eSAxel Dörfler #include <Directory.h> 27b21d610eSAxel Dörfler #include <File.h> 28b21d610eSAxel Dörfler #include <FindDirectory.h> 29b21d610eSAxel Dörfler #include <InterfaceDefs.h> 30b21d610eSAxel Dörfler #include <LayoutBuilder.h> 31b21d610eSAxel Dörfler #include <MenuBar.h> 32b21d610eSAxel Dörfler #include <MenuItem.h> 33b21d610eSAxel Dörfler #include <MenuField.h> 34b21d610eSAxel Dörfler #include <Messenger.h> 35b21d610eSAxel Dörfler #include <Path.h> 36b21d610eSAxel Dörfler #include <PopUpMenu.h> 37b21d610eSAxel Dörfler #include <Screen.h> 38b21d610eSAxel Dörfler #include <String.h> 39b21d610eSAxel Dörfler #include <StringView.h> 40b21d610eSAxel Dörfler #include <Roster.h> 41b21d610eSAxel Dörfler #include <Window.h> 42b21d610eSAxel Dörfler 43b21d610eSAxel Dörfler #include <InterfacePrivate.h> 44b21d610eSAxel Dörfler 45a10cf76eSAxel Dörfler #include "AlertWindow.h" 46a10cf76eSAxel Dörfler #include "Constants.h" 47a10cf76eSAxel Dörfler #include "RefreshWindow.h" 48a10cf76eSAxel Dörfler #include "MonitorView.h" 49a10cf76eSAxel Dörfler #include "ScreenSettings.h" 50a10cf76eSAxel Dörfler #include "Utility.h" 51a10cf76eSAxel Dörfler 52a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant. 53a10cf76eSAxel Dörfler * It's a solution that works with the current BeOS interface that Haiku 54a10cf76eSAxel Dörfler * adopted. 55a10cf76eSAxel Dörfler * However, it's not a nice and clean solution. Don't use this header in any 56a10cf76eSAxel Dörfler * application if you can avoid it. No other driver is using this, or should 57a10cf76eSAxel Dörfler * be using this. 58a10cf76eSAxel Dörfler * It will be replaced as soon as we introduce an updated accelerant interface 59a10cf76eSAxel Dörfler * which may even happen before R1 hits the streets. 60a10cf76eSAxel Dörfler */ 61a10cf76eSAxel Dörfler #include "multimon.h" // the usual: DANGER WILL, ROBINSON! 62a10cf76eSAxel Dörfler 63a10cf76eSAxel Dörfler 6475c92c56SRyan Leavengood const char* kBackgroundsSignature = "application/x-vnd.Haiku-Backgrounds"; 65c5d80d47SAxel Dörfler 66a10cf76eSAxel Dörfler // list of officially supported colour spaces 67a10cf76eSAxel Dörfler static const struct { 68a10cf76eSAxel Dörfler color_space space; 69a10cf76eSAxel Dörfler int32 bits_per_pixel; 70a10cf76eSAxel Dörfler const char* label; 71a10cf76eSAxel Dörfler } kColorSpaces[] = { 729c1a9b92SAdrien Destugues { B_CMAP8, 8, "8 bits/pixel, 256 colors" }, 739c1a9b92SAdrien Destugues { B_RGB15, 15, "15 bits/pixel, 32768 colors" }, 749c1a9b92SAdrien Destugues { B_RGB16, 16, "16 bits/pixel, 65536 colors" }, 759c1a9b92SAdrien Destugues { B_RGB24, 24, "24 bits/pixel, 16 Million colors" }, 769c1a9b92SAdrien Destugues { B_RGB32, 32, "32 bits/pixel, 16 Million colors" } 77a10cf76eSAxel Dörfler }; 78b21d610eSAxel Dörfler static const int32 kColorSpaceCount 79b21d610eSAxel Dörfler = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]); 80a10cf76eSAxel Dörfler 81a10cf76eSAxel Dörfler // list of standard refresh rates 82a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 }; 83b21d610eSAxel Dörfler static const int32 kRefreshRateCount 84b21d610eSAxel Dörfler = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); 85a10cf76eSAxel Dörfler 86a10cf76eSAxel Dörfler // list of combine modes 87a10cf76eSAxel Dörfler static const struct { 88a10cf76eSAxel Dörfler combine_mode mode; 89a10cf76eSAxel Dörfler const char *name; 90a10cf76eSAxel Dörfler } kCombineModes[] = { 91a10cf76eSAxel Dörfler { kCombineDisable, "disable" }, 92a10cf76eSAxel Dörfler { kCombineHorizontally, "horizontally" }, 93a10cf76eSAxel Dörfler { kCombineVertically, "vertically" } 94a10cf76eSAxel Dörfler }; 95b21d610eSAxel Dörfler static const int32 kCombineModeCount 96b21d610eSAxel Dörfler = sizeof(kCombineModes) / sizeof(kCombineModes[0]); 9729e8a73aSAxel Dörfler 98a10cf76eSAxel Dörfler 99a10cf76eSAxel Dörfler static BString 100a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode) 101a10cf76eSAxel Dörfler { 102a10cf76eSAxel Dörfler switch (mode) { 103a10cf76eSAxel Dörfler case 0: return "disabled"; 104a10cf76eSAxel Dörfler case 1: return "NTSC"; 105a10cf76eSAxel Dörfler case 2: return "NTSC Japan"; 106a10cf76eSAxel Dörfler case 3: return "PAL BDGHI"; 107a10cf76eSAxel Dörfler case 4: return "PAL M"; 108a10cf76eSAxel Dörfler case 5: return "PAL N"; 109a10cf76eSAxel Dörfler case 6: return "SECAM"; 110a10cf76eSAxel Dörfler case 101: return "NTSC 443"; 111a10cf76eSAxel Dörfler case 102: return "PAL 60"; 112a10cf76eSAxel Dörfler case 103: return "PAL NC"; 113a10cf76eSAxel Dörfler default: 114a10cf76eSAxel Dörfler { 115a10cf76eSAxel Dörfler BString name; 116a10cf76eSAxel Dörfler name << "??? (" << mode << ")"; 117a10cf76eSAxel Dörfler 118a10cf76eSAxel Dörfler return name; 119a10cf76eSAxel Dörfler } 120a10cf76eSAxel Dörfler } 121a10cf76eSAxel Dörfler } 122a10cf76eSAxel Dörfler 123a10cf76eSAxel Dörfler 124a10cf76eSAxel Dörfler static void 125a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string) 126a10cf76eSAxel Dörfler { 127a10cf76eSAxel Dörfler string << mode.width << " x " << mode.height; 128a10cf76eSAxel Dörfler } 129a10cf76eSAxel Dörfler 130a10cf76eSAxel Dörfler 131a10cf76eSAxel Dörfler static void 132a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string, 133a10cf76eSAxel Dörfler bool appendUnit = true, bool alwaysWithFraction = false) 134a10cf76eSAxel Dörfler { 1358bf23e3cSAxel Dörfler snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, 1368bf23e3cSAxel Dörfler refresh); 137a10cf76eSAxel Dörfler string.UnlockBuffer(); 138a10cf76eSAxel Dörfler 139a10cf76eSAxel Dörfler if (appendUnit) 140a10cf76eSAxel Dörfler string << " Hz"; 141a10cf76eSAxel Dörfler } 142a10cf76eSAxel Dörfler 143a10cf76eSAxel Dörfler 14407184a9eSAxel Dörfler static const char* 14507184a9eSAxel Dörfler screen_errors(status_t status) 14607184a9eSAxel Dörfler { 14707184a9eSAxel Dörfler switch (status) { 14807184a9eSAxel Dörfler case B_ENTRY_NOT_FOUND: 1499c1a9b92SAdrien Destugues return "Unknown mode"; 15007184a9eSAxel Dörfler // TODO: add more? 15107184a9eSAxel Dörfler 15207184a9eSAxel Dörfler default: 15307184a9eSAxel Dörfler return strerror(status); 15407184a9eSAxel Dörfler } 15507184a9eSAxel Dörfler } 15607184a9eSAxel Dörfler 15729e8a73aSAxel Dörfler 1583dfd20c0SStephan Aßmus // #pragma mark - 1593dfd20c0SStephan Aßmus 1603dfd20c0SStephan Aßmus 1615a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings* settings) 162b21d610eSAxel Dörfler : 163b21d610eSAxel Dörfler BWindow(settings->WindowFrame(), "Screen", B_TITLED_WINDOW, 164b21d610eSAxel Dörfler B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS, 165b21d610eSAxel Dörfler B_ALL_WORKSPACES), 166199893c3SAxel Dörfler fBootWorkspaceApplied(false), 167a10cf76eSAxel Dörfler fScreenMode(this), 16861c5c89bSAxel Dörfler fUndoScreenMode(this), 169abc649b8SWaldemar Kornewald fModified(false) 170a10cf76eSAxel Dörfler { 171a10cf76eSAxel Dörfler BScreen screen(this); 172a10cf76eSAxel Dörfler 17312580984SAxel Dörfler accelerant_device_info info; 174d1516993SAxel Dörfler if (screen.GetDeviceInfo(&info) == B_OK 175d1516993SAxel Dörfler && !strcasecmp(info.chipset, "VESA")) 17612580984SAxel Dörfler fIsVesa = true; 17712580984SAxel Dörfler 1785de171daSAxel Dörfler _UpdateOriginal(); 1791fc4cb1fSAxel Dörfler _BuildSupportedColorSpaces(); 180a10cf76eSAxel Dörfler fActive = fSelected = fOriginal; 181a10cf76eSAxel Dörfler 1825a78744bSAxel Dörfler fSettings = settings; 1835a78744bSAxel Dörfler 1845a78744bSAxel Dörfler // we need the "Current Workspace" first to get its height 1855a78744bSAxel Dörfler 1869c1a9b92SAdrien Destugues BPopUpMenu *popUpMenu = new BPopUpMenu("Current workspace", true, true); 1879c1a9b92SAdrien Destugues fAllWorkspacesItem = new BMenuItem("All workspaces", 188d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 1895a78744bSAxel Dörfler popUpMenu->AddItem(fAllWorkspacesItem); 1909c1a9b92SAdrien Destugues BMenuItem *item = new BMenuItem("Current workspace", 191d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 192b72c4836SAlexandre Deckner 1935a78744bSAxel Dörfler popUpMenu->AddItem(item); 19427c43a2dSRene Gollent fAllWorkspacesItem->SetMarked(true); 1955a78744bSAxel Dörfler 196b21d610eSAxel Dörfler BMenuField* workspaceMenuField = new BMenuField("WorkspaceMenu", NULL, 197b21d610eSAxel Dörfler popUpMenu, NULL); 1985a78744bSAxel Dörfler workspaceMenuField->ResizeToPreferred(); 199a10cf76eSAxel Dörfler 200a10cf76eSAxel Dörfler // box on the left with workspace count and monitor view 201a10cf76eSAxel Dörfler 202b21d610eSAxel Dörfler BBox* screenBox = new BBox("screen box"); 2038bf23e3cSAxel Dörfler BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 5.0); 204b21d610eSAxel Dörfler layout->SetInsets(10, 10, 10, 10); 205b21d610eSAxel Dörfler screenBox->SetLayout(layout); 206a10cf76eSAxel Dörfler 20712966d04SAxel Dörfler fMonitorInfo = new BStringView("monitor info", ""); 20812966d04SAxel Dörfler screenBox->AddChild(fMonitorInfo); 20912966d04SAxel Dörfler 210df3f5bacSStephan Aßmus fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), "monitor", 2116bda235aSStefano Ceccherini screen.Frame().IntegerWidth() + 1, screen.Frame().IntegerHeight() + 1); 212b21d610eSAxel Dörfler screenBox->AddChild(fMonitorView); 2135a78744bSAxel Dörfler 214b21d610eSAxel Dörfler fColumnsControl = new BTextControl("Columns:", "0", 215b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceColumnsChanged)); 216b21d610eSAxel Dörfler fRowsControl = new BTextControl("Rows:", "0", 217b21d610eSAxel Dörfler new BMessage(kMsgWorkspaceRowsChanged)); 218b21d610eSAxel Dörfler 219b21d610eSAxel Dörfler screenBox->AddChild(BLayoutBuilder::Grid<>(5.0, 5.0) 220b21d610eSAxel Dörfler .Add(new BStringView("", "Workspaces"), 0, 0, 3) 221b21d610eSAxel Dörfler .AddTextControl(fColumnsControl, 0, 1, B_ALIGN_RIGHT) 222b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 0, 2, 1) 223b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(true, false)) 224b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(true, true)) 225b21d610eSAxel Dörfler .End() 226b21d610eSAxel Dörfler .AddTextControl(fRowsControl, 0, 2, B_ALIGN_RIGHT) 227b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 0, 2, 2) 228b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(false, false)) 229b21d610eSAxel Dörfler .Add(_CreateColumnRowButton(false, true)) 230*25fd5c7bSAlex Wilson .End() 231*25fd5c7bSAlex Wilson .View()); 232b21d610eSAxel Dörfler 233b21d610eSAxel Dörfler fBackgroundsButton = new BButton("BackgroundsButton", 2349c1a9b92SAdrien Destugues "Set background" B_UTF8_ELLIPSIS, 235b21d610eSAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 236b21d610eSAxel Dörfler fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 237b21d610eSAxel Dörfler screenBox->AddChild(fBackgroundsButton); 238a10cf76eSAxel Dörfler 239a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 240a10cf76eSAxel Dörfler 241b21d610eSAxel Dörfler BBox* controlsBox = new BBox("controls box"); 242b21d610eSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 243*25fd5c7bSAlex Wilson BGroupView* outerControlsView = new BGroupView(B_VERTICAL, 10.0); 244*25fd5c7bSAlex Wilson outerControlsView->GroupLayout()->SetInsets(10, 10, 10, 10); 245b21d610eSAxel Dörfler controlsBox->AddChild(outerControlsView); 246a10cf76eSAxel Dörfler 247a10cf76eSAxel Dörfler fResolutionMenu = new BPopUpMenu("resolution", true, true); 248a10cf76eSAxel Dörfler 24966ab1666SAxel Dörfler uint16 maxWidth = 0; 25066ab1666SAxel Dörfler uint16 maxHeight = 0; 25166ab1666SAxel Dörfler uint16 previousWidth = 0; 25266ab1666SAxel Dörfler uint16 previousHeight = 0; 253a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 254a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 255a10cf76eSAxel Dörfler 256a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 257a10cf76eSAxel Dörfler continue; 258a10cf76eSAxel Dörfler 259a10cf76eSAxel Dörfler previousWidth = mode.width; 260a10cf76eSAxel Dörfler previousHeight = mode.height; 26166ab1666SAxel Dörfler if (maxWidth < mode.width) 26266ab1666SAxel Dörfler maxWidth = mode.width; 26366ab1666SAxel Dörfler if (maxHeight < mode.height) 26466ab1666SAxel Dörfler maxHeight = mode.height; 265a10cf76eSAxel Dörfler 266a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_RESOLUTION_MSG); 267a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 268a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 269a10cf76eSAxel Dörfler 270a10cf76eSAxel Dörfler BString name; 271a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 272a10cf76eSAxel Dörfler 273a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 274a10cf76eSAxel Dörfler } 275a10cf76eSAxel Dörfler 27666ab1666SAxel Dörfler fMonitorView->SetMaxResolution(maxWidth, maxHeight); 27766ab1666SAxel Dörfler 278b21d610eSAxel Dörfler fResolutionField = new BMenuField("ResolutionMenu", "Resolution:", 279b21d610eSAxel Dörfler fResolutionMenu, NULL); 280a10cf76eSAxel Dörfler 281f99cba9eSAxel Dörfler fColorsMenu = new BPopUpMenu("colors", true, false); 282a10cf76eSAxel Dörfler 283a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 2841fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 2851fc4cb1fSAxel Dörfler continue; 2861fc4cb1fSAxel Dörfler 287a10cf76eSAxel Dörfler BMessage* message = new BMessage(POP_COLORS_MSG); 288a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 289a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 290a10cf76eSAxel Dörfler 2911fc4cb1fSAxel Dörfler BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message); 2921fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == screen.ColorSpace()) 2931fc4cb1fSAxel Dörfler fUserSelectedColorSpace = item; 2941fc4cb1fSAxel Dörfler 2951fc4cb1fSAxel Dörfler fColorsMenu->AddItem(item); 296a10cf76eSAxel Dörfler } 297a10cf76eSAxel Dörfler 298b21d610eSAxel Dörfler fColorsField = new BMenuField("ColorsMenu", "Colors:", fColorsMenu, NULL); 299a10cf76eSAxel Dörfler 300a10cf76eSAxel Dörfler fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 301a10cf76eSAxel Dörfler 30229e8a73aSAxel Dörfler BMessage *message; 30329e8a73aSAxel Dörfler 30429e8a73aSAxel Dörfler float min, max; 30529e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fActive, min, max) && min == max) { 30629e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 30729e8a73aSAxel Dörfler // frequency, like the VESA driver 30829e8a73aSAxel Dörfler BString name; 30929e8a73aSAxel Dörfler name << min << " Hz"; 31029e8a73aSAxel Dörfler 31129e8a73aSAxel Dörfler message = new BMessage(POP_REFRESH_MSG); 31229e8a73aSAxel Dörfler message->AddFloat("refresh", min); 31329e8a73aSAxel Dörfler 31429e8a73aSAxel Dörfler fRefreshMenu->AddItem(item = new BMenuItem(name.String(), message)); 31529e8a73aSAxel Dörfler item->SetEnabled(false); 31629e8a73aSAxel Dörfler } else { 31770a2b1b5SAxel Dörfler monitor_info info; 31870a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 31970a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 32070a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 32170a2b1b5SAxel Dörfler } 32270a2b1b5SAxel Dörfler 323a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 32470a2b1b5SAxel Dörfler if (kRefreshRates[i] < min || kRefreshRates[i] > max) 32570a2b1b5SAxel Dörfler continue; 32670a2b1b5SAxel Dörfler 327a10cf76eSAxel Dörfler BString name; 328a10cf76eSAxel Dörfler name << kRefreshRates[i] << " Hz"; 329a10cf76eSAxel Dörfler 33029e8a73aSAxel Dörfler message = new BMessage(POP_REFRESH_MSG); 331a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 332a10cf76eSAxel Dörfler 333a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 334a10cf76eSAxel Dörfler } 335a10cf76eSAxel Dörfler 33629e8a73aSAxel Dörfler message = new BMessage(POP_OTHER_REFRESH_MSG); 337a10cf76eSAxel Dörfler 338a10cf76eSAxel Dörfler fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message); 339a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 34029e8a73aSAxel Dörfler } 341a10cf76eSAxel Dörfler 3429c1a9b92SAdrien Destugues fRefreshField = new BMenuField("RefreshMenu", "Refresh rate:", 343b21d610eSAxel Dörfler fRefreshMenu, NULL); 344b21d610eSAxel Dörfler 34512580984SAxel Dörfler if (_IsVesa()) 34612580984SAxel Dörfler fRefreshField->Hide(); 347a10cf76eSAxel Dörfler 348a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 349a10cf76eSAxel Dörfler { 350a10cf76eSAxel Dörfler bool dummy; 351a10cf76eSAxel Dörfler uint32 dummy32; 352a10cf76eSAxel Dörfler bool multiMonSupport; 353a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 354a10cf76eSAxel Dörfler bool tvStandardSupport; 355a10cf76eSAxel Dörfler 356a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 357a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 358a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 359a10cf76eSAxel Dörfler 360a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 361a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 362a10cf76eSAxel Dörfler 363a10cf76eSAxel Dörfler fCombineMenu = new BPopUpMenu("CombineDisplays", true, true); 364a10cf76eSAxel Dörfler 365a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 366a10cf76eSAxel Dörfler message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 367a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 368a10cf76eSAxel Dörfler 369d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 370d1516993SAxel Dörfler message)); 371a10cf76eSAxel Dörfler } 372a10cf76eSAxel Dörfler 373b21d610eSAxel Dörfler fCombineField = new BMenuField("CombineMenu", 3749c1a9b92SAdrien Destugues "Combine displays:", fCombineMenu, NULL); 375a10cf76eSAxel Dörfler 376a10cf76eSAxel Dörfler if (!multiMonSupport) 377df3f5bacSStephan Aßmus fCombineField->Hide(); 378a10cf76eSAxel Dörfler 379a10cf76eSAxel Dörfler fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true); 380a10cf76eSAxel Dörfler 381a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 382a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 383a10cf76eSAxel Dörfler message->AddBool("swap", false); 384a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("no", message)); 385a10cf76eSAxel Dörfler 386a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 387a10cf76eSAxel Dörfler message->AddBool("swap", true); 388a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message)); 389a10cf76eSAxel Dörfler 3909c1a9b92SAdrien Destugues fSwapDisplaysField = new BMenuField("SwapMenu", "Swap displays:", 391b21d610eSAxel Dörfler fSwapDisplaysMenu, NULL); 392a10cf76eSAxel Dörfler 393a10cf76eSAxel Dörfler if (!multiMonSupport) 394df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 395a10cf76eSAxel Dörfler 396a10cf76eSAxel Dörfler fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true); 397a10cf76eSAxel Dörfler 398a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 399a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 400a10cf76eSAxel Dörfler message->AddBool("use", false); 401a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message)); 402a10cf76eSAxel Dörfler 403a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 404a10cf76eSAxel Dörfler message->AddBool("use", true); 405a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message)); 406a10cf76eSAxel Dörfler 407b21d610eSAxel Dörfler fUseLaptopPanelField = new BMenuField("UseLaptopPanel", 4089c1a9b92SAdrien Destugues "Use laptop panel:", fUseLaptopPanelMenu, NULL); 409a10cf76eSAxel Dörfler 410a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 411df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 412a10cf76eSAxel Dörfler 413a10cf76eSAxel Dörfler fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 414a10cf76eSAxel Dörfler 415a10cf76eSAxel Dörfler // arbitrary limit 416a10cf76eSAxel Dörfler uint32 i; 417a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 418a10cf76eSAxel Dörfler uint32 mode; 419a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 420a10cf76eSAxel Dörfler break; 421a10cf76eSAxel Dörfler 422a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 423a10cf76eSAxel Dörfler 424a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 425a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 426a10cf76eSAxel Dörfler 427a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 428a10cf76eSAxel Dörfler } 429a10cf76eSAxel Dörfler 4309c1a9b92SAdrien Destugues fTVStandardField = new BMenuField("tv standard", "Video format:", 431b21d610eSAxel Dörfler fTVStandardMenu, NULL); 432df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 433a10cf76eSAxel Dörfler 434b21d610eSAxel Dörfler if (!tvStandardSupport || i == 0) 435df3f5bacSStephan Aßmus fTVStandardField->Hide(); 436a10cf76eSAxel Dörfler } 437a10cf76eSAxel Dörfler 438*25fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 439*25fd5c7bSAlex Wilson .AddGrid(5.0, 5.0) 440b21d610eSAxel Dörfler .AddMenuField(fResolutionField, 0, 0, B_ALIGN_RIGHT) 441b21d610eSAxel Dörfler .AddMenuField(fColorsField, 0, 1, B_ALIGN_RIGHT) 442b21d610eSAxel Dörfler .AddMenuField(fRefreshField, 0, 2, B_ALIGN_RIGHT) 443b21d610eSAxel Dörfler .AddMenuField(fCombineField, 0, 3, B_ALIGN_RIGHT) 444b21d610eSAxel Dörfler .AddMenuField(fSwapDisplaysField, 0, 4, B_ALIGN_RIGHT) 445b21d610eSAxel Dörfler .AddMenuField(fUseLaptopPanelField, 0, 5, B_ALIGN_RIGHT) 446*25fd5c7bSAlex Wilson .AddMenuField(fTVStandardField, 0, 6, B_ALIGN_RIGHT) 447*25fd5c7bSAlex Wilson .End(); 448df3f5bacSStephan Aßmus 449abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 450abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 451b21d610eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG));*/ 452a10cf76eSAxel Dörfler 453b21d610eSAxel Dörfler fApplyButton = new BButton("ApplyButton", "Apply", 454df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 455df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 456*25fd5c7bSAlex Wilson BLayoutBuilder::Group<>(outerControlsView) 457b21d610eSAxel Dörfler .AddGlue() 458*25fd5c7bSAlex Wilson .AddGroup(B_HORIZONTAL) 459*25fd5c7bSAlex Wilson .AddGlue() 460*25fd5c7bSAlex Wilson .Add(fApplyButton); 461b21d610eSAxel Dörfler 462b21d610eSAxel Dörfler fRevertButton = new BButton("RevertButton", "Revert", 463b21d610eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 464b21d610eSAxel Dörfler fRevertButton->SetEnabled(false); 465b21d610eSAxel Dörfler 466*25fd5c7bSAlex Wilson BLayoutBuilder::Group<>(this, B_VERTICAL, 10.0) 467b21d610eSAxel Dörfler .SetInsets(10, 10, 10, 10) 468b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 10.0) 469b21d610eSAxel Dörfler .AddGroup(B_VERTICAL) 470*25fd5c7bSAlex Wilson .AddStrut(controlsBox->TopBorderOffset() - 1) 471b21d610eSAxel Dörfler .Add(screenBox) 472b21d610eSAxel Dörfler .End() 473b21d610eSAxel Dörfler .Add(controlsBox) 474b21d610eSAxel Dörfler .End() 475b21d610eSAxel Dörfler .AddGroup(B_HORIZONTAL, 10.0) 476b21d610eSAxel Dörfler .Add(fRevertButton) 477b21d610eSAxel Dörfler .AddGlue(); 478b21d610eSAxel Dörfler 4795de171daSAxel Dörfler _UpdateControls(); 48012966d04SAxel Dörfler _UpdateMonitor(); 481a10cf76eSAxel Dörfler } 482a10cf76eSAxel Dörfler 483a10cf76eSAxel Dörfler 484a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 485a10cf76eSAxel Dörfler { 486a10cf76eSAxel Dörfler delete fSettings; 487a10cf76eSAxel Dörfler } 488a10cf76eSAxel Dörfler 489a10cf76eSAxel Dörfler 490a10cf76eSAxel Dörfler bool 491a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 492a10cf76eSAxel Dörfler { 493a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 494199893c3SAxel Dörfler 495199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 496199893c3SAxel Dörfler screen_mode vesaMode; 497199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 498199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 49912580984SAxel Dörfler if (status < B_OK) { 50012580984SAxel Dörfler BString warning = "Could not write VESA mode settings file:\n\t"; 50112580984SAxel Dörfler warning << strerror(status); 5029c1a9b92SAdrien Destugues (new BAlert("VesaAlert", warning.String(), "OK", NULL, NULL, 50312580984SAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); 50412580984SAxel Dörfler } 50512580984SAxel Dörfler } 50612580984SAxel Dörfler 507a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 508a10cf76eSAxel Dörfler 509a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 510a10cf76eSAxel Dörfler } 511a10cf76eSAxel Dörfler 512a10cf76eSAxel Dörfler 5135de171daSAxel Dörfler /*! Update resolution list according to combine mode 5141fc4cb1fSAxel Dörfler (some resolutions may not be combinable due to memory restrictions). 515a10cf76eSAxel Dörfler */ 516a10cf76eSAxel Dörfler void 5175de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 518a10cf76eSAxel Dörfler { 519a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 520a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 521a10cf76eSAxel Dörfler 522a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 523a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 524a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 525a10cf76eSAxel Dörfler continue; 526a10cf76eSAxel Dörfler 527a10cf76eSAxel Dörfler BString name; 528a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 529a10cf76eSAxel Dörfler 530a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 531a10cf76eSAxel Dörfler if (item != NULL) 532a10cf76eSAxel Dörfler item->SetEnabled(true); 533a10cf76eSAxel Dörfler } 534a10cf76eSAxel Dörfler } 535a10cf76eSAxel Dörfler 536a10cf76eSAxel Dörfler 5375de171daSAxel Dörfler /*! Update color and refresh options according to current mode 5385de171daSAxel Dörfler (a color space is made active if there is any mode with 5395de171daSAxel Dörfler given resolution and this colour space; same applies for 5405de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 541a10cf76eSAxel Dörfler */ 542a10cf76eSAxel Dörfler void 5435de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 544a10cf76eSAxel Dörfler { 5451fc4cb1fSAxel Dörfler int32 supportsAnything = false; 5461fc4cb1fSAxel Dörfler int32 index = 0; 5471fc4cb1fSAxel Dörfler 548a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 5491fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 5501fc4cb1fSAxel Dörfler continue; 5511fc4cb1fSAxel Dörfler 552a10cf76eSAxel Dörfler bool supported = false; 553a10cf76eSAxel Dörfler 554a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 555a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 556a10cf76eSAxel Dörfler 557a10cf76eSAxel Dörfler if (fSelected.width == mode.width 558a10cf76eSAxel Dörfler && fSelected.height == mode.height 5591fc4cb1fSAxel Dörfler && kColorSpaces[i].space == mode.space 560a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 5611fc4cb1fSAxel Dörfler supportsAnything = true; 562a10cf76eSAxel Dörfler supported = true; 563a10cf76eSAxel Dörfler break; 564a10cf76eSAxel Dörfler } 565a10cf76eSAxel Dörfler } 566a10cf76eSAxel Dörfler 5671fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(index++); 568a10cf76eSAxel Dörfler if (item) 569a10cf76eSAxel Dörfler item->SetEnabled(supported); 570a10cf76eSAxel Dörfler } 5711fc4cb1fSAxel Dörfler 5721fc4cb1fSAxel Dörfler fColorsField->SetEnabled(supportsAnything); 5731fc4cb1fSAxel Dörfler 5741fc4cb1fSAxel Dörfler if (!supportsAnything) 5751fc4cb1fSAxel Dörfler return; 5761fc4cb1fSAxel Dörfler 5771fc4cb1fSAxel Dörfler // Make sure a valid item is selected 5781fc4cb1fSAxel Dörfler 5791fc4cb1fSAxel Dörfler BMenuItem* item = fColorsMenu->FindMarked(); 5801fc4cb1fSAxel Dörfler bool changed = false; 5811fc4cb1fSAxel Dörfler 5821fc4cb1fSAxel Dörfler if (item != fUserSelectedColorSpace) { 5831fc4cb1fSAxel Dörfler if (fUserSelectedColorSpace != NULL 5841fc4cb1fSAxel Dörfler && fUserSelectedColorSpace->IsEnabled()) { 5851fc4cb1fSAxel Dörfler fUserSelectedColorSpace->SetMarked(true); 5861fc4cb1fSAxel Dörfler item = fUserSelectedColorSpace; 5871fc4cb1fSAxel Dörfler changed = true; 5881fc4cb1fSAxel Dörfler } 5891fc4cb1fSAxel Dörfler } 5901fc4cb1fSAxel Dörfler if (item != NULL && !item->IsEnabled()) { 5911fc4cb1fSAxel Dörfler // find the next best item 5921fc4cb1fSAxel Dörfler int32 index = fColorsMenu->IndexOf(item); 5931fc4cb1fSAxel Dörfler bool found = false; 5941fc4cb1fSAxel Dörfler 5951fc4cb1fSAxel Dörfler for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) { 5961fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 5971fc4cb1fSAxel Dörfler if (item->IsEnabled()) { 5981fc4cb1fSAxel Dörfler found = true; 5991fc4cb1fSAxel Dörfler break; 6001fc4cb1fSAxel Dörfler } 6011fc4cb1fSAxel Dörfler } 6021fc4cb1fSAxel Dörfler if (!found) { 6031fc4cb1fSAxel Dörfler // search backwards as well 6041fc4cb1fSAxel Dörfler for (int32 i = index - 1; i >= 0; i--) { 6051fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(i); 6061fc4cb1fSAxel Dörfler if (item->IsEnabled()) 6071fc4cb1fSAxel Dörfler break; 6081fc4cb1fSAxel Dörfler } 6091fc4cb1fSAxel Dörfler } 6101fc4cb1fSAxel Dörfler 6111fc4cb1fSAxel Dörfler item->SetMarked(true); 6121fc4cb1fSAxel Dörfler changed = true; 6131fc4cb1fSAxel Dörfler } 6141fc4cb1fSAxel Dörfler 6151fc4cb1fSAxel Dörfler if (changed) { 6161fc4cb1fSAxel Dörfler // Update selected space 6171fc4cb1fSAxel Dörfler 6181fc4cb1fSAxel Dörfler BMessage* message = item->Message(); 6191fc4cb1fSAxel Dörfler int32 space; 6201fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) == B_OK) { 6211fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 6221fc4cb1fSAxel Dörfler _UpdateColorLabel(); 6231fc4cb1fSAxel Dörfler } 6241fc4cb1fSAxel Dörfler } 625a10cf76eSAxel Dörfler } 626a10cf76eSAxel Dörfler 627a10cf76eSAxel Dörfler 6285de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 629a10cf76eSAxel Dörfler void 6305de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 631a10cf76eSAxel Dörfler { 63229e8a73aSAxel Dörfler float min, max; 63329e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 63429e8a73aSAxel Dörfler return; 635a10cf76eSAxel Dörfler 63629e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 63729e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 63829e8a73aSAxel Dörfler BMessage* message = item->Message(); 63929e8a73aSAxel Dörfler float refresh; 64029e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 64129e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 642a10cf76eSAxel Dörfler } 643a10cf76eSAxel Dörfler } 644a10cf76eSAxel Dörfler 645a10cf76eSAxel Dörfler 6465de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 647a10cf76eSAxel Dörfler void 6485de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 649a10cf76eSAxel Dörfler { 650a10cf76eSAxel Dörfler BString string; 651a10cf76eSAxel Dörfler refresh_rate_to_string(fSelected.refresh, string); 652a10cf76eSAxel Dörfler 653a10cf76eSAxel Dörfler BMenuItem* item = fRefreshMenu->FindItem(string.String()); 654a10cf76eSAxel Dörfler if (item) { 655a10cf76eSAxel Dörfler if (!item->IsMarked()) 656a10cf76eSAxel Dörfler item->SetMarked(true); 65729e8a73aSAxel Dörfler 658a10cf76eSAxel Dörfler // "Other…" items only contains a refresh rate when active 659e6b421a9SJérôme Duval fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS); 660a10cf76eSAxel Dörfler return; 661a10cf76eSAxel Dörfler } 662a10cf76eSAxel Dörfler 663a10cf76eSAxel Dörfler // this is a non-standard refresh rate 664a10cf76eSAxel Dörfler 665a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 666a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 667a10cf76eSAxel Dörfler 668a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 669a10cf76eSAxel Dörfler 6709c1a9b92SAdrien Destugues string.Append("/other" B_UTF8_ELLIPSIS); 671a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 672a10cf76eSAxel Dörfler } 673a10cf76eSAxel Dörfler 674a10cf76eSAxel Dörfler 675a10cf76eSAxel Dörfler void 6765de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 677a10cf76eSAxel Dörfler { 678a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 679a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 680a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 681a10cf76eSAxel Dörfler 682a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 683a10cf76eSAxel Dörfler } 684a10cf76eSAxel Dörfler 685a10cf76eSAxel Dörfler 686a10cf76eSAxel Dörfler void 6875de171daSAxel Dörfler ScreenWindow::_UpdateControls() 688a10cf76eSAxel Dörfler { 689b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 690b21d610eSAxel Dörfler 691a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 692a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 693a10cf76eSAxel Dörfler item->SetMarked(true); 694a10cf76eSAxel Dörfler 695a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 696a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 697a10cf76eSAxel Dörfler item->SetMarked(true); 698a10cf76eSAxel Dörfler 699a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 700a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 701a10cf76eSAxel Dörfler 702a10cf76eSAxel Dörfler uint32 tvStandard; 703a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 704a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 705a10cf76eSAxel Dörfler if (!item->IsMarked()) 706a10cf76eSAxel Dörfler item->SetMarked(true); 707a10cf76eSAxel Dörfler break; 708a10cf76eSAxel Dörfler } 709a10cf76eSAxel Dörfler } 710a10cf76eSAxel Dörfler 7115de171daSAxel Dörfler _CheckResolutionMenu(); 7125de171daSAxel Dörfler _CheckColorMenu(); 7135de171daSAxel Dörfler _CheckRefreshMenu(); 714a10cf76eSAxel Dörfler 715a10cf76eSAxel Dörfler BString string; 716a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 717a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 718a10cf76eSAxel Dörfler 719a10cf76eSAxel Dörfler if (item != NULL) { 720a10cf76eSAxel Dörfler if (!item->IsMarked()) 721a10cf76eSAxel Dörfler item->SetMarked(true); 722a10cf76eSAxel Dörfler } else { 723a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 724a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 725a10cf76eSAxel Dörfler // 1. add a new resolution to list 726a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 727a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 728a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 729a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 730a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 731a10cf76eSAxel Dörfler // 2. choose nearest resolution 732a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 733a10cf76eSAxel Dörfler // 3. choose lowest resolution 734a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 735a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 736a10cf76eSAxel Dörfler if (item) 737a10cf76eSAxel Dörfler item->SetMarked(true); 738a10cf76eSAxel Dörfler 739a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 740a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 741a10cf76eSAxel Dörfler } 742a10cf76eSAxel Dörfler 743a10cf76eSAxel Dörfler // mark active combine mode 744a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 745a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 746a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 747a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 748a10cf76eSAxel Dörfler item->SetMarked(true); 749a10cf76eSAxel Dörfler break; 750a10cf76eSAxel Dörfler } 751a10cf76eSAxel Dörfler } 752a10cf76eSAxel Dörfler 753a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 754a10cf76eSAxel Dörfler 7551fc4cb1fSAxel Dörfler for (int32 i = 0, index = 0; i < kColorSpaceCount; i++) { 7561fc4cb1fSAxel Dörfler if ((fSupportedColorSpaces & (1 << i)) == 0) 7571fc4cb1fSAxel Dörfler continue; 7581fc4cb1fSAxel Dörfler 7591fc4cb1fSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 7601fc4cb1fSAxel Dörfler item = fColorsMenu->ItemAt(index); 761a10cf76eSAxel Dörfler break; 762a10cf76eSAxel Dörfler } 7631fc4cb1fSAxel Dörfler 7641fc4cb1fSAxel Dörfler index++; 765a10cf76eSAxel Dörfler } 766a10cf76eSAxel Dörfler 767a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 768a10cf76eSAxel Dörfler item->SetMarked(true); 769a10cf76eSAxel Dörfler 7701fc4cb1fSAxel Dörfler _UpdateColorLabel(); 7715de171daSAxel Dörfler _UpdateMonitorView(); 7725de171daSAxel Dörfler _UpdateRefreshControl(); 773a10cf76eSAxel Dörfler 7745de171daSAxel Dörfler _CheckApplyEnabled(); 775a10cf76eSAxel Dörfler } 776a10cf76eSAxel Dörfler 777a10cf76eSAxel Dörfler 77812580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 779a10cf76eSAxel Dörfler void 7805de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 781a10cf76eSAxel Dörfler { 78212580984SAxel Dörfler // Usually, this function gets called after a mode 783a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 784a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 785a10cf76eSAxel Dörfler // what kind of mode we actually got 786a10cf76eSAxel Dörfler fScreenMode.Get(fActive); 787a10cf76eSAxel Dörfler fSelected = fActive; 788a10cf76eSAxel Dörfler 78912966d04SAxel Dörfler _UpdateMonitor(); 7905de171daSAxel Dörfler _UpdateControls(); 791a10cf76eSAxel Dörfler } 792a10cf76eSAxel Dörfler 793a10cf76eSAxel Dörfler 794a10cf76eSAxel Dörfler void 795b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons() 796b21d610eSAxel Dörfler { 797b21d610eSAxel Dörfler uint32 columns; 798b21d610eSAxel Dörfler uint32 rows; 799b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 800b21d610eSAxel Dörfler 801b21d610eSAxel Dörfler char text[32]; 802b21d610eSAxel Dörfler snprintf(text, sizeof(text), "%ld", columns); 803b21d610eSAxel Dörfler fColumnsControl->SetText(text); 804b21d610eSAxel Dörfler 805b21d610eSAxel Dörfler snprintf(text, sizeof(text), "%ld", rows); 806b21d610eSAxel Dörfler fRowsControl->SetText(text); 807b21d610eSAxel Dörfler 808b21d610eSAxel Dörfler _GetColumnRowButton(true, false)->SetEnabled(columns != 1 && rows != 32); 809b21d610eSAxel Dörfler _GetColumnRowButton(true, true)->SetEnabled((columns + 1) * rows < 32); 810b21d610eSAxel Dörfler _GetColumnRowButton(false, false)->SetEnabled(rows != 1 && columns != 32); 811b21d610eSAxel Dörfler _GetColumnRowButton(false, true)->SetEnabled(columns * (rows + 1) < 32); 812b21d610eSAxel Dörfler } 813b21d610eSAxel Dörfler 814b21d610eSAxel Dörfler 815b21d610eSAxel Dörfler void 816a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 817a10cf76eSAxel Dörfler { 818a10cf76eSAxel Dörfler // move window on screen, if necessary 819a10cf76eSAxel Dörfler if (frame.right <= Frame().right 820a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 821a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 822a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 823a10cf76eSAxel Dörfler } 824a10cf76eSAxel Dörfler } 825a10cf76eSAxel Dörfler 826a10cf76eSAxel Dörfler 827a10cf76eSAxel Dörfler void 828a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 829a10cf76eSAxel Dörfler { 830abc649b8SWaldemar Kornewald fScreenMode.GetOriginalMode(fOriginal, workspace); 8315de171daSAxel Dörfler _UpdateActiveMode(); 832a10cf76eSAxel Dörfler 8336edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 8346edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 835a10cf76eSAxel Dörfler } 836a10cf76eSAxel Dörfler 837a10cf76eSAxel Dörfler 838a10cf76eSAxel Dörfler void 839a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 840a10cf76eSAxel Dörfler { 841a10cf76eSAxel Dörfler switch (message->what) { 842a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 8435de171daSAxel Dörfler _CheckApplyEnabled(); 844a10cf76eSAxel Dörfler break; 845a10cf76eSAxel Dörfler 846b21d610eSAxel Dörfler case kMsgWorkspaceLayoutChanged: 847a10cf76eSAxel Dörfler { 848b21d610eSAxel Dörfler int32 deltaX = 0; 849b21d610eSAxel Dörfler int32 deltaY = 0; 850b21d610eSAxel Dörfler message->FindInt32("delta_x", &deltaX); 851b21d610eSAxel Dörfler message->FindInt32("delta_y", &deltaY); 852b21d610eSAxel Dörfler 853b21d610eSAxel Dörfler if (deltaX == 0 && deltaY == 0) 854b21d610eSAxel Dörfler break; 855b21d610eSAxel Dörfler 856b21d610eSAxel Dörfler uint32 newColumns; 857b21d610eSAxel Dörfler uint32 newRows; 858b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&newColumns, &newRows); 859b21d610eSAxel Dörfler 860b21d610eSAxel Dörfler newColumns += deltaX; 861b21d610eSAxel Dörfler newRows += deltaY; 862b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, newRows); 863b21d610eSAxel Dörfler 864b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 8655de171daSAxel Dörfler _CheckApplyEnabled(); 866b21d610eSAxel Dörfler break; 867abc649b8SWaldemar Kornewald } 868b21d610eSAxel Dörfler 869b21d610eSAxel Dörfler case kMsgWorkspaceColumnsChanged: 870b21d610eSAxel Dörfler { 871b21d610eSAxel Dörfler uint32 newColumns = strtoul(fColumnsControl->Text(), NULL, 10); 872b21d610eSAxel Dörfler 873b21d610eSAxel Dörfler uint32 rows; 874b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(NULL, &rows); 875b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(newColumns, rows); 876b21d610eSAxel Dörfler 877b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 878b21d610eSAxel Dörfler _CheckApplyEnabled(); 879b21d610eSAxel Dörfler break; 880b21d610eSAxel Dörfler } 881b21d610eSAxel Dörfler 882b21d610eSAxel Dörfler case kMsgWorkspaceRowsChanged: 883b21d610eSAxel Dörfler { 884b21d610eSAxel Dörfler uint32 newRows = strtoul(fRowsControl->Text(), NULL, 10); 885b21d610eSAxel Dörfler 886b21d610eSAxel Dörfler uint32 columns; 887b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, NULL); 888b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(columns, newRows); 889b21d610eSAxel Dörfler 890b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 891b21d610eSAxel Dörfler _CheckApplyEnabled(); 892a10cf76eSAxel Dörfler break; 893a10cf76eSAxel Dörfler } 894a10cf76eSAxel Dörfler 895a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 896a10cf76eSAxel Dörfler { 897a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 898a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 899a10cf76eSAxel Dörfler 9005de171daSAxel Dörfler _CheckColorMenu(); 9015de171daSAxel Dörfler _CheckRefreshMenu(); 902a10cf76eSAxel Dörfler 9035de171daSAxel Dörfler _UpdateMonitorView(); 9045de171daSAxel Dörfler _UpdateRefreshControl(); 905a10cf76eSAxel Dörfler 9065de171daSAxel Dörfler _CheckApplyEnabled(); 907a10cf76eSAxel Dörfler break; 908a10cf76eSAxel Dörfler } 909a10cf76eSAxel Dörfler 910a10cf76eSAxel Dörfler case POP_COLORS_MSG: 911a10cf76eSAxel Dörfler { 9121fc4cb1fSAxel Dörfler int32 space; 9131fc4cb1fSAxel Dörfler if (message->FindInt32("space", &space) != B_OK) 9141fc4cb1fSAxel Dörfler break; 915a10cf76eSAxel Dörfler 9161fc4cb1fSAxel Dörfler int32 index; 9171fc4cb1fSAxel Dörfler if (message->FindInt32("index", &index) == B_OK 9181fc4cb1fSAxel Dörfler && fColorsMenu->ItemAt(index) != NULL) 9191fc4cb1fSAxel Dörfler fUserSelectedColorSpace = fColorsMenu->ItemAt(index); 9201fc4cb1fSAxel Dörfler 9211fc4cb1fSAxel Dörfler fSelected.space = (color_space)space; 9221fc4cb1fSAxel Dörfler _UpdateColorLabel(); 923a10cf76eSAxel Dörfler 9245de171daSAxel Dörfler _CheckApplyEnabled(); 925a10cf76eSAxel Dörfler break; 926a10cf76eSAxel Dörfler } 927a10cf76eSAxel Dörfler 928a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 929a40498e2SWaldemar Kornewald { 930a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 931a10cf76eSAxel Dörfler fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS); 9321fc4cb1fSAxel Dörfler // revert "Other…" label - it might have a refresh rate prefix 933a10cf76eSAxel Dörfler 9345de171daSAxel Dörfler _CheckApplyEnabled(); 935a10cf76eSAxel Dörfler break; 936a40498e2SWaldemar Kornewald } 937a10cf76eSAxel Dörfler 938a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 939a10cf76eSAxel Dörfler { 94029e8a73aSAxel Dörfler // make sure menu shows something useful 9415de171daSAxel Dörfler _UpdateRefreshControl(); 942a10cf76eSAxel Dörfler 94329e8a73aSAxel Dörfler float min = 0, max = 999; 94429e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 94529e8a73aSAxel Dörfler if (min < gMinRefresh) 94629e8a73aSAxel Dörfler min = gMinRefresh; 94729e8a73aSAxel Dörfler if (max > gMaxRefresh) 94829e8a73aSAxel Dörfler max = gMaxRefresh; 94929e8a73aSAxel Dörfler 95070a2b1b5SAxel Dörfler monitor_info info; 95170a2b1b5SAxel Dörfler if (fScreenMode.GetMonitorInfo(info) == B_OK) { 95270a2b1b5SAxel Dörfler min = max_c(info.min_vertical_frequency, min); 95370a2b1b5SAxel Dörfler max = min_c(info.max_vertical_frequency, max); 95470a2b1b5SAxel Dörfler } 95570a2b1b5SAxel Dörfler 956c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 95770a2b1b5SAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, 95870a2b1b5SAxel Dörfler min, max); 959a10cf76eSAxel Dörfler fRefreshWindow->Show(); 960a10cf76eSAxel Dörfler break; 961a10cf76eSAxel Dörfler } 962a10cf76eSAxel Dörfler 963a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 964a10cf76eSAxel Dörfler { 965a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 966a10cf76eSAxel Dörfler // select the refresh rate chosen 967a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 968a10cf76eSAxel Dörfler 9695de171daSAxel Dörfler _UpdateRefreshControl(); 9705de171daSAxel Dörfler _CheckApplyEnabled(); 971a10cf76eSAxel Dörfler break; 972a10cf76eSAxel Dörfler } 973a10cf76eSAxel Dörfler 974a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 975a10cf76eSAxel Dörfler { 976a10cf76eSAxel Dörfler // new combine mode has bee chosen 977a10cf76eSAxel Dörfler int32 mode; 978a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 979a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 980a10cf76eSAxel Dörfler 9815de171daSAxel Dörfler _CheckResolutionMenu(); 9825de171daSAxel Dörfler _CheckApplyEnabled(); 983a10cf76eSAxel Dörfler break; 984a10cf76eSAxel Dörfler } 985a10cf76eSAxel Dörfler 986a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 987a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 9885de171daSAxel Dörfler _CheckApplyEnabled(); 989a10cf76eSAxel Dörfler break; 990a10cf76eSAxel Dörfler 991a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 992a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 9935de171daSAxel Dörfler _CheckApplyEnabled(); 994a10cf76eSAxel Dörfler break; 995a10cf76eSAxel Dörfler 996a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 997a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 9985de171daSAxel Dörfler _CheckApplyEnabled(); 999a10cf76eSAxel Dörfler break; 1000a10cf76eSAxel Dörfler 1001df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 10026f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 10036f095d6aSRyan Leavengood app_info info; 10046f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 10056f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 10066f095d6aSRyan Leavengood } 1007df3f5bacSStephan Aßmus break; 1008df3f5bacSStephan Aßmus 1009a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 1010a10cf76eSAxel Dörfler { 10114be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 1012a10cf76eSAxel Dörfler fSelected.width = 640; 1013a10cf76eSAxel Dörfler fSelected.height = 480; 1014a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 1015a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 1016a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 1017a10cf76eSAxel Dörfler fSelected.swap_displays = false; 1018a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 1019a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 1020a10cf76eSAxel Dörfler 1021b21d610eSAxel Dörfler // TODO: workspace defaults 1022abc649b8SWaldemar Kornewald 10235de171daSAxel Dörfler _UpdateControls(); 1024a10cf76eSAxel Dörfler break; 1025a10cf76eSAxel Dörfler } 1026a10cf76eSAxel Dörfler 102710e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 102861c5c89bSAxel Dörfler fUndoScreenMode.Revert(); 10295de171daSAxel Dörfler _UpdateActiveMode(); 1030abc649b8SWaldemar Kornewald break; 1031abc649b8SWaldemar Kornewald 1032abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 1033abc649b8SWaldemar Kornewald { 1034abc649b8SWaldemar Kornewald fModified = false; 1035199893c3SAxel Dörfler fBootWorkspaceApplied = false; 1036abc649b8SWaldemar Kornewald 1037b21d610eSAxel Dörfler // ScreenMode::Revert() assumes that we first set the correct 1038b21d610eSAxel Dörfler // number of workspaces 1039b21d610eSAxel Dörfler 1040b21d610eSAxel Dörfler BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns, 1041b21d610eSAxel Dörfler fOriginalWorkspacesRows); 1042b21d610eSAxel Dörfler _UpdateWorkspaceButtons(); 1043b21d610eSAxel Dörfler 1044a10cf76eSAxel Dörfler fScreenMode.Revert(); 10455de171daSAxel Dörfler _UpdateActiveMode(); 1046a10cf76eSAxel Dörfler break; 1047abc649b8SWaldemar Kornewald } 1048a10cf76eSAxel Dörfler 1049a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 10505de171daSAxel Dörfler _Apply(); 1051a10cf76eSAxel Dörfler break; 1052a10cf76eSAxel Dörfler 1053abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 1054abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 1055abc649b8SWaldemar Kornewald fModified = true; 10565de171daSAxel Dörfler _UpdateActiveMode(); 1057a10cf76eSAxel Dörfler break; 1058a10cf76eSAxel Dörfler 1059a10cf76eSAxel Dörfler default: 1060a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 1061a10cf76eSAxel Dörfler break; 1062a10cf76eSAxel Dörfler } 1063a10cf76eSAxel Dörfler } 1064a10cf76eSAxel Dörfler 1065a10cf76eSAxel Dörfler 106612580984SAxel Dörfler status_t 106712580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 106812580984SAxel Dörfler { 106912580984SAxel Dörfler BPath path; 107012580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 107112580984SAxel Dörfler if (status < B_OK) 107212580984SAxel Dörfler return status; 107312580984SAxel Dörfler 107412580984SAxel Dörfler path.Append("kernel/drivers"); 107512580984SAxel Dörfler status = create_directory(path.Path(), 0755); 107612580984SAxel Dörfler if (status < B_OK) 107712580984SAxel Dörfler return status; 107812580984SAxel Dörfler 107912580984SAxel Dörfler path.Append("vesa"); 108012580984SAxel Dörfler BFile file; 108112580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 108212580984SAxel Dörfler if (status < B_OK) 108312580984SAxel Dörfler return status; 108412580984SAxel Dörfler 108512580984SAxel Dörfler char buffer[256]; 108612580984SAxel Dörfler snprintf(buffer, sizeof(buffer), "mode %ld %ld %ld\n", 108712580984SAxel Dörfler mode.width, mode.height, mode.BitsPerPixel()); 108812580984SAxel Dörfler 108912580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 109012580984SAxel Dörfler if (bytesWritten < B_OK) 109112580984SAxel Dörfler return bytesWritten; 109212580984SAxel Dörfler 109312580984SAxel Dörfler return B_OK; 109412580984SAxel Dörfler } 109512580984SAxel Dörfler 109612580984SAxel Dörfler 1097b21d610eSAxel Dörfler BButton* 1098b21d610eSAxel Dörfler ScreenWindow::_CreateColumnRowButton(bool columns, bool plus) 1099b21d610eSAxel Dörfler { 1100b21d610eSAxel Dörfler BMessage* message = new BMessage(kMsgWorkspaceLayoutChanged); 1101b21d610eSAxel Dörfler message->AddInt32("delta_x", columns ? (plus ? 1 : -1) : 0); 1102b21d610eSAxel Dörfler message->AddInt32("delta_y", !columns ? (plus ? 1 : -1) : 0); 1103b21d610eSAxel Dörfler 1104b21d610eSAxel Dörfler BButton* button = new BButton(plus ? "+" : "-", message); 1105b21d610eSAxel Dörfler button->SetFontSize(be_plain_font->Size() * 0.9); 1106b21d610eSAxel Dörfler 1107b21d610eSAxel Dörfler BSize size = button->MinSize(); 1108b21d610eSAxel Dörfler size.width = button->StringWidth("+") + 16; 1109b21d610eSAxel Dörfler button->SetExplicitMinSize(size); 1110b21d610eSAxel Dörfler button->SetExplicitMaxSize(size); 1111b21d610eSAxel Dörfler 1112b21d610eSAxel Dörfler fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)] = button; 1113b21d610eSAxel Dörfler return button; 1114b21d610eSAxel Dörfler } 1115b21d610eSAxel Dörfler 1116b21d610eSAxel Dörfler 1117b21d610eSAxel Dörfler BButton* 1118b21d610eSAxel Dörfler ScreenWindow::_GetColumnRowButton(bool columns, bool plus) 1119b21d610eSAxel Dörfler { 1120b21d610eSAxel Dörfler return fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)]; 1121b21d610eSAxel Dörfler } 1122b21d610eSAxel Dörfler 1123b21d610eSAxel Dörfler 1124a10cf76eSAxel Dörfler void 11251fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces() 11261fc4cb1fSAxel Dörfler { 11271fc4cb1fSAxel Dörfler fSupportedColorSpaces = 0; 11281fc4cb1fSAxel Dörfler 11291fc4cb1fSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 11301fc4cb1fSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 11311fc4cb1fSAxel Dörfler if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) { 11321fc4cb1fSAxel Dörfler fSupportedColorSpaces |= 1 << i; 11331fc4cb1fSAxel Dörfler break; 11341fc4cb1fSAxel Dörfler } 11351fc4cb1fSAxel Dörfler } 11361fc4cb1fSAxel Dörfler } 11371fc4cb1fSAxel Dörfler } 11381fc4cb1fSAxel Dörfler 11391fc4cb1fSAxel Dörfler 11401fc4cb1fSAxel Dörfler void 11415de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1142a10cf76eSAxel Dörfler { 114327c43a2dSRene Gollent fApplyButton->SetEnabled(fSelected != fActive 114427c43a2dSRene Gollent || fAllWorkspacesItem->IsMarked()); 1145b21d610eSAxel Dörfler 1146b21d610eSAxel Dörfler uint32 columns; 1147b21d610eSAxel Dörfler uint32 rows; 1148b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&columns, &rows); 1149b21d610eSAxel Dörfler 1150b21d610eSAxel Dörfler fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns 1151b21d610eSAxel Dörfler || rows != fOriginalWorkspacesRows 11525de171daSAxel Dörfler || fSelected != fOriginal); 1153a10cf76eSAxel Dörfler } 1154a10cf76eSAxel Dörfler 1155a10cf76eSAxel Dörfler 1156a10cf76eSAxel Dörfler void 11575de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1158abc649b8SWaldemar Kornewald { 1159b21d610eSAxel Dörfler BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns, 1160b21d610eSAxel Dörfler &fOriginalWorkspacesRows); 1161b21d610eSAxel Dörfler 1162abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1163abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1164abc649b8SWaldemar Kornewald } 1165abc649b8SWaldemar Kornewald 1166abc649b8SWaldemar Kornewald 1167abc649b8SWaldemar Kornewald void 116812966d04SAxel Dörfler ScreenWindow::_UpdateMonitor() 116912966d04SAxel Dörfler { 117012966d04SAxel Dörfler monitor_info info; 117112966d04SAxel Dörfler float diagonalInches; 117212966d04SAxel Dörfler status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches); 117355030977SAxel Dörfler if (status == B_OK) { 11741a8af605SAxel Dörfler char text[512]; 117566ab1666SAxel Dörfler snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor, 117666ab1666SAxel Dörfler info.name[0] ? " " : "", info.name, diagonalInches); 117712966d04SAxel Dörfler 117812966d04SAxel Dörfler fMonitorInfo->SetText(text); 117912966d04SAxel Dörfler 118012966d04SAxel Dörfler if (fMonitorInfo->IsHidden()) 118112966d04SAxel Dörfler fMonitorInfo->Show(); 118255030977SAxel Dörfler } else { 118355030977SAxel Dörfler if (!fMonitorInfo->IsHidden()) 118455030977SAxel Dörfler fMonitorInfo->Hide(); 118555030977SAxel Dörfler } 1186af8f9c31SAxel Dörfler 118755030977SAxel Dörfler char text[512]; 11881a8af605SAxel Dörfler size_t length = 0; 11891a8af605SAxel Dörfler text[0] = 0; 11901a8af605SAxel Dörfler 119155030977SAxel Dörfler if (status == B_OK) { 1192af8f9c31SAxel Dörfler if (info.min_horizontal_frequency != 0 1193af8f9c31SAxel Dörfler && info.min_vertical_frequency != 0 1194af8f9c31SAxel Dörfler && info.max_pixel_clock != 0) { 11951a8af605SAxel Dörfler length = snprintf(text, sizeof(text), 11969c1a9b92SAdrien Destugues "Horizonal frequency:\t%lu - %lu kHz\n" 11979c1a9b92SAdrien Destugues "Vertical frequency:\t%lu - %lu Hz\n\n" 11989c1a9b92SAdrien Destugues "Maximum pixel clock:\t%g MHz", 11991a8af605SAxel Dörfler info.min_horizontal_frequency, info.max_horizontal_frequency, 12001a8af605SAxel Dörfler info.min_vertical_frequency, info.max_vertical_frequency, 12011a8af605SAxel Dörfler info.max_pixel_clock / 1000.0); 1202af8f9c31SAxel Dörfler } 12031a8af605SAxel Dörfler if (info.serial_number[0] && length < sizeof(text)) { 12041a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 12051a8af605SAxel Dörfler "%sSerial no.: %s", length ? "\n\n" : "", 12061a8af605SAxel Dörfler info.serial_number); 12071a8af605SAxel Dörfler if (info.produced.week != 0 && info.produced.year != 0 12081a8af605SAxel Dörfler && length < sizeof(text)) { 12091a8af605SAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 12101a8af605SAxel Dörfler " (%u/%u)", info.produced.week, info.produced.year); 12111a8af605SAxel Dörfler } 12121a8af605SAxel Dörfler } 121355030977SAxel Dörfler } 121461c5c89bSAxel Dörfler 121561c5c89bSAxel Dörfler // Add info about the graphics device 121661c5c89bSAxel Dörfler 121761c5c89bSAxel Dörfler accelerant_device_info deviceInfo; 121861c5c89bSAxel Dörfler if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK 121961c5c89bSAxel Dörfler && length < sizeof(text)) { 122061c5c89bSAxel Dörfler if (deviceInfo.name[0] && deviceInfo.chipset[0]) { 122161c5c89bSAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 122261c5c89bSAxel Dörfler "%s%s (%s)", length != 0 ? "\n\n" : "", deviceInfo.name, 122361c5c89bSAxel Dörfler deviceInfo.chipset); 122461c5c89bSAxel Dörfler } else if (deviceInfo.name[0] || deviceInfo.chipset[0]) { 122561c5c89bSAxel Dörfler length += snprintf(text + length, sizeof(text) - length, 122661c5c89bSAxel Dörfler "%s%s", length != 0 ? "\n\n" : "", deviceInfo.name[0] 122761c5c89bSAxel Dörfler ? deviceInfo.name : deviceInfo.chipset); 122861c5c89bSAxel Dörfler } 122961c5c89bSAxel Dörfler } 123061c5c89bSAxel Dörfler 12311a8af605SAxel Dörfler if (text[0]) 12321a8af605SAxel Dörfler fMonitorView->SetToolTip(text); 123312966d04SAxel Dörfler } 123412966d04SAxel Dörfler 123512966d04SAxel Dörfler 123612966d04SAxel Dörfler void 12371fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel() 12381fc4cb1fSAxel Dörfler { 12391fc4cb1fSAxel Dörfler BString string; 12409c1a9b92SAdrien Destugues string << fSelected.BitsPerPixel() << " bits/pixel"; 12411fc4cb1fSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 12421fc4cb1fSAxel Dörfler } 12431fc4cb1fSAxel Dörfler 12441fc4cb1fSAxel Dörfler 12451fc4cb1fSAxel Dörfler void 12465de171daSAxel Dörfler ScreenWindow::_Apply() 1247a10cf76eSAxel Dörfler { 1248abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 124961c5c89bSAxel Dörfler fUndoScreenMode.UpdateOriginalModes(); 125061c5c89bSAxel Dörfler 125107184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 125207184a9eSAxel Dörfler if (status == B_OK) { 1253abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1254abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1255abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1256abc649b8SWaldemar Kornewald display_mode newMode; 1257abc649b8SWaldemar Kornewald BScreen screen(this); 1258abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1259abc649b8SWaldemar Kornewald 1260abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1261abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 1262abc649b8SWaldemar Kornewald for (int32 i = 0; i < count_workspaces(); i++) { 1263abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1264abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1265abc649b8SWaldemar Kornewald } 1266199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1267199893c3SAxel Dörfler } else { 1268199893c3SAxel Dörfler if (current_workspace() == 0) 1269199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1270abc649b8SWaldemar Kornewald } 1271abc649b8SWaldemar Kornewald 1272a10cf76eSAxel Dörfler fActive = fSelected; 1273a10cf76eSAxel Dörfler 1274abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 1275a10cf76eSAxel Dörfler BWindow* window = new AlertWindow(this); 1276a10cf76eSAxel Dörfler window->Show(); 127707184a9eSAxel Dörfler } else { 127807184a9eSAxel Dörfler char message[256]; 127907184a9eSAxel Dörfler snprintf(message, sizeof(message), 128007184a9eSAxel Dörfler "The screen mode could not be set:\n\t%s\n", screen_errors(status)); 12819c1a9b92SAdrien Destugues BAlert* alert = new BAlert("Screen Alert", message, "OK", NULL, NULL, 128207184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 128307184a9eSAxel Dörfler alert->Go(); 1284a10cf76eSAxel Dörfler } 128507184a9eSAxel Dörfler } 128607184a9eSAxel Dörfler 1287