xref: /haiku/src/preferences/screen/ScreenWindow.cpp (revision 7eab6b486ebadb54ca3c306601f4b04dd92359fa)
1a10cf76eSAxel Dörfler /*
28bf216d6SAxel Dörfler  * Copyright 2001-2015 Haiku, Inc. All rights reserved.
3a10cf76eSAxel Dörfler  * Distributed under the terms of the MIT License.
4a10cf76eSAxel Dörfler  *
5a10cf76eSAxel Dörfler  * Authors:
6e1c88201SJohn Scipione  *		Stephan Aßmus, superstippi@gmx.de
7a10cf76eSAxel Dörfler  *		Andrew Bachmann
8e1c88201SJohn Scipione  *		Stefano Ceccherini, burton666@libero.it
9e1c88201SJohn Scipione  *		Alexandre Deckner, alex@zappotek.com
10e1c88201SJohn Scipione  *		Axel Dörfler, axeld@pinc-software.de
117e44de36SRene Gollent  *		Rene Gollent, rene@gollent.com
12a10cf76eSAxel Dörfler  *		Thomas Kurschel
13e1c88201SJohn Scipione  *		Rafael Romo
14e1c88201SJohn Scipione  *		John Scipione, jscipione@gmail.com
15a10cf76eSAxel Dörfler  */
16a10cf76eSAxel Dörfler 
17a10cf76eSAxel Dörfler 
18b21d610eSAxel Dörfler #include "ScreenWindow.h"
19b21d610eSAxel Dörfler 
20b21d610eSAxel Dörfler #include <stdio.h>
21b21d610eSAxel Dörfler #include <stdlib.h>
223aeed660SJérôme Duval #include <strings.h>
23b21d610eSAxel Dörfler 
24b21d610eSAxel Dörfler #include <Alert.h>
25b21d610eSAxel Dörfler #include <Application.h>
26b21d610eSAxel Dörfler #include <Box.h>
27b21d610eSAxel Dörfler #include <Button.h>
28c9e8f97aSAdrien Destugues #include <Catalog.h>
29e1c88201SJohn Scipione #include <ControlLook.h>
30b21d610eSAxel Dörfler #include <Directory.h>
31b21d610eSAxel Dörfler #include <File.h>
32b21d610eSAxel Dörfler #include <FindDirectory.h>
33b21d610eSAxel Dörfler #include <InterfaceDefs.h>
34b21d610eSAxel Dörfler #include <LayoutBuilder.h>
35b21d610eSAxel Dörfler #include <MenuBar.h>
36b21d610eSAxel Dörfler #include <MenuField.h>
3728d2323aSDaniel Martin #include <MenuItem.h>
38b21d610eSAxel Dörfler #include <Messenger.h>
39b21d610eSAxel Dörfler #include <Path.h>
40b21d610eSAxel Dörfler #include <PopUpMenu.h>
4128d2323aSDaniel Martin #include <Roster.h>
42b21d610eSAxel Dörfler #include <Screen.h>
43e1c88201SJohn Scipione #include <SpaceLayoutItem.h>
44a3fa81bdSJohn Scipione #include <Spinner.h>
45b21d610eSAxel Dörfler #include <String.h>
46b21d610eSAxel Dörfler #include <StringView.h>
47b21d610eSAxel Dörfler #include <Window.h>
48b21d610eSAxel Dörfler 
49b21d610eSAxel Dörfler #include <InterfacePrivate.h>
50b21d610eSAxel Dörfler 
51a10cf76eSAxel Dörfler #include "AlertWindow.h"
52a10cf76eSAxel Dörfler #include "Constants.h"
53a10cf76eSAxel Dörfler #include "RefreshWindow.h"
54a10cf76eSAxel Dörfler #include "MonitorView.h"
55a10cf76eSAxel Dörfler #include "ScreenSettings.h"
56a10cf76eSAxel Dörfler #include "Utility.h"
57a10cf76eSAxel Dörfler 
58a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant.
59a10cf76eSAxel Dörfler  * It's a solution that works with the current BeOS interface that Haiku
60a10cf76eSAxel Dörfler  * adopted.
61a10cf76eSAxel Dörfler  * However, it's not a nice and clean solution. Don't use this header in any
62a10cf76eSAxel Dörfler  * application if you can avoid it. No other driver is using this, or should
63a10cf76eSAxel Dörfler  * be using this.
64a10cf76eSAxel Dörfler  * It will be replaced as soon as we introduce an updated accelerant interface
65a10cf76eSAxel Dörfler  * which may even happen before R1 hits the streets.
66a10cf76eSAxel Dörfler  */
67a10cf76eSAxel Dörfler #include "multimon.h"	// the usual: DANGER WILL, ROBINSON!
68a10cf76eSAxel Dörfler 
69a10cf76eSAxel Dörfler 
70546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
71546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Screen"
72c9e8f97aSAdrien Destugues 
73c9e8f97aSAdrien Destugues 
7475c92c56SRyan Leavengood const char* kBackgroundsSignature = "application/x-vnd.Haiku-Backgrounds";
75c5d80d47SAxel Dörfler 
76a10cf76eSAxel Dörfler // list of officially supported colour spaces
77a10cf76eSAxel Dörfler static const struct {
78a10cf76eSAxel Dörfler 	color_space	space;
79a10cf76eSAxel Dörfler 	int32		bits_per_pixel;
80a10cf76eSAxel Dörfler 	const char*	label;
81a10cf76eSAxel Dörfler } kColorSpaces[] = {
8226747978SAdrien Destugues 	{ B_CMAP8, 8, B_TRANSLATE("8 bits/pixel, 256 colors") },
83c9e8f97aSAdrien Destugues 	{ B_RGB15, 15, B_TRANSLATE("15 bits/pixel, 32768 colors") },
84c9e8f97aSAdrien Destugues 	{ B_RGB16, 16, B_TRANSLATE("16 bits/pixel, 65536 colors") },
85c9e8f97aSAdrien Destugues 	{ B_RGB24, 24, B_TRANSLATE("24 bits/pixel, 16 Million colors") },
86c9e8f97aSAdrien Destugues 	{ B_RGB32, 32, B_TRANSLATE("32 bits/pixel, 16 Million colors") }
87a10cf76eSAxel Dörfler };
8828d2323aSDaniel Martin static const int32 kColorSpaceCount = B_COUNT_OF(kColorSpaces);
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 };
9228d2323aSDaniel Martin static const int32 kRefreshRateCount = B_COUNT_OF(kRefreshRates);
93a10cf76eSAxel Dörfler 
94a10cf76eSAxel Dörfler // list of combine modes
95a10cf76eSAxel Dörfler static const struct {
96a10cf76eSAxel Dörfler 	combine_mode	mode;
97a10cf76eSAxel Dörfler 	const char		*name;
98a10cf76eSAxel Dörfler } kCombineModes[] = {
99c9e8f97aSAdrien Destugues 	{ kCombineDisable, B_TRANSLATE("disable") },
100c9e8f97aSAdrien Destugues 	{ kCombineHorizontally, B_TRANSLATE("horizontally") },
101c9e8f97aSAdrien Destugues 	{ kCombineVertically, B_TRANSLATE("vertically") }
102a10cf76eSAxel Dörfler };
10328d2323aSDaniel Martin static const int32 kCombineModeCount = B_COUNT_OF(kCombineModes);
10429e8a73aSAxel Dörfler 
105a10cf76eSAxel Dörfler 
106a10cf76eSAxel Dörfler static BString
107a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode)
108a10cf76eSAxel Dörfler {
109a10cf76eSAxel Dörfler 	switch (mode) {
110a10cf76eSAxel Dörfler 		case 0:		return "disabled";
111a10cf76eSAxel Dörfler 		case 1:		return "NTSC";
112a10cf76eSAxel Dörfler 		case 2:		return "NTSC Japan";
113a10cf76eSAxel Dörfler 		case 3:		return "PAL BDGHI";
114a10cf76eSAxel Dörfler 		case 4:		return "PAL M";
115a10cf76eSAxel Dörfler 		case 5:		return "PAL N";
116a10cf76eSAxel Dörfler 		case 6:		return "SECAM";
117a10cf76eSAxel Dörfler 		case 101:	return "NTSC 443";
118a10cf76eSAxel Dörfler 		case 102:	return "PAL 60";
119a10cf76eSAxel Dörfler 		case 103:	return "PAL NC";
120a10cf76eSAxel Dörfler 		default:
121a10cf76eSAxel Dörfler 		{
122a10cf76eSAxel Dörfler 			BString name;
123a10cf76eSAxel Dörfler 			name << "??? (" << mode << ")";
124a10cf76eSAxel Dörfler 
125a10cf76eSAxel Dörfler 			return name;
126a10cf76eSAxel Dörfler 		}
127a10cf76eSAxel Dörfler 	}
128a10cf76eSAxel Dörfler }
129a10cf76eSAxel Dörfler 
130a10cf76eSAxel Dörfler 
131a10cf76eSAxel Dörfler static void
132a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string)
133a10cf76eSAxel Dörfler {
1343961af9fSHumdinger 	string.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32,
1353961af9fSHumdinger 			"The '×' is the Unicode multiplication sign U+00D7"),
1363961af9fSHumdinger 			mode.width, 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 
167a3fa81bdSJohn Scipione //	#pragma mark - ScreenWindow
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 
214ef046e3bSJohn Scipione 	fScreenBox = new BBox("screen box");
215ef046e3bSJohn Scipione 	BGroupView* groupView = new BGroupView(B_VERTICAL, B_USE_SMALL_SPACING);
216ef046e3bSJohn Scipione 	fScreenBox->AddChild(groupView);
217ef046e3bSJohn Scipione 	fScreenBox->SetLabel("placeholder");
218ef046e3bSJohn Scipione 		// Needed for layouting, will be replaced with screen name/size
219ef046e3bSJohn Scipione 	groupView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING,
220ef046e3bSJohn Scipione 		B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
221a10cf76eSAxel Dörfler 
222ef046e3bSJohn Scipione 	fDeviceInfo = new BStringView("device info", "");
2238b46ee25SAdrien Destugues 	fDeviceInfo->SetAlignment(B_ALIGN_CENTER);
224ef046e3bSJohn Scipione 	groupView->AddChild(fDeviceInfo);
2258b46ee25SAdrien Destugues 
2268bf216d6SAxel Dörfler 	float scaling = std::max(1.0f, be_plain_font->Size() / 12.0f);
2278bf216d6SAxel Dörfler 	fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0 * scaling,
2288bf216d6SAxel Dörfler 			80.0 * scaling), "monitor", screen.Frame().IntegerWidth() + 1,
229c9e8f97aSAdrien Destugues 		screen.Frame().IntegerHeight() + 1);
230ef046e3bSJohn Scipione 	fMonitorView->SetToolTip(B_TRANSLATE("Set background" B_UTF8_ELLIPSIS));
231ef046e3bSJohn Scipione 	groupView->AddChild(fMonitorView);
2325a78744bSAxel Dörfler 
233ef046e3bSJohn Scipione 	// brightness slider
234ef046e3bSJohn Scipione 	fBrightnessSlider = new BSlider("brightness", B_TRANSLATE("Brightness:"),
235ef046e3bSJohn Scipione 		NULL, 0, 255, B_HORIZONTAL);
236ef046e3bSJohn Scipione 	groupView->AddChild(fBrightnessSlider);
237ef046e3bSJohn Scipione 
238ef046e3bSJohn Scipione 	if (screen.GetBrightness(&fOriginalBrightness) == B_OK) {
239ef046e3bSJohn Scipione 		fBrightnessSlider->SetModificationMessage(
240ef046e3bSJohn Scipione 			new BMessage(SLIDER_BRIGHTNESS_MSG));
241ef046e3bSJohn Scipione 		fBrightnessSlider->SetValue(fOriginalBrightness * 255);
242ef046e3bSJohn Scipione 	} else {
243ef046e3bSJohn Scipione 		// The driver does not support changing the brightness,
244ef046e3bSJohn Scipione 		// so hide the slider
245ef046e3bSJohn Scipione 		fBrightnessSlider->Hide();
246ef046e3bSJohn Scipione 		fOriginalBrightness = -1;
247ef046e3bSJohn Scipione 	}
248ef046e3bSJohn Scipione 
249ef046e3bSJohn Scipione 	// box on the left below the screen box with workspaces
250ef046e3bSJohn Scipione 
251ef046e3bSJohn Scipione 	BBox* workspacesBox = new BBox("workspaces box");
252ef046e3bSJohn Scipione 	workspacesBox->SetLabel(B_TRANSLATE("Workspaces"));
253ef046e3bSJohn Scipione 
254ef046e3bSJohn Scipione 	BGroupLayout* workspacesLayout = new BGroupLayout(B_VERTICAL);
255ef046e3bSJohn Scipione 	workspacesLayout->SetInsets(B_USE_DEFAULT_SPACING,
256ef046e3bSJohn Scipione 		be_control_look->DefaultItemSpacing() * 2, B_USE_DEFAULT_SPACING,
257ef046e3bSJohn Scipione 		B_USE_DEFAULT_SPACING);
258ef046e3bSJohn Scipione 	workspacesBox->SetLayout(workspacesLayout);
259e1c88201SJohn Scipione 
260a3fa81bdSJohn Scipione 	fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"),
261b21d610eSAxel Dörfler 		new BMessage(kMsgWorkspaceColumnsChanged));
262a3fa81bdSJohn Scipione 	fColumnsControl->SetAlignment(B_ALIGN_RIGHT);
263a3fa81bdSJohn Scipione 	fColumnsControl->SetRange(1, 32);
264b21d610eSAxel Dörfler 
265a3fa81bdSJohn Scipione 	fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"),
266a3fa81bdSJohn Scipione 		new BMessage(kMsgWorkspaceRowsChanged));
267a3fa81bdSJohn Scipione 	fRowsControl->SetAlignment(B_ALIGN_RIGHT);
268a3fa81bdSJohn Scipione 	fRowsControl->SetRange(1, 32);
269a3fa81bdSJohn Scipione 
270a3fa81bdSJohn Scipione 	uint32 columns;
271a3fa81bdSJohn Scipione 	uint32 rows;
272a3fa81bdSJohn Scipione 	BPrivate::get_workspaces_layout(&columns, &rows);
273a3fa81bdSJohn Scipione 	fColumnsControl->SetValue(columns);
274a3fa81bdSJohn Scipione 	fRowsControl->SetValue(rows);
275a3fa81bdSJohn Scipione 
276ef046e3bSJohn Scipione 	workspacesBox->AddChild(BLayoutBuilder::Group<>()
277e1c88201SJohn Scipione 		.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
2784dcc9761SJohn Scipione 			.AddGroup(B_HORIZONTAL, 0)
2794dcc9761SJohn Scipione 				.AddGlue()
280a3fa81bdSJohn Scipione 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
281e1c88201SJohn Scipione 					// columns
282e1c88201SJohn Scipione 					.Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0)
283a3fa81bdSJohn Scipione 					.Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0)
284e1c88201SJohn Scipione 					// rows
285e1c88201SJohn Scipione 					.Add(fRowsControl->CreateLabelLayoutItem(), 0, 1)
286a3fa81bdSJohn Scipione 					.Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1)
287b21d610eSAxel Dörfler 					.End()
2884dcc9761SJohn Scipione 				.AddGlue()
2894dcc9761SJohn Scipione 				.End()
29025fd5c7bSAlex Wilson 			.End()
29125fd5c7bSAlex Wilson 		.View());
292b21d610eSAxel Dörfler 
293ef046e3bSJohn Scipione 	// put workspaces slider in a vertical group with a half space above so
294ef046e3bSJohn Scipione 	// if hidden you won't see the extra space.
295ef046e3bSJohn Scipione 	BView* workspacesView = BLayoutBuilder::Group<>(B_VERTICAL, 0)
296ef046e3bSJohn Scipione 		.AddStrut(B_USE_HALF_ITEM_SPACING)
297ef046e3bSJohn Scipione 		.Add(workspacesBox)
298ef046e3bSJohn Scipione 		.View();
299a10cf76eSAxel Dörfler 
300a10cf76eSAxel Dörfler 	// box on the right with screen resolution, etc.
301a10cf76eSAxel Dörfler 
302b21d610eSAxel Dörfler 	BBox* controlsBox = new BBox("controls box");
303b21d610eSAxel Dörfler 	controlsBox->SetLabel(workspaceMenuField);
3046048f541SJohn Scipione 	BGroupView* outerControlsView = new BGroupView(B_VERTICAL);
3056048f541SJohn Scipione 	outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING,
3066048f541SJohn Scipione 		B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
307b21d610eSAxel Dörfler 	controlsBox->AddChild(outerControlsView);
308a10cf76eSAxel Dörfler 
3094c28b3f1SPulkoMandy 	menu_layout layout = B_ITEMS_IN_COLUMN;
310a10cf76eSAxel Dörfler 
3114c28b3f1SPulkoMandy 	// There are modes in the list with the same resolution but different bpp or refresh rates.
3124c28b3f1SPulkoMandy 	// We don't want to take these into account when computing the menu layout, so we need to
3134c28b3f1SPulkoMandy 	// count how many entries we will really have in the menu.
3144c28b3f1SPulkoMandy 	int fullModeCount = fScreenMode.CountModes();
3154c28b3f1SPulkoMandy 	int modeCount = 0;
3164c28b3f1SPulkoMandy 	int index = 0;
31766ab1666SAxel Dörfler 	uint16 maxWidth = 0;
31866ab1666SAxel Dörfler 	uint16 maxHeight = 0;
31966ab1666SAxel Dörfler 	uint16 previousWidth = 0;
32066ab1666SAxel Dörfler 	uint16 previousHeight = 0;
3214c28b3f1SPulkoMandy 	for (int32 i = 0; i < fullModeCount; i++) {
3224c28b3f1SPulkoMandy 		screen_mode mode = fScreenMode.ModeAt(i);
3234c28b3f1SPulkoMandy 
3244c28b3f1SPulkoMandy 		if (mode.width == previousWidth && mode.height == previousHeight)
3254c28b3f1SPulkoMandy 			continue;
3264c28b3f1SPulkoMandy 		modeCount++;
3274c28b3f1SPulkoMandy 		previousWidth = mode.width;
3284c28b3f1SPulkoMandy 		previousHeight = mode.height;
3294c28b3f1SPulkoMandy 		if (maxWidth < mode.width)
3304c28b3f1SPulkoMandy 			maxWidth = mode.width;
3314c28b3f1SPulkoMandy 		if (maxHeight < mode.height)
3324c28b3f1SPulkoMandy 			maxHeight = mode.height;
3334c28b3f1SPulkoMandy 	}
3344c28b3f1SPulkoMandy 
3354c28b3f1SPulkoMandy 	if (modeCount > 16)
3364c28b3f1SPulkoMandy 		layout = B_ITEMS_IN_MATRIX;
3374c28b3f1SPulkoMandy 
3384c28b3f1SPulkoMandy 	fResolutionMenu = new BPopUpMenu("resolution", true, true, layout);
3394c28b3f1SPulkoMandy 
3404c28b3f1SPulkoMandy 	// Compute the size we should allocate to each item in the menu
3414c28b3f1SPulkoMandy 	BRect itemRect;
3424c28b3f1SPulkoMandy 	if (layout == B_ITEMS_IN_MATRIX) {
3434c28b3f1SPulkoMandy 		BFont menuFont;
3444c28b3f1SPulkoMandy 		font_height fontHeight;
3454c28b3f1SPulkoMandy 
3464c28b3f1SPulkoMandy 		fResolutionMenu->GetFont(&menuFont);
3474c28b3f1SPulkoMandy 		menuFont.GetHeight(&fontHeight);
3484c28b3f1SPulkoMandy 		itemRect.left = itemRect.top = 0;
3494c28b3f1SPulkoMandy 		itemRect.bottom = fontHeight.ascent + fontHeight.descent + 4;
3504c28b3f1SPulkoMandy 		itemRect.right = menuFont.StringWidth("99999x99999") + 16;
3514c28b3f1SPulkoMandy 		rows = modeCount / 3 + 1;
3524c28b3f1SPulkoMandy 	}
3534c28b3f1SPulkoMandy 
3544c28b3f1SPulkoMandy 	index = 0;
3554c28b3f1SPulkoMandy 	for (int32 i = 0; i < fullModeCount; i++) {
356a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
357a10cf76eSAxel Dörfler 
358a10cf76eSAxel Dörfler 		if (mode.width == previousWidth && mode.height == previousHeight)
359a10cf76eSAxel Dörfler 			continue;
360a10cf76eSAxel Dörfler 
361a10cf76eSAxel Dörfler 		previousWidth = mode.width;
362a10cf76eSAxel Dörfler 		previousHeight = mode.height;
363a10cf76eSAxel Dörfler 
364a10cf76eSAxel Dörfler 		BMessage* message = new BMessage(POP_RESOLUTION_MSG);
365a10cf76eSAxel Dörfler 		message->AddInt32("width", mode.width);
366a10cf76eSAxel Dörfler 		message->AddInt32("height", mode.height);
367a10cf76eSAxel Dörfler 
368a10cf76eSAxel Dörfler 		BString name;
3693961af9fSHumdinger 		name.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32,
3703961af9fSHumdinger 			"The '×' is the Unicode multiplication sign U+00D7"),
3713961af9fSHumdinger 			mode.width, mode.height);
372a10cf76eSAxel Dörfler 
3734c28b3f1SPulkoMandy 		if (layout == B_ITEMS_IN_COLUMN)
374a10cf76eSAxel Dörfler 			fResolutionMenu->AddItem(new BMenuItem(name.String(), message));
3754c28b3f1SPulkoMandy 		else {
3764c28b3f1SPulkoMandy 			int y = index % rows;
3774c28b3f1SPulkoMandy 			int x = index / rows;
3784c28b3f1SPulkoMandy 			itemRect.OffsetTo(x * itemRect.Width(), y * itemRect.Height());
3794c28b3f1SPulkoMandy 			fResolutionMenu->AddItem(new BMenuItem(name.String(), message), itemRect);
3804c28b3f1SPulkoMandy 		}
3814c28b3f1SPulkoMandy 
3824c28b3f1SPulkoMandy 		index++;
383a10cf76eSAxel Dörfler 	}
384a10cf76eSAxel Dörfler 
38566ab1666SAxel Dörfler 	fMonitorView->SetMaxResolution(maxWidth, maxHeight);
38666ab1666SAxel Dörfler 
387c9e8f97aSAdrien Destugues 	fResolutionField = new BMenuField("ResolutionMenu",
38810dfe897SAxel Dörfler 		B_TRANSLATE("Resolution:"), fResolutionMenu);
3896048f541SJohn Scipione 	fResolutionField->SetAlignment(B_ALIGN_RIGHT);
390a10cf76eSAxel Dörfler 
391551c9f15SSiarzhuk Zharski 	fColorsMenu = new BPopUpMenu("colors", true, false);
392a10cf76eSAxel Dörfler 
393a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
3941fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
3951fc4cb1fSAxel Dörfler 			continue;
3961fc4cb1fSAxel Dörfler 
397a10cf76eSAxel Dörfler 		BMessage* message = new BMessage(POP_COLORS_MSG);
398a10cf76eSAxel Dörfler 		message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
399a10cf76eSAxel Dörfler 		message->AddInt32("space", kColorSpaces[i].space);
400a10cf76eSAxel Dörfler 
4011fc4cb1fSAxel Dörfler 		BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message);
4021fc4cb1fSAxel Dörfler 		if (kColorSpaces[i].space == screen.ColorSpace())
4031fc4cb1fSAxel Dörfler 			fUserSelectedColorSpace = item;
4041fc4cb1fSAxel Dörfler 
4051fc4cb1fSAxel Dörfler 		fColorsMenu->AddItem(item);
406a10cf76eSAxel Dörfler 	}
407a10cf76eSAxel Dörfler 
408c9e8f97aSAdrien Destugues 	fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"),
40910dfe897SAxel Dörfler 		fColorsMenu);
4106048f541SJohn Scipione 	fColorsField->SetAlignment(B_ALIGN_RIGHT);
411a10cf76eSAxel Dörfler 
412551c9f15SSiarzhuk Zharski 	fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
413a10cf76eSAxel Dörfler 
41429e8a73aSAxel Dörfler 	float min, max;
415ec495b30SRene Gollent 	if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) {
416ec495b30SRene Gollent 		// if we couldn't obtain the refresh limits, reset to the default
417ec495b30SRene Gollent 		// range. Constraints from detected monitors will fine-tune this
418ec495b30SRene Gollent 		// later.
419ec495b30SRene Gollent 		min = kRefreshRates[0];
420ec495b30SRene Gollent 		max = kRefreshRates[kRefreshRateCount - 1];
421ec495b30SRene Gollent 	}
422ec495b30SRene Gollent 
423ec495b30SRene Gollent 	if (min == max) {
42429e8a73aSAxel Dörfler 		// This is a special case for drivers that only support a single
42529e8a73aSAxel Dörfler 		// frequency, like the VESA driver
42629e8a73aSAxel Dörfler 		BString name;
4277e44de36SRene Gollent 		refresh_rate_to_string(min, name);
428cf076964SRene Gollent 		BMessage *message = new BMessage(POP_REFRESH_MSG);
429cf076964SRene Gollent 		message->AddFloat("refresh", min);
430cf076964SRene Gollent 		BMenuItem *item = new BMenuItem(name.String(), message);
4310efb8b66SJerome Duval 		fRefreshMenu->AddItem(item);
43229e8a73aSAxel Dörfler 		item->SetEnabled(false);
43329e8a73aSAxel Dörfler 	} else {
43470a2b1b5SAxel Dörfler 		monitor_info info;
43570a2b1b5SAxel Dörfler 		if (fScreenMode.GetMonitorInfo(info) == B_OK) {
43670a2b1b5SAxel Dörfler 			min = max_c(info.min_vertical_frequency, min);
43770a2b1b5SAxel Dörfler 			max = min_c(info.max_vertical_frequency, max);
43870a2b1b5SAxel Dörfler 		}
43970a2b1b5SAxel Dörfler 
440a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kRefreshRateCount; ++i) {
44170a2b1b5SAxel Dörfler 			if (kRefreshRates[i] < min || kRefreshRates[i] > max)
44270a2b1b5SAxel Dörfler 				continue;
44370a2b1b5SAxel Dörfler 
444a10cf76eSAxel Dörfler 			BString name;
445551c9f15SSiarzhuk Zharski 			name << kRefreshRates[i] << " " << B_TRANSLATE("Hz");
446a10cf76eSAxel Dörfler 
4470efb8b66SJerome Duval 			BMessage *message = new BMessage(POP_REFRESH_MSG);
448a10cf76eSAxel Dörfler 			message->AddFloat("refresh", kRefreshRates[i]);
449a10cf76eSAxel Dörfler 
450a10cf76eSAxel Dörfler 			fRefreshMenu->AddItem(new BMenuItem(name.String(), message));
451a10cf76eSAxel Dörfler 		}
452a10cf76eSAxel Dörfler 
453c9e8f97aSAdrien Destugues 		fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS),
4540efb8b66SJerome Duval 			new BMessage(POP_OTHER_REFRESH_MSG));
455a10cf76eSAxel Dörfler 		fRefreshMenu->AddItem(fOtherRefresh);
45629e8a73aSAxel Dörfler 	}
457a10cf76eSAxel Dörfler 
458c9e8f97aSAdrien Destugues 	fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"),
45910dfe897SAxel Dörfler 		fRefreshMenu);
4606048f541SJohn Scipione 	fRefreshField->SetAlignment(B_ALIGN_RIGHT);
461b21d610eSAxel Dörfler 
46212580984SAxel Dörfler 	if (_IsVesa())
46312580984SAxel Dörfler 		fRefreshField->Hide();
464a10cf76eSAxel Dörfler 
465a10cf76eSAxel Dörfler 	// enlarged area for multi-monitor settings
466a10cf76eSAxel Dörfler 	{
467a10cf76eSAxel Dörfler 		bool dummy;
468a10cf76eSAxel Dörfler 		uint32 dummy32;
469a10cf76eSAxel Dörfler 		bool multiMonSupport;
470a10cf76eSAxel Dörfler 		bool useLaptopPanelSupport;
471a10cf76eSAxel Dörfler 		bool tvStandardSupport;
472a10cf76eSAxel Dörfler 
473a10cf76eSAxel Dörfler 		multiMonSupport = TestMultiMonSupport(&screen) == B_OK;
474a10cf76eSAxel Dörfler 		useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK;
475a10cf76eSAxel Dörfler 		tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK;
476a10cf76eSAxel Dörfler 
477a10cf76eSAxel Dörfler 		// even if there is no support, we still create all controls
478a10cf76eSAxel Dörfler 		// to make sure we don't access NULL pointers later on
479a10cf76eSAxel Dörfler 
480551c9f15SSiarzhuk Zharski 		fCombineMenu = new BPopUpMenu("CombineDisplays",
481c9e8f97aSAdrien Destugues 			true, true);
482a10cf76eSAxel Dörfler 
483a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kCombineModeCount; i++) {
4840efb8b66SJerome Duval 			BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG);
485a10cf76eSAxel Dörfler 			message->AddInt32("mode", kCombineModes[i].mode);
486a10cf76eSAxel Dörfler 
487d1516993SAxel Dörfler 			fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name,
488d1516993SAxel Dörfler 				message));
489a10cf76eSAxel Dörfler 		}
490a10cf76eSAxel Dörfler 
491b21d610eSAxel Dörfler 		fCombineField = new BMenuField("CombineMenu",
49210dfe897SAxel Dörfler 			B_TRANSLATE("Combine displays:"), fCombineMenu);
4936048f541SJohn Scipione 		fCombineField->SetAlignment(B_ALIGN_RIGHT);
494a10cf76eSAxel Dörfler 
495a10cf76eSAxel Dörfler 		if (!multiMonSupport)
496df3f5bacSStephan Aßmus 			fCombineField->Hide();
497a10cf76eSAxel Dörfler 
498551c9f15SSiarzhuk Zharski 		fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays",
499c9e8f97aSAdrien Destugues 			true, true);
500a10cf76eSAxel Dörfler 
501a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
5020efb8b66SJerome Duval 		BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG);
503a10cf76eSAxel Dörfler 		message->AddBool("swap", false);
504c9e8f97aSAdrien Destugues 		fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message));
505a10cf76eSAxel Dörfler 
506a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
507a10cf76eSAxel Dörfler 		message->AddBool("swap", true);
508c9e8f97aSAdrien Destugues 		fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message));
509a10cf76eSAxel Dörfler 
510c9e8f97aSAdrien Destugues 		fSwapDisplaysField = new BMenuField("SwapMenu",
51110dfe897SAxel Dörfler 			B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu);
5126048f541SJohn Scipione 		fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT);
513a10cf76eSAxel Dörfler 
514a10cf76eSAxel Dörfler 		if (!multiMonSupport)
515df3f5bacSStephan Aßmus 			fSwapDisplaysField->Hide();
516a10cf76eSAxel Dörfler 
517551c9f15SSiarzhuk Zharski 		fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel",
518c9e8f97aSAdrien Destugues 			true, true);
519a10cf76eSAxel Dörfler 
520a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
521a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
522a10cf76eSAxel Dörfler 		message->AddBool("use", false);
523c9e8f97aSAdrien Destugues 		fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"),
524c9e8f97aSAdrien Destugues 			message));
525a10cf76eSAxel Dörfler 
526a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
527a10cf76eSAxel Dörfler 		message->AddBool("use", true);
528c9e8f97aSAdrien Destugues 		fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"),
529c9e8f97aSAdrien Destugues 			message));
530a10cf76eSAxel Dörfler 
531b21d610eSAxel Dörfler 		fUseLaptopPanelField = new BMenuField("UseLaptopPanel",
53210dfe897SAxel Dörfler 			B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu);
5336048f541SJohn Scipione 		fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT);
534a10cf76eSAxel Dörfler 
535a10cf76eSAxel Dörfler 		if (!useLaptopPanelSupport)
536df3f5bacSStephan Aßmus 			fUseLaptopPanelField->Hide();
537a10cf76eSAxel Dörfler 
538551c9f15SSiarzhuk Zharski 		fTVStandardMenu = new BPopUpMenu("TVStandard", true, true);
539a10cf76eSAxel Dörfler 
540a10cf76eSAxel Dörfler 		// arbitrary limit
541a10cf76eSAxel Dörfler 		uint32 i;
542a10cf76eSAxel Dörfler 		for (i = 0; i < 100; ++i) {
543a10cf76eSAxel Dörfler 			uint32 mode;
544a10cf76eSAxel Dörfler 			if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK)
545a10cf76eSAxel Dörfler 				break;
546a10cf76eSAxel Dörfler 
547a10cf76eSAxel Dörfler 			BString name = tv_standard_to_string(mode);
548a10cf76eSAxel Dörfler 
549a10cf76eSAxel Dörfler 			message = new BMessage(POP_TV_STANDARD_MSG);
550a10cf76eSAxel Dörfler 			message->AddInt32("tv_standard", mode);
551a10cf76eSAxel Dörfler 
552a10cf76eSAxel Dörfler 			fTVStandardMenu->AddItem(new BMenuItem(name.String(), message));
553a10cf76eSAxel Dörfler 		}
554a10cf76eSAxel Dörfler 
555c9e8f97aSAdrien Destugues 		fTVStandardField = new BMenuField("tv standard",
55610dfe897SAxel Dörfler 			B_TRANSLATE("Video format:"), fTVStandardMenu);
557df3f5bacSStephan Aßmus 		fTVStandardField->SetAlignment(B_ALIGN_RIGHT);
558a10cf76eSAxel Dörfler 
559b21d610eSAxel Dörfler 		if (!tvStandardSupport || i == 0)
560df3f5bacSStephan Aßmus 			fTVStandardField->Hide();
561a10cf76eSAxel Dörfler 	}
562a10cf76eSAxel Dörfler 
56325fd5c7bSAlex Wilson 	BLayoutBuilder::Group<>(outerControlsView)
5646048f541SJohn Scipione 		.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
5656048f541SJohn Scipione 			.Add(fResolutionField->CreateLabelLayoutItem(), 0, 0)
5666048f541SJohn Scipione 			.Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0)
5676048f541SJohn Scipione 			.Add(fColorsField->CreateLabelLayoutItem(), 0, 1)
5686048f541SJohn Scipione 			.Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1)
5696048f541SJohn Scipione 			.Add(fRefreshField->CreateLabelLayoutItem(), 0, 2)
5706048f541SJohn Scipione 			.Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2)
5716048f541SJohn Scipione 			.Add(fCombineField->CreateLabelLayoutItem(), 0, 3)
5726048f541SJohn Scipione 			.Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3)
5736048f541SJohn Scipione 			.Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4)
5746048f541SJohn Scipione 			.Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4)
5756048f541SJohn Scipione 			.Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5)
5766048f541SJohn Scipione 			.Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5)
5776048f541SJohn Scipione 			.Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6)
5786048f541SJohn Scipione 			.Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6)
57925fd5c7bSAlex Wilson 		.End();
580df3f5bacSStephan Aßmus 
581abc649b8SWaldemar Kornewald 	// TODO: we don't support getting the screen's preferred settings
582abc649b8SWaldemar Kornewald 	/* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults",
583b21d610eSAxel Dörfler 		new BMessage(BUTTON_DEFAULTS_MSG));*/
584a10cf76eSAxel Dörfler 
585c9e8f97aSAdrien Destugues 	fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"),
586df3f5bacSStephan Aßmus 		new BMessage(BUTTON_APPLY_MSG));
587df3f5bacSStephan Aßmus 	fApplyButton->SetEnabled(false);
58825fd5c7bSAlex Wilson 	BLayoutBuilder::Group<>(outerControlsView)
589b21d610eSAxel Dörfler 		.AddGlue()
59025fd5c7bSAlex Wilson 		.AddGroup(B_HORIZONTAL)
59125fd5c7bSAlex Wilson 			.AddGlue()
59225fd5c7bSAlex Wilson 			.Add(fApplyButton);
593b21d610eSAxel Dörfler 
594c9e8f97aSAdrien Destugues 	fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"),
595b21d610eSAxel Dörfler 		new BMessage(BUTTON_REVERT_MSG));
596b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(false);
597b21d610eSAxel Dörfler 
5984666484fSJohn Scipione 	BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING)
5994666484fSJohn Scipione 		.AddGroup(B_HORIZONTAL)
600a2cb1737SAdrien Destugues 			.AddGroup(B_VERTICAL, 0, 1)
601ef046e3bSJohn Scipione 				.AddStrut(floorf(controlsBox->TopBorderOffset()
602ef046e3bSJohn Scipione 					- fScreenBox->TopBorderOffset()))
603ef046e3bSJohn Scipione 				.Add(fScreenBox)
604ef046e3bSJohn Scipione 				.Add(workspacesView)
60583cc66b3SJohn Scipione 				.End()
6063a2b67b5SAdrien Destugues 			.AddGroup(B_VERTICAL, 0, 1)
607a2cb1737SAdrien Destugues 				.Add(controlsBox, 2)
6083a2b67b5SAdrien Destugues 				.End()
609b21d610eSAxel Dörfler 			.End()
6104666484fSJohn Scipione 		.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
611b21d610eSAxel Dörfler 			.Add(fRevertButton)
6124666484fSJohn Scipione 			.AddGlue()
6134666484fSJohn Scipione 			.End()
614d0ac6099SHumdinger 		.SetInsets(B_USE_WINDOW_SPACING);
615b21d610eSAxel Dörfler 
6165de171daSAxel Dörfler 	_UpdateControls();
61712966d04SAxel Dörfler 	_UpdateMonitor();
6188bf216d6SAxel Dörfler 
6198bf216d6SAxel Dörfler 	MoveOnScreen();
620a10cf76eSAxel Dörfler }
621a10cf76eSAxel Dörfler 
622a10cf76eSAxel Dörfler 
623a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow()
624a10cf76eSAxel Dörfler {
625a10cf76eSAxel Dörfler 	delete fSettings;
626a10cf76eSAxel Dörfler }
627a10cf76eSAxel Dörfler 
628a10cf76eSAxel Dörfler 
629a10cf76eSAxel Dörfler bool
630a10cf76eSAxel Dörfler ScreenWindow::QuitRequested()
631a10cf76eSAxel Dörfler {
632a10cf76eSAxel Dörfler 	fSettings->SetWindowFrame(Frame());
633199893c3SAxel Dörfler 
634199893c3SAxel Dörfler 	// Write mode of workspace 0 (the boot workspace) to the vesa settings file
635199893c3SAxel Dörfler 	screen_mode vesaMode;
636199893c3SAxel Dörfler 	if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) {
637199893c3SAxel Dörfler 		status_t status = _WriteVesaModeFile(vesaMode);
63812580984SAxel Dörfler 		if (status < B_OK) {
639c9e8f97aSAdrien Destugues 			BString warning = B_TRANSLATE("Could not write VESA mode settings"
640c9e8f97aSAdrien Destugues 				" file:\n\t");
64112580984SAxel Dörfler 			warning << strerror(status);
642aed35104SHumdinger 			BAlert* alert = new BAlert(B_TRANSLATE("Warning"),
643aed35104SHumdinger 				warning.String(), B_TRANSLATE("OK"), NULL,
644aed35104SHumdinger 				NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
645aed35104SHumdinger 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
646aed35104SHumdinger 			alert->Go();
64712580984SAxel Dörfler 		}
64812580984SAxel Dörfler 	}
64912580984SAxel Dörfler 
650a10cf76eSAxel Dörfler 	be_app->PostMessage(B_QUIT_REQUESTED);
651a10cf76eSAxel Dörfler 
652a10cf76eSAxel Dörfler 	return BWindow::QuitRequested();
653a10cf76eSAxel Dörfler }
654a10cf76eSAxel Dörfler 
655a10cf76eSAxel Dörfler 
6565de171daSAxel Dörfler /*!	Update resolution list according to combine mode
6571fc4cb1fSAxel Dörfler 	(some resolutions may not be combinable due to memory restrictions).
658a10cf76eSAxel Dörfler */
659a10cf76eSAxel Dörfler void
6605de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu()
661a10cf76eSAxel Dörfler {
662a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fResolutionMenu->CountItems(); i++)
663a10cf76eSAxel Dörfler 		fResolutionMenu->ItemAt(i)->SetEnabled(false);
664a10cf76eSAxel Dörfler 
665a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
666a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
667a10cf76eSAxel Dörfler 		if (mode.combine != fSelected.combine)
668a10cf76eSAxel Dörfler 			continue;
669a10cf76eSAxel Dörfler 
670a10cf76eSAxel Dörfler 		BString name;
6713961af9fSHumdinger 		name.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32,
6723961af9fSHumdinger 			"The '×' is the Unicode multiplication sign U+00D7"),
6733961af9fSHumdinger 			mode.width, mode.height);
674a10cf76eSAxel Dörfler 
675a10cf76eSAxel Dörfler 		BMenuItem *item = fResolutionMenu->FindItem(name.String());
676a10cf76eSAxel Dörfler 		if (item != NULL)
677a10cf76eSAxel Dörfler 			item->SetEnabled(true);
678a10cf76eSAxel Dörfler 	}
679a10cf76eSAxel Dörfler }
680a10cf76eSAxel Dörfler 
681a10cf76eSAxel Dörfler 
6825de171daSAxel Dörfler /*!	Update color and refresh options according to current mode
6835de171daSAxel Dörfler 	(a color space is made active if there is any mode with
6845de171daSAxel Dörfler 	given resolution and this colour space; same applies for
6855de171daSAxel Dörfler 	refresh rate, though "Other…" is always possible)
686a10cf76eSAxel Dörfler */
687a10cf76eSAxel Dörfler void
6885de171daSAxel Dörfler ScreenWindow::_CheckColorMenu()
689a10cf76eSAxel Dörfler {
6901fc4cb1fSAxel Dörfler 	int32 supportsAnything = false;
6911fc4cb1fSAxel Dörfler 	int32 index = 0;
6921fc4cb1fSAxel Dörfler 
693a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
6941fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
6951fc4cb1fSAxel Dörfler 			continue;
6961fc4cb1fSAxel Dörfler 
697a10cf76eSAxel Dörfler 		bool supported = false;
698a10cf76eSAxel Dörfler 
699a10cf76eSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
700a10cf76eSAxel Dörfler 			screen_mode mode = fScreenMode.ModeAt(j);
701a10cf76eSAxel Dörfler 
702a10cf76eSAxel Dörfler 			if (fSelected.width == mode.width
703a10cf76eSAxel Dörfler 				&& fSelected.height == mode.height
7041fc4cb1fSAxel Dörfler 				&& kColorSpaces[i].space == mode.space
705a10cf76eSAxel Dörfler 				&& fSelected.combine == mode.combine) {
7061fc4cb1fSAxel Dörfler 				supportsAnything = true;
707a10cf76eSAxel Dörfler 				supported = true;
708a10cf76eSAxel Dörfler 				break;
709a10cf76eSAxel Dörfler 			}
710a10cf76eSAxel Dörfler 		}
711a10cf76eSAxel Dörfler 
7121fc4cb1fSAxel Dörfler 		BMenuItem* item = fColorsMenu->ItemAt(index++);
713a10cf76eSAxel Dörfler 		if (item)
714a10cf76eSAxel Dörfler 			item->SetEnabled(supported);
715a10cf76eSAxel Dörfler 	}
7161fc4cb1fSAxel Dörfler 
7171fc4cb1fSAxel Dörfler 	fColorsField->SetEnabled(supportsAnything);
7181fc4cb1fSAxel Dörfler 
7191fc4cb1fSAxel Dörfler 	if (!supportsAnything)
7201fc4cb1fSAxel Dörfler 		return;
7211fc4cb1fSAxel Dörfler 
7221fc4cb1fSAxel Dörfler 	// Make sure a valid item is selected
7231fc4cb1fSAxel Dörfler 
7241fc4cb1fSAxel Dörfler 	BMenuItem* item = fColorsMenu->FindMarked();
7251fc4cb1fSAxel Dörfler 	bool changed = false;
7261fc4cb1fSAxel Dörfler 
7271fc4cb1fSAxel Dörfler 	if (item != fUserSelectedColorSpace) {
7281fc4cb1fSAxel Dörfler 		if (fUserSelectedColorSpace != NULL
7291fc4cb1fSAxel Dörfler 			&& fUserSelectedColorSpace->IsEnabled()) {
7301fc4cb1fSAxel Dörfler 			fUserSelectedColorSpace->SetMarked(true);
7311fc4cb1fSAxel Dörfler 			item = fUserSelectedColorSpace;
7321fc4cb1fSAxel Dörfler 			changed = true;
7331fc4cb1fSAxel Dörfler 		}
7341fc4cb1fSAxel Dörfler 	}
7351fc4cb1fSAxel Dörfler 	if (item != NULL && !item->IsEnabled()) {
7361fc4cb1fSAxel Dörfler 		// find the next best item
7371fc4cb1fSAxel Dörfler 		int32 index = fColorsMenu->IndexOf(item);
7381fc4cb1fSAxel Dörfler 		bool found = false;
7391fc4cb1fSAxel Dörfler 
7401fc4cb1fSAxel Dörfler 		for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) {
7411fc4cb1fSAxel Dörfler 			item = fColorsMenu->ItemAt(i);
7421fc4cb1fSAxel Dörfler 			if (item->IsEnabled()) {
7431fc4cb1fSAxel Dörfler 				found = true;
7441fc4cb1fSAxel Dörfler 				break;
7451fc4cb1fSAxel Dörfler 			}
7461fc4cb1fSAxel Dörfler 		}
7471fc4cb1fSAxel Dörfler 		if (!found) {
7481fc4cb1fSAxel Dörfler 			// search backwards as well
7491fc4cb1fSAxel Dörfler 			for (int32 i = index - 1; i >= 0; i--) {
7501fc4cb1fSAxel Dörfler 				item = fColorsMenu->ItemAt(i);
7511fc4cb1fSAxel Dörfler 				if (item->IsEnabled())
7521fc4cb1fSAxel Dörfler 					break;
7531fc4cb1fSAxel Dörfler 			}
7541fc4cb1fSAxel Dörfler 		}
7551fc4cb1fSAxel Dörfler 
7561fc4cb1fSAxel Dörfler 		item->SetMarked(true);
7571fc4cb1fSAxel Dörfler 		changed = true;
7581fc4cb1fSAxel Dörfler 	}
7591fc4cb1fSAxel Dörfler 
7601fc4cb1fSAxel Dörfler 	if (changed) {
7611fc4cb1fSAxel Dörfler 		// Update selected space
7621fc4cb1fSAxel Dörfler 
7631fc4cb1fSAxel Dörfler 		BMessage* message = item->Message();
7641fc4cb1fSAxel Dörfler 		int32 space;
7651fc4cb1fSAxel Dörfler 		if (message->FindInt32("space", &space) == B_OK) {
7661fc4cb1fSAxel Dörfler 			fSelected.space = (color_space)space;
7671fc4cb1fSAxel Dörfler 			_UpdateColorLabel();
7681fc4cb1fSAxel Dörfler 		}
7691fc4cb1fSAxel Dörfler 	}
770a10cf76eSAxel Dörfler }
771a10cf76eSAxel Dörfler 
772a10cf76eSAxel Dörfler 
7735de171daSAxel Dörfler /*!	Enable/disable refresh options according to current mode. */
774a10cf76eSAxel Dörfler void
7755de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu()
776a10cf76eSAxel Dörfler {
77729e8a73aSAxel Dörfler 	float min, max;
77829e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max)
77929e8a73aSAxel Dörfler 		return;
780a10cf76eSAxel Dörfler 
78129e8a73aSAxel Dörfler 	for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) {
78229e8a73aSAxel Dörfler 		BMenuItem* item = fRefreshMenu->ItemAt(i);
78329e8a73aSAxel Dörfler 		BMessage* message = item->Message();
78429e8a73aSAxel Dörfler 		float refresh;
78529e8a73aSAxel Dörfler 		if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK)
78629e8a73aSAxel Dörfler 			item->SetEnabled(refresh >= min && refresh <= max);
787a10cf76eSAxel Dörfler 	}
788a10cf76eSAxel Dörfler }
789a10cf76eSAxel Dörfler 
790a10cf76eSAxel Dörfler 
7915de171daSAxel Dörfler /*!	Activate appropriate menu item according to selected refresh rate */
792a10cf76eSAxel Dörfler void
7935de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl()
794a10cf76eSAxel Dörfler {
795e96dd823SPulkoMandy 	if (isnan(fSelected.refresh)) {
796e96dd823SPulkoMandy 		fRefreshMenu->SetEnabled(false);
797e96dd823SPulkoMandy 		fOtherRefresh->SetLabel(B_TRANSLATE("Unknown"));
798e96dd823SPulkoMandy 		fOtherRefresh->SetMarked(true);
799e96dd823SPulkoMandy 		return;
800e96dd823SPulkoMandy 	} else {
801e96dd823SPulkoMandy 		fRefreshMenu->SetEnabled(true);
802e96dd823SPulkoMandy 	}
803e96dd823SPulkoMandy 
8047e44de36SRene Gollent 	for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) {
8057e44de36SRene Gollent 		BMenuItem* item = fRefreshMenu->ItemAt(i);
8067e44de36SRene Gollent 		if (item->Message()->FindFloat("refresh") == fSelected.refresh) {
807a10cf76eSAxel Dörfler 			item->SetMarked(true);
80826747978SAdrien Destugues 			// "Other" items only contains a refresh rate when active
809122d4ef7SMurai Takashi 			if (fOtherRefresh != NULL)
81026747978SAdrien Destugues 				fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS));
811a10cf76eSAxel Dörfler 			return;
812a10cf76eSAxel Dörfler 		}
8137e44de36SRene Gollent 	}
814a10cf76eSAxel Dörfler 
815a10cf76eSAxel Dörfler 	// this is a non-standard refresh rate
8167e44de36SRene Gollent 	if (fOtherRefresh != NULL) {
817a10cf76eSAxel Dörfler 		fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh);
818a10cf76eSAxel Dörfler 		fOtherRefresh->SetMarked(true);
819a10cf76eSAxel Dörfler 
8207e44de36SRene Gollent 		BString string;
8217e44de36SRene Gollent 		refresh_rate_to_string(fSelected.refresh, string);
822a10cf76eSAxel Dörfler 		fRefreshMenu->Superitem()->SetLabel(string.String());
823a10cf76eSAxel Dörfler 
824c9e8f97aSAdrien Destugues 		string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS));
825a10cf76eSAxel Dörfler 		fOtherRefresh->SetLabel(string.String());
826a10cf76eSAxel Dörfler 	}
8277e44de36SRene Gollent }
828a10cf76eSAxel Dörfler 
829a10cf76eSAxel Dörfler 
830a10cf76eSAxel Dörfler void
8315de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView()
832a10cf76eSAxel Dörfler {
833a10cf76eSAxel Dörfler 	BMessage updateMessage(UPDATE_DESKTOP_MSG);
834a10cf76eSAxel Dörfler 	updateMessage.AddInt32("width", fSelected.width);
835a10cf76eSAxel Dörfler 	updateMessage.AddInt32("height", fSelected.height);
836a10cf76eSAxel Dörfler 
837a10cf76eSAxel Dörfler 	PostMessage(&updateMessage, fMonitorView);
838a10cf76eSAxel Dörfler }
839a10cf76eSAxel Dörfler 
840a10cf76eSAxel Dörfler 
841a10cf76eSAxel Dörfler void
8425de171daSAxel Dörfler ScreenWindow::_UpdateControls()
843a10cf76eSAxel Dörfler {
844b21d610eSAxel Dörfler 	_UpdateWorkspaceButtons();
845b21d610eSAxel Dörfler 
846a10cf76eSAxel Dörfler 	BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays);
847c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
848a10cf76eSAxel Dörfler 		item->SetMarked(true);
849a10cf76eSAxel Dörfler 
850a10cf76eSAxel Dörfler 	item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel);
851c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
852a10cf76eSAxel Dörfler 		item->SetMarked(true);
853a10cf76eSAxel Dörfler 
854a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) {
855a10cf76eSAxel Dörfler 		item = fTVStandardMenu->ItemAt(i);
856a10cf76eSAxel Dörfler 
857a10cf76eSAxel Dörfler 		uint32 tvStandard;
858a10cf76eSAxel Dörfler 		item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard);
859a10cf76eSAxel Dörfler 		if (tvStandard == fSelected.tv_standard) {
860a10cf76eSAxel Dörfler 			if (!item->IsMarked())
861a10cf76eSAxel Dörfler 				item->SetMarked(true);
862a10cf76eSAxel Dörfler 			break;
863a10cf76eSAxel Dörfler 		}
864a10cf76eSAxel Dörfler 	}
865a10cf76eSAxel Dörfler 
8665de171daSAxel Dörfler 	_CheckResolutionMenu();
8675de171daSAxel Dörfler 	_CheckColorMenu();
8685de171daSAxel Dörfler 	_CheckRefreshMenu();
869a10cf76eSAxel Dörfler 
870a10cf76eSAxel Dörfler 	BString string;
871a10cf76eSAxel Dörfler 	resolution_to_string(fSelected, string);
872a10cf76eSAxel Dörfler 	item = fResolutionMenu->FindItem(string.String());
873a10cf76eSAxel Dörfler 
874a10cf76eSAxel Dörfler 	if (item != NULL) {
875a10cf76eSAxel Dörfler 		if (!item->IsMarked())
876a10cf76eSAxel Dörfler 			item->SetMarked(true);
877a10cf76eSAxel Dörfler 	} else {
878a10cf76eSAxel Dörfler 		// this is bad luck - if mode has been set via screen references,
879a10cf76eSAxel Dörfler 		// this case cannot occur; there are three possible solutions:
880a10cf76eSAxel Dörfler 		// 1. add a new resolution to list
881a10cf76eSAxel Dörfler 		//    - we had to remove it as soon as a "valid" one is selected
882a10cf76eSAxel Dörfler 		//    - we don't know which frequencies/bit depths are supported
883a10cf76eSAxel Dörfler 		//    - as long as we haven't the GMT formula to create
884a10cf76eSAxel Dörfler 		//      parameters for any resolution given, we cannot
885a10cf76eSAxel Dörfler 		//      really set current mode - it's just not in the list
886a10cf76eSAxel Dörfler 		// 2. choose nearest resolution
887a10cf76eSAxel Dörfler 		//    - probably a good idea, but implies coding and testing
888a10cf76eSAxel Dörfler 		// 3. choose lowest resolution
889a10cf76eSAxel Dörfler 		//    - do you really think we are so lazy? yes, we are
890a10cf76eSAxel Dörfler 		item = fResolutionMenu->ItemAt(0);
891a10cf76eSAxel Dörfler 		if (item)
892a10cf76eSAxel Dörfler 			item->SetMarked(true);
893a10cf76eSAxel Dörfler 
894a10cf76eSAxel Dörfler 		// okay - at least we set menu label to active resolution
895a10cf76eSAxel Dörfler 		fResolutionMenu->Superitem()->SetLabel(string.String());
896a10cf76eSAxel Dörfler 	}
897a10cf76eSAxel Dörfler 
898a10cf76eSAxel Dörfler 	// mark active combine mode
899a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kCombineModeCount; i++) {
900a10cf76eSAxel Dörfler 		if (kCombineModes[i].mode == fSelected.combine) {
901a10cf76eSAxel Dörfler 			item = fCombineMenu->ItemAt(i);
902c33a865cSJohn Scipione 			if (item != NULL && !item->IsMarked())
903a10cf76eSAxel Dörfler 				item->SetMarked(true);
904a10cf76eSAxel Dörfler 			break;
905a10cf76eSAxel Dörfler 		}
906a10cf76eSAxel Dörfler 	}
907a10cf76eSAxel Dörfler 
908a10cf76eSAxel Dörfler 	item = fColorsMenu->ItemAt(0);
909a10cf76eSAxel Dörfler 
9101fc4cb1fSAxel Dörfler 	for (int32 i = 0, index = 0; i <  kColorSpaceCount; i++) {
9111fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
9121fc4cb1fSAxel Dörfler 			continue;
9131fc4cb1fSAxel Dörfler 
9141fc4cb1fSAxel Dörfler 		if (kColorSpaces[i].space == fSelected.space) {
9151fc4cb1fSAxel Dörfler 			item = fColorsMenu->ItemAt(index);
916a10cf76eSAxel Dörfler 			break;
917a10cf76eSAxel Dörfler 		}
9181fc4cb1fSAxel Dörfler 
9191fc4cb1fSAxel Dörfler 		index++;
920a10cf76eSAxel Dörfler 	}
921a10cf76eSAxel Dörfler 
922c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
923a10cf76eSAxel Dörfler 		item->SetMarked(true);
924a10cf76eSAxel Dörfler 
9251fc4cb1fSAxel Dörfler 	_UpdateColorLabel();
9265de171daSAxel Dörfler 	_UpdateMonitorView();
9275de171daSAxel Dörfler 	_UpdateRefreshControl();
928a10cf76eSAxel Dörfler 
9295de171daSAxel Dörfler 	_CheckApplyEnabled();
930a10cf76eSAxel Dörfler }
931a10cf76eSAxel Dörfler 
932a10cf76eSAxel Dörfler 
93312580984SAxel Dörfler /*! Reflect active mode in chosen settings */
934a10cf76eSAxel Dörfler void
9355de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode()
936a10cf76eSAxel Dörfler {
937c491b5adSJohn Scipione 	_UpdateActiveMode(current_workspace());
938c491b5adSJohn Scipione }
939c491b5adSJohn Scipione 
940c491b5adSJohn Scipione 
941c491b5adSJohn Scipione void
942c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace)
943c491b5adSJohn Scipione {
94412580984SAxel Dörfler 	// Usually, this function gets called after a mode
945a10cf76eSAxel Dörfler 	// has been set manually; still, as the graphics driver
946a10cf76eSAxel Dörfler 	// is free to fiddle with mode passed, we better ask
947a10cf76eSAxel Dörfler 	// what kind of mode we actually got
948c491b5adSJohn Scipione 	if (fScreenMode.Get(fActive, workspace) == B_OK) {
949a10cf76eSAxel Dörfler 		fSelected = fActive;
950a10cf76eSAxel Dörfler 
95112966d04SAxel Dörfler 		_UpdateMonitor();
952c491b5adSJohn Scipione 		_BuildSupportedColorSpaces();
9535de171daSAxel Dörfler 		_UpdateControls();
954a10cf76eSAxel Dörfler 	}
955c491b5adSJohn Scipione }
956a10cf76eSAxel Dörfler 
957a10cf76eSAxel Dörfler 
958a10cf76eSAxel Dörfler void
959b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons()
960b21d610eSAxel Dörfler {
961b21d610eSAxel Dörfler 	uint32 columns;
962b21d610eSAxel Dörfler 	uint32 rows;
963b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
964b21d610eSAxel Dörfler 
965a3fa81bdSJohn Scipione 	// Set the max values enabling/disabling the up/down arrows
966b21d610eSAxel Dörfler 
967a3fa81bdSJohn Scipione 	if (rows == 1)
968a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(32);
969a3fa81bdSJohn Scipione 	else if (rows == 2)
970a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(16);
971a3fa81bdSJohn Scipione 	else if (rows <= 4)
972a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(8);
973a3fa81bdSJohn Scipione 	else if (rows <= 8)
974a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(4);
975a3fa81bdSJohn Scipione 	else if (rows <= 16)
976a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(2);
977a3fa81bdSJohn Scipione 	else if (rows <= 32)
978a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(1);
979b21d610eSAxel Dörfler 
980a3fa81bdSJohn Scipione 	if (columns == 1)
981a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(32);
982a3fa81bdSJohn Scipione 	else if (columns == 2)
983a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(16);
984a3fa81bdSJohn Scipione 	else if (columns <= 4)
985a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(8);
986a3fa81bdSJohn Scipione 	else if (columns <= 8)
987a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(4);
988a3fa81bdSJohn Scipione 	else if (columns <= 16)
989a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(2);
990a3fa81bdSJohn Scipione 	else if (columns <= 32)
991a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(1);
992b21d610eSAxel Dörfler }
993b21d610eSAxel Dörfler 
994b21d610eSAxel Dörfler 
995b21d610eSAxel Dörfler void
996a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode)
997a10cf76eSAxel Dörfler {
998a10cf76eSAxel Dörfler 	// move window on screen, if necessary
999a10cf76eSAxel Dörfler 	if (frame.right <= Frame().right
1000a10cf76eSAxel Dörfler 		&& frame.bottom <= Frame().bottom) {
1001a10cf76eSAxel Dörfler 		MoveTo((frame.Width() - Frame().Width()) / 2,
1002a10cf76eSAxel Dörfler 			(frame.Height() - Frame().Height()) / 2);
1003a10cf76eSAxel Dörfler 	}
1004a10cf76eSAxel Dörfler }
1005a10cf76eSAxel Dörfler 
1006a10cf76eSAxel Dörfler 
1007a10cf76eSAxel Dörfler void
1008a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state)
1009a10cf76eSAxel Dörfler {
1010c491b5adSJohn Scipione 	if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) {
1011c491b5adSJohn Scipione 		_UpdateActiveMode(workspace);
1012a10cf76eSAxel Dörfler 
10136edaa0f6SStefano Ceccherini 		BMessage message(UPDATE_DESKTOP_COLOR_MSG);
10146edaa0f6SStefano Ceccherini 		PostMessage(&message, fMonitorView);
1015a10cf76eSAxel Dörfler 	}
1016c491b5adSJohn Scipione }
1017a10cf76eSAxel Dörfler 
1018a10cf76eSAxel Dörfler 
1019a10cf76eSAxel Dörfler void
1020a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message)
1021a10cf76eSAxel Dörfler {
1022a10cf76eSAxel Dörfler 	switch (message->what) {
1023a10cf76eSAxel Dörfler 		case WORKSPACE_CHECK_MSG:
10245de171daSAxel Dörfler 			_CheckApplyEnabled();
1025a10cf76eSAxel Dörfler 			break;
1026a10cf76eSAxel Dörfler 
1027b21d610eSAxel Dörfler 		case kMsgWorkspaceColumnsChanged:
1028b21d610eSAxel Dörfler 		{
1029a3fa81bdSJohn Scipione 			uint32 newColumns = (uint32)fColumnsControl->Value();
1030b21d610eSAxel Dörfler 
1031b21d610eSAxel Dörfler 			uint32 rows;
1032b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(NULL, &rows);
1033b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(newColumns, rows);
1034b21d610eSAxel Dörfler 
1035b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
1036a3fa81bdSJohn Scipione 			fRowsControl->SetValue(rows);
1037a3fa81bdSJohn Scipione 				// enables/disables up/down arrows
1038b21d610eSAxel Dörfler 			_CheckApplyEnabled();
1039a3fa81bdSJohn Scipione 
1040b21d610eSAxel Dörfler 			break;
1041b21d610eSAxel Dörfler 		}
1042b21d610eSAxel Dörfler 
1043b21d610eSAxel Dörfler 		case kMsgWorkspaceRowsChanged:
1044b21d610eSAxel Dörfler 		{
1045a3fa81bdSJohn Scipione 			uint32 newRows = (uint32)fRowsControl->Value();
1046b21d610eSAxel Dörfler 
1047b21d610eSAxel Dörfler 			uint32 columns;
1048b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(&columns, NULL);
1049b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(columns, newRows);
1050b21d610eSAxel Dörfler 
1051b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
1052a3fa81bdSJohn Scipione 			fColumnsControl->SetValue(columns);
1053a3fa81bdSJohn Scipione 				// enables/disables up/down arrows
1054b21d610eSAxel Dörfler 			_CheckApplyEnabled();
1055a10cf76eSAxel Dörfler 			break;
1056a10cf76eSAxel Dörfler 		}
1057a10cf76eSAxel Dörfler 
1058a10cf76eSAxel Dörfler 		case POP_RESOLUTION_MSG:
1059a10cf76eSAxel Dörfler 		{
1060a10cf76eSAxel Dörfler 			message->FindInt32("width", &fSelected.width);
1061a10cf76eSAxel Dörfler 			message->FindInt32("height", &fSelected.height);
1062a10cf76eSAxel Dörfler 
10635de171daSAxel Dörfler 			_CheckColorMenu();
10645de171daSAxel Dörfler 			_CheckRefreshMenu();
1065a10cf76eSAxel Dörfler 
10665de171daSAxel Dörfler 			_UpdateMonitorView();
10675de171daSAxel Dörfler 			_UpdateRefreshControl();
1068a10cf76eSAxel Dörfler 
10695de171daSAxel Dörfler 			_CheckApplyEnabled();
1070a10cf76eSAxel Dörfler 			break;
1071a10cf76eSAxel Dörfler 		}
1072a10cf76eSAxel Dörfler 
1073a10cf76eSAxel Dörfler 		case POP_COLORS_MSG:
1074a10cf76eSAxel Dörfler 		{
10751fc4cb1fSAxel Dörfler 			int32 space;
10761fc4cb1fSAxel Dörfler 			if (message->FindInt32("space", &space) != B_OK)
10771fc4cb1fSAxel Dörfler 				break;
1078a10cf76eSAxel Dörfler 
10791fc4cb1fSAxel Dörfler 			int32 index;
10801fc4cb1fSAxel Dörfler 			if (message->FindInt32("index", &index) == B_OK
10811fc4cb1fSAxel Dörfler 				&& fColorsMenu->ItemAt(index) != NULL)
10821fc4cb1fSAxel Dörfler 				fUserSelectedColorSpace = fColorsMenu->ItemAt(index);
10831fc4cb1fSAxel Dörfler 
10841fc4cb1fSAxel Dörfler 			fSelected.space = (color_space)space;
10851fc4cb1fSAxel Dörfler 			_UpdateColorLabel();
1086a10cf76eSAxel Dörfler 
10875de171daSAxel Dörfler 			_CheckApplyEnabled();
1088a10cf76eSAxel Dörfler 			break;
1089a10cf76eSAxel Dörfler 		}
1090a10cf76eSAxel Dörfler 
1091a10cf76eSAxel Dörfler 		case POP_REFRESH_MSG:
1092a40498e2SWaldemar Kornewald 		{
1093a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
1094c9e8f97aSAdrien Destugues 			fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS));
10951fc4cb1fSAxel Dörfler 				// revert "Other…" label - it might have a refresh rate prefix
1096a10cf76eSAxel Dörfler 
10975de171daSAxel Dörfler 			_CheckApplyEnabled();
1098a10cf76eSAxel Dörfler 			break;
1099a40498e2SWaldemar Kornewald 		}
1100a10cf76eSAxel Dörfler 
1101a10cf76eSAxel Dörfler 		case POP_OTHER_REFRESH_MSG:
1102a10cf76eSAxel Dörfler 		{
110329e8a73aSAxel Dörfler 			// make sure menu shows something useful
11045de171daSAxel Dörfler 			_UpdateRefreshControl();
1105a10cf76eSAxel Dörfler 
110629e8a73aSAxel Dörfler 			float min = 0, max = 999;
110729e8a73aSAxel Dörfler 			fScreenMode.GetRefreshLimits(fSelected, min, max);
110829e8a73aSAxel Dörfler 			if (min < gMinRefresh)
110929e8a73aSAxel Dörfler 				min = gMinRefresh;
111029e8a73aSAxel Dörfler 			if (max > gMaxRefresh)
111129e8a73aSAxel Dörfler 				max = gMaxRefresh;
111229e8a73aSAxel Dörfler 
111370a2b1b5SAxel Dörfler 			monitor_info info;
111470a2b1b5SAxel Dörfler 			if (fScreenMode.GetMonitorInfo(info) == B_OK) {
111570a2b1b5SAxel Dörfler 				min = max_c(info.min_vertical_frequency, min);
111670a2b1b5SAxel Dörfler 				max = min_c(info.max_vertical_frequency, max);
111770a2b1b5SAxel Dörfler 			}
111870a2b1b5SAxel Dörfler 
1119c5d10f7aSAxel Dörfler 			RefreshWindow *fRefreshWindow = new RefreshWindow(
112070a2b1b5SAxel Dörfler 				fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh,
112170a2b1b5SAxel Dörfler 				min, max);
1122a10cf76eSAxel Dörfler 			fRefreshWindow->Show();
1123a10cf76eSAxel Dörfler 			break;
1124a10cf76eSAxel Dörfler 		}
1125a10cf76eSAxel Dörfler 
1126a10cf76eSAxel Dörfler 		case SET_CUSTOM_REFRESH_MSG:
1127a10cf76eSAxel Dörfler 		{
1128a10cf76eSAxel Dörfler 			// user pressed "done" in "Other…" refresh dialog;
1129a10cf76eSAxel Dörfler 			// select the refresh rate chosen
1130a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
1131a10cf76eSAxel Dörfler 
11325de171daSAxel Dörfler 			_UpdateRefreshControl();
11335de171daSAxel Dörfler 			_CheckApplyEnabled();
1134a10cf76eSAxel Dörfler 			break;
1135a10cf76eSAxel Dörfler 		}
1136a10cf76eSAxel Dörfler 
1137a10cf76eSAxel Dörfler 		case POP_COMBINE_DISPLAYS_MSG:
1138a10cf76eSAxel Dörfler 		{
1139a10cf76eSAxel Dörfler 			// new combine mode has bee chosen
1140a10cf76eSAxel Dörfler 			int32 mode;
1141a10cf76eSAxel Dörfler 			if (message->FindInt32("mode", &mode) == B_OK)
1142a10cf76eSAxel Dörfler 				fSelected.combine = (combine_mode)mode;
1143a10cf76eSAxel Dörfler 
11445de171daSAxel Dörfler 			_CheckResolutionMenu();
11455de171daSAxel Dörfler 			_CheckApplyEnabled();
1146a10cf76eSAxel Dörfler 			break;
1147a10cf76eSAxel Dörfler 		}
1148a10cf76eSAxel Dörfler 
1149a10cf76eSAxel Dörfler 		case POP_SWAP_DISPLAYS_MSG:
1150a10cf76eSAxel Dörfler 			message->FindBool("swap", &fSelected.swap_displays);
11515de171daSAxel Dörfler 			_CheckApplyEnabled();
1152a10cf76eSAxel Dörfler 			break;
1153a10cf76eSAxel Dörfler 
1154a10cf76eSAxel Dörfler 		case POP_USE_LAPTOP_PANEL_MSG:
1155a10cf76eSAxel Dörfler 			message->FindBool("use", &fSelected.use_laptop_panel);
11565de171daSAxel Dörfler 			_CheckApplyEnabled();
1157a10cf76eSAxel Dörfler 			break;
1158a10cf76eSAxel Dörfler 
1159a10cf76eSAxel Dörfler 		case POP_TV_STANDARD_MSG:
1160a10cf76eSAxel Dörfler 			message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard);
11615de171daSAxel Dörfler 			_CheckApplyEnabled();
1162a10cf76eSAxel Dörfler 			break;
1163a10cf76eSAxel Dörfler 
1164df3f5bacSStephan Aßmus 		case BUTTON_LAUNCH_BACKGROUNDS_MSG:
11656f095d6aSRyan Leavengood 			if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) {
11666f095d6aSRyan Leavengood 				app_info info;
11676f095d6aSRyan Leavengood 				be_roster->GetAppInfo(kBackgroundsSignature, &info);
11686f095d6aSRyan Leavengood 				be_roster->ActivateApp(info.team);
11696f095d6aSRyan Leavengood 			}
1170df3f5bacSStephan Aßmus 			break;
1171df3f5bacSStephan Aßmus 
1172a10cf76eSAxel Dörfler 		case BUTTON_DEFAULTS_MSG:
1173a10cf76eSAxel Dörfler 		{
11744be51fe3SWaldemar Kornewald 			// TODO: get preferred settings of screen
1175a10cf76eSAxel Dörfler 			fSelected.width = 640;
1176a10cf76eSAxel Dörfler 			fSelected.height = 480;
1177a10cf76eSAxel Dörfler 			fSelected.space = B_CMAP8;
1178a10cf76eSAxel Dörfler 			fSelected.refresh = 60.0;
1179a10cf76eSAxel Dörfler 			fSelected.combine = kCombineDisable;
1180a10cf76eSAxel Dörfler 			fSelected.swap_displays = false;
1181a10cf76eSAxel Dörfler 			fSelected.use_laptop_panel = false;
1182a10cf76eSAxel Dörfler 			fSelected.tv_standard = 0;
1183a10cf76eSAxel Dörfler 
1184b21d610eSAxel Dörfler 			// TODO: workspace defaults
1185abc649b8SWaldemar Kornewald 
11865de171daSAxel Dörfler 			_UpdateControls();
1187a10cf76eSAxel Dörfler 			break;
1188a10cf76eSAxel Dörfler 		}
1189a10cf76eSAxel Dörfler 
119010e9b12fSWaldemar Kornewald 		case BUTTON_UNDO_MSG:
119161c5c89bSAxel Dörfler 			fUndoScreenMode.Revert();
11925de171daSAxel Dörfler 			_UpdateActiveMode();
1193abc649b8SWaldemar Kornewald 			break;
1194abc649b8SWaldemar Kornewald 
1195abc649b8SWaldemar Kornewald 		case BUTTON_REVERT_MSG:
1196abc649b8SWaldemar Kornewald 		{
1197abc649b8SWaldemar Kornewald 			fModified = false;
1198199893c3SAxel Dörfler 			fBootWorkspaceApplied = false;
1199abc649b8SWaldemar Kornewald 
1200b21d610eSAxel Dörfler 			// ScreenMode::Revert() assumes that we first set the correct
1201b21d610eSAxel Dörfler 			// number of workspaces
1202b21d610eSAxel Dörfler 
1203b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns,
1204b21d610eSAxel Dörfler 				fOriginalWorkspacesRows);
1205b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
1206b21d610eSAxel Dörfler 
1207a10cf76eSAxel Dörfler 			fScreenMode.Revert();
12083a2b67b5SAdrien Destugues 
12093a2b67b5SAdrien Destugues 			BScreen screen(this);
12103a2b67b5SAdrien Destugues 			screen.SetBrightness(fOriginalBrightness);
12113a2b67b5SAdrien Destugues 			fBrightnessSlider->SetValue(fOriginalBrightness * 255);
12121f2666fdSJadedTuna 
12131f2666fdSJadedTuna 			_UpdateActiveMode();
1214a10cf76eSAxel Dörfler 			break;
1215abc649b8SWaldemar Kornewald 		}
1216a10cf76eSAxel Dörfler 
1217a10cf76eSAxel Dörfler 		case BUTTON_APPLY_MSG:
12185de171daSAxel Dörfler 			_Apply();
1219a10cf76eSAxel Dörfler 			break;
1220a10cf76eSAxel Dörfler 
1221abc649b8SWaldemar Kornewald 		case MAKE_INITIAL_MSG:
1222abc649b8SWaldemar Kornewald 			// user pressed "keep" in confirmation dialog
1223abc649b8SWaldemar Kornewald 			fModified = true;
12245de171daSAxel Dörfler 			_UpdateActiveMode();
1225a10cf76eSAxel Dörfler 			break;
1226a10cf76eSAxel Dörfler 
1227b8a61399SBrian Hill 		case UPDATE_DESKTOP_COLOR_MSG:
1228b8a61399SBrian Hill 			PostMessage(message, fMonitorView);
1229b8a61399SBrian Hill 			break;
1230b8a61399SBrian Hill 
12313a2b67b5SAdrien Destugues 		case SLIDER_BRIGHTNESS_MSG:
12323a2b67b5SAdrien Destugues 		{
12333a2b67b5SAdrien Destugues 			BScreen screen(this);
12343a2b67b5SAdrien Destugues 			screen.SetBrightness(message->FindInt32("be:value") / 255.f);
12353a2b67b5SAdrien Destugues 			_CheckApplyEnabled();
12363a2b67b5SAdrien Destugues 			break;
12373a2b67b5SAdrien Destugues 		}
12383a2b67b5SAdrien Destugues 
1239a10cf76eSAxel Dörfler 		default:
1240a10cf76eSAxel Dörfler 			BWindow::MessageReceived(message);
1241a10cf76eSAxel Dörfler 	}
1242a10cf76eSAxel Dörfler }
1243a10cf76eSAxel Dörfler 
1244a10cf76eSAxel Dörfler 
124512580984SAxel Dörfler status_t
124612580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const
124712580984SAxel Dörfler {
124812580984SAxel Dörfler 	BPath path;
124912580984SAxel Dörfler 	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
125012580984SAxel Dörfler 	if (status < B_OK)
125112580984SAxel Dörfler 		return status;
125212580984SAxel Dörfler 
125312580984SAxel Dörfler 	path.Append("kernel/drivers");
125412580984SAxel Dörfler 	status = create_directory(path.Path(), 0755);
125512580984SAxel Dörfler 	if (status < B_OK)
125612580984SAxel Dörfler 		return status;
125712580984SAxel Dörfler 
125812580984SAxel Dörfler 	path.Append("vesa");
125912580984SAxel Dörfler 	BFile file;
126012580984SAxel Dörfler 	status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
126112580984SAxel Dörfler 	if (status < B_OK)
126212580984SAxel Dörfler 		return status;
126312580984SAxel Dörfler 
126412580984SAxel Dörfler 	char buffer[256];
12655084d0d4SAlex Smith 	snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %"
12665084d0d4SAlex Smith 		B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel());
126712580984SAxel Dörfler 
126812580984SAxel Dörfler 	ssize_t bytesWritten = file.Write(buffer, strlen(buffer));
126912580984SAxel Dörfler 	if (bytesWritten < B_OK)
127012580984SAxel Dörfler 		return bytesWritten;
127112580984SAxel Dörfler 
127212580984SAxel Dörfler 	return B_OK;
127312580984SAxel Dörfler }
127412580984SAxel Dörfler 
127512580984SAxel Dörfler 
1276a10cf76eSAxel Dörfler void
12771fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces()
12781fc4cb1fSAxel Dörfler {
12791fc4cb1fSAxel Dörfler 	fSupportedColorSpaces = 0;
12801fc4cb1fSAxel Dörfler 
12811fc4cb1fSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
12821fc4cb1fSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
12831fc4cb1fSAxel Dörfler 			if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) {
12841fc4cb1fSAxel Dörfler 				fSupportedColorSpaces |= 1 << i;
12851fc4cb1fSAxel Dörfler 				break;
12861fc4cb1fSAxel Dörfler 			}
12871fc4cb1fSAxel Dörfler 		}
12881fc4cb1fSAxel Dörfler 	}
12891fc4cb1fSAxel Dörfler }
12901fc4cb1fSAxel Dörfler 
12911fc4cb1fSAxel Dörfler 
12921fc4cb1fSAxel Dörfler void
12935de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled()
1294a10cf76eSAxel Dörfler {
129595ef5044SJanus 	bool applyEnabled = true;
129695ef5044SJanus 
129795ef5044SJanus 	if (fSelected == fActive) {
129895ef5044SJanus 		applyEnabled = false;
129995ef5044SJanus 		if (fAllWorkspacesItem->IsMarked()) {
130095ef5044SJanus 			screen_mode screenMode;
130195ef5044SJanus 			const int32 workspaceCount = count_workspaces();
130295ef5044SJanus 			for (int32 i = 0; i < workspaceCount; i++) {
130395ef5044SJanus 				fScreenMode.Get(screenMode, i);
130495ef5044SJanus 				if (screenMode != fSelected) {
130595ef5044SJanus 					applyEnabled = true;
130695ef5044SJanus 					break;
130795ef5044SJanus 				}
130895ef5044SJanus 			}
130995ef5044SJanus 		}
131095ef5044SJanus 	}
131195ef5044SJanus 
131295ef5044SJanus 	fApplyButton->SetEnabled(applyEnabled);
1313b21d610eSAxel Dörfler 
1314b21d610eSAxel Dörfler 	uint32 columns;
1315b21d610eSAxel Dörfler 	uint32 rows;
1316b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
1317b21d610eSAxel Dörfler 
13183a2b67b5SAdrien Destugues 	BScreen screen(this);
13193a2b67b5SAdrien Destugues 	float brightness = -1;
13203a2b67b5SAdrien Destugues 	screen.GetBrightness(&brightness);
13213a2b67b5SAdrien Destugues 
1322b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns
1323b21d610eSAxel Dörfler 		|| rows != fOriginalWorkspacesRows
13243a2b67b5SAdrien Destugues 		|| brightness != fOriginalBrightness
13255de171daSAxel Dörfler 		|| fSelected != fOriginal);
1326a10cf76eSAxel Dörfler }
1327a10cf76eSAxel Dörfler 
1328a10cf76eSAxel Dörfler 
1329a10cf76eSAxel Dörfler void
13305de171daSAxel Dörfler ScreenWindow::_UpdateOriginal()
1331abc649b8SWaldemar Kornewald {
1332b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns,
1333b21d610eSAxel Dörfler 		&fOriginalWorkspacesRows);
1334b21d610eSAxel Dörfler 
1335abc649b8SWaldemar Kornewald 	fScreenMode.Get(fOriginal);
1336abc649b8SWaldemar Kornewald 	fScreenMode.UpdateOriginalModes();
1337abc649b8SWaldemar Kornewald }
1338abc649b8SWaldemar Kornewald 
1339abc649b8SWaldemar Kornewald 
1340abc649b8SWaldemar Kornewald void
134112966d04SAxel Dörfler ScreenWindow::_UpdateMonitor()
134212966d04SAxel Dörfler {
134312966d04SAxel Dörfler 	monitor_info info;
134412966d04SAxel Dörfler 	float diagonalInches;
134512966d04SAxel Dörfler 	status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches);
134655030977SAxel Dörfler 	if (status == B_OK) {
13471a8af605SAxel Dörfler 		char text[512];
134866ab1666SAxel Dörfler 		snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor,
134966ab1666SAxel Dörfler 			info.name[0] ? " " : "", info.name, diagonalInches);
135012966d04SAxel Dörfler 
1351ef046e3bSJohn Scipione 		fScreenBox->SetLabel(text);
135255030977SAxel Dörfler 	} else {
1353ef046e3bSJohn Scipione 		fScreenBox->SetLabel(B_TRANSLATE("Display info"));
135455030977SAxel Dörfler 	}
1355af8f9c31SAxel Dörfler 
13568b46ee25SAdrien Destugues 	// Add info about the graphics device
13578b46ee25SAdrien Destugues 
13588b46ee25SAdrien Destugues 	accelerant_device_info deviceInfo;
13598b46ee25SAdrien Destugues 
13608b46ee25SAdrien Destugues 	if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK) {
13618b46ee25SAdrien Destugues 		BString deviceString;
13628b46ee25SAdrien Destugues 
13638b46ee25SAdrien Destugues 		if (deviceInfo.name[0] && deviceInfo.chipset[0]) {
13648b46ee25SAdrien Destugues 			deviceString.SetToFormat("%s (%s)", deviceInfo.name,
13658b46ee25SAdrien Destugues 				deviceInfo.chipset);
13668b46ee25SAdrien Destugues 		} else if (deviceInfo.name[0] || deviceInfo.chipset[0]) {
13678b46ee25SAdrien Destugues 			deviceString
13688b46ee25SAdrien Destugues 				= deviceInfo.name[0] ? deviceInfo.name : deviceInfo.chipset;
13698b46ee25SAdrien Destugues 		}
13708b46ee25SAdrien Destugues 
13718b46ee25SAdrien Destugues 		fDeviceInfo->SetText(deviceString);
13728b46ee25SAdrien Destugues 	}
13738b46ee25SAdrien Destugues 
13748b46ee25SAdrien Destugues 
137555030977SAxel Dörfler 	char text[512];
13761a8af605SAxel Dörfler 	size_t length = 0;
13771a8af605SAxel Dörfler 	text[0] = 0;
13781a8af605SAxel Dörfler 
137955030977SAxel Dörfler 	if (status == B_OK) {
1380af8f9c31SAxel Dörfler 		if (info.min_horizontal_frequency != 0
1381af8f9c31SAxel Dörfler 			&& info.min_vertical_frequency != 0
1382af8f9c31SAxel Dörfler 			&& info.max_pixel_clock != 0) {
13831a8af605SAxel Dörfler 			length = snprintf(text, sizeof(text),
1384c9e8f97aSAdrien Destugues 				B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n"
13859c1a9b92SAdrien Destugues 					"Vertical frequency:\t%lu - %lu Hz\n\n"
1386c9e8f97aSAdrien Destugues 					"Maximum pixel clock:\t%g MHz"),
1387*7eab6b48SPulkoMandy 				(long unsigned)info.min_horizontal_frequency,
1388*7eab6b48SPulkoMandy 				(long unsigned)info.max_horizontal_frequency,
1389*7eab6b48SPulkoMandy 				(long unsigned)info.min_vertical_frequency,
1390*7eab6b48SPulkoMandy 				(long unsigned)info.max_vertical_frequency,
13911a8af605SAxel Dörfler 				info.max_pixel_clock / 1000.0);
1392af8f9c31SAxel Dörfler 		}
13931a8af605SAxel Dörfler 		if (info.serial_number[0] && length < sizeof(text)) {
1394e96dd823SPulkoMandy 			if (length > 0) {
1395e96dd823SPulkoMandy 				text[length++] = '\n';
1396e96dd823SPulkoMandy 				text[length++] = '\n';
1397e96dd823SPulkoMandy 				text[length] = '\0';
1398e96dd823SPulkoMandy 			}
13991a8af605SAxel Dörfler 			length += snprintf(text + length, sizeof(text) - length,
1400e96dd823SPulkoMandy 				B_TRANSLATE("Serial no.: %s"), info.serial_number);
14011a8af605SAxel Dörfler 			if (info.produced.week != 0 && info.produced.year != 0
14021a8af605SAxel Dörfler 				&& length < sizeof(text)) {
14031a8af605SAxel Dörfler 				length += snprintf(text + length, sizeof(text) - length,
14041a8af605SAxel Dörfler 					" (%u/%u)", info.produced.week, info.produced.year);
14051a8af605SAxel Dörfler 			}
14061a8af605SAxel Dörfler 		}
140755030977SAxel Dörfler 	}
140861c5c89bSAxel Dörfler 
14091a8af605SAxel Dörfler 	if (text[0])
14101a8af605SAxel Dörfler 		fMonitorView->SetToolTip(text);
141112966d04SAxel Dörfler }
141212966d04SAxel Dörfler 
141312966d04SAxel Dörfler 
141412966d04SAxel Dörfler void
14151fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel()
14161fc4cb1fSAxel Dörfler {
14171fc4cb1fSAxel Dörfler 	BString string;
1418551c9f15SSiarzhuk Zharski 	string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel");
14191fc4cb1fSAxel Dörfler 	fColorsMenu->Superitem()->SetLabel(string.String());
14201fc4cb1fSAxel Dörfler }
14211fc4cb1fSAxel Dörfler 
14221fc4cb1fSAxel Dörfler 
14231fc4cb1fSAxel Dörfler void
14245de171daSAxel Dörfler ScreenWindow::_Apply()
1425a10cf76eSAxel Dörfler {
1426abc649b8SWaldemar Kornewald 	// make checkpoint, so we can undo these changes
142761c5c89bSAxel Dörfler 	fUndoScreenMode.UpdateOriginalModes();
142861c5c89bSAxel Dörfler 
142907184a9eSAxel Dörfler 	status_t status = fScreenMode.Set(fSelected);
143007184a9eSAxel Dörfler 	if (status == B_OK) {
1431abc649b8SWaldemar Kornewald 		// use the mode that has eventually been set and
1432abc649b8SWaldemar Kornewald 		// thus we know to be working; it can differ from
1433abc649b8SWaldemar Kornewald 		// the mode selected by user due to hardware limitation
1434abc649b8SWaldemar Kornewald 		display_mode newMode;
1435abc649b8SWaldemar Kornewald 		BScreen screen(this);
1436abc649b8SWaldemar Kornewald 		screen.GetMode(&newMode);
1437abc649b8SWaldemar Kornewald 
1438abc649b8SWaldemar Kornewald 		if (fAllWorkspacesItem->IsMarked()) {
1439abc649b8SWaldemar Kornewald 			int32 originatingWorkspace = current_workspace();
144095ef5044SJanus 			const int32 workspaceCount = count_workspaces();
144195ef5044SJanus 			for (int32 i = 0; i < workspaceCount; i++) {
1442abc649b8SWaldemar Kornewald 				if (i != originatingWorkspace)
1443abc649b8SWaldemar Kornewald 					screen.SetMode(i, &newMode, true);
1444abc649b8SWaldemar Kornewald 			}
1445199893c3SAxel Dörfler 			fBootWorkspaceApplied = true;
1446199893c3SAxel Dörfler 		} else {
1447199893c3SAxel Dörfler 			if (current_workspace() == 0)
1448199893c3SAxel Dörfler 				fBootWorkspaceApplied = true;
1449abc649b8SWaldemar Kornewald 		}
1450abc649b8SWaldemar Kornewald 
1451a10cf76eSAxel Dörfler 		fActive = fSelected;
1452a10cf76eSAxel Dörfler 
1453abc649b8SWaldemar Kornewald 		// TODO: only show alert when this is an unknown mode
145441f43d56SAugustin Cavalier 		BAlert* window = new AlertWindow(this);
145541f43d56SAugustin Cavalier 		window->Go(NULL);
145607184a9eSAxel Dörfler 	} else {
145707184a9eSAxel Dörfler 		char message[256];
145807184a9eSAxel Dörfler 		snprintf(message, sizeof(message),
1459c9e8f97aSAdrien Destugues 			B_TRANSLATE("The screen mode could not be set:\n\t%s\n"),
1460c9e8f97aSAdrien Destugues 			screen_errors(status));
1461551c9f15SSiarzhuk Zharski 		BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message,
1462c9e8f97aSAdrien Destugues 			B_TRANSLATE("OK"), NULL, NULL,
146307184a9eSAxel Dörfler 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
1464aed35104SHumdinger 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
146507184a9eSAxel Dörfler 		alert->Go();
1466a10cf76eSAxel Dörfler 	}
146707184a9eSAxel Dörfler }
1468