xref: /haiku/src/preferences/screen/ScreenWindow.cpp (revision a31d463b38bbc273d5d4c5ac8ba43a117e6331eb)
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
tv_standard_to_string(uint32 mode)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
resolution_to_string(screen_mode & mode,BString & string)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
refresh_rate_to_string(float refresh,BString & string,bool appendUnit=true,bool alwaysWithFraction=false)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*
screen_errors(status_t status)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 
ScreenWindow(ScreenSettings * settings)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),
177*a31d463bSJérôme Duval 	fUserSelectedColorSpace(NULL),
1787e44de36SRene Gollent 	fOtherRefresh(NULL),
179294a85aaSRene Gollent 	fScreenMode(this),
18061c5c89bSAxel Dörfler 	fUndoScreenMode(this),
181abc649b8SWaldemar Kornewald 	fModified(false)
182a10cf76eSAxel Dörfler {
183a10cf76eSAxel Dörfler 	BScreen screen(this);
184a10cf76eSAxel Dörfler 
18512580984SAxel Dörfler 	accelerant_device_info info;
186d1516993SAxel Dörfler 	if (screen.GetDeviceInfo(&info) == B_OK
187d1516993SAxel Dörfler 		&& !strcasecmp(info.chipset, "VESA"))
18812580984SAxel Dörfler 		fIsVesa = true;
18912580984SAxel Dörfler 
1905de171daSAxel Dörfler 	_UpdateOriginal();
1911fc4cb1fSAxel Dörfler 	_BuildSupportedColorSpaces();
192a10cf76eSAxel Dörfler 	fActive = fSelected = fOriginal;
193a10cf76eSAxel Dörfler 
1945a78744bSAxel Dörfler 	fSettings = settings;
1955a78744bSAxel Dörfler 
1965a78744bSAxel Dörfler 	// we need the "Current Workspace" first to get its height
1975a78744bSAxel Dörfler 
198c9e8f97aSAdrien Destugues 	BPopUpMenu* popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"),
199c9e8f97aSAdrien Destugues 		true, true);
200c9e8f97aSAdrien Destugues 	fAllWorkspacesItem = new BMenuItem(B_TRANSLATE("All workspaces"),
201d1516993SAxel Dörfler 		new BMessage(WORKSPACE_CHECK_MSG));
2025a78744bSAxel Dörfler 	popUpMenu->AddItem(fAllWorkspacesItem);
203c9e8f97aSAdrien Destugues 	BMenuItem *item = new BMenuItem(B_TRANSLATE("Current workspace"),
204d1516993SAxel Dörfler 		new BMessage(WORKSPACE_CHECK_MSG));
205b72c4836SAlexandre Deckner 
2065a78744bSAxel Dörfler 	popUpMenu->AddItem(item);
20727c43a2dSRene Gollent 	fAllWorkspacesItem->SetMarked(true);
2085a78744bSAxel Dörfler 
209b21d610eSAxel Dörfler 	BMenuField* workspaceMenuField = new BMenuField("WorkspaceMenu", NULL,
21010dfe897SAxel Dörfler 		popUpMenu);
2115a78744bSAxel Dörfler 	workspaceMenuField->ResizeToPreferred();
212a10cf76eSAxel Dörfler 
213a10cf76eSAxel Dörfler 	// box on the left with workspace count and monitor view
214a10cf76eSAxel Dörfler 
215ef046e3bSJohn Scipione 	fScreenBox = new BBox("screen box");
216ef046e3bSJohn Scipione 	BGroupView* groupView = new BGroupView(B_VERTICAL, B_USE_SMALL_SPACING);
217ef046e3bSJohn Scipione 	fScreenBox->AddChild(groupView);
218ef046e3bSJohn Scipione 	fScreenBox->SetLabel("placeholder");
219ef046e3bSJohn Scipione 		// Needed for layouting, will be replaced with screen name/size
220ef046e3bSJohn Scipione 	groupView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING,
221ef046e3bSJohn Scipione 		B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
222a10cf76eSAxel Dörfler 
223ef046e3bSJohn Scipione 	fDeviceInfo = new BStringView("device info", "");
2248b46ee25SAdrien Destugues 	fDeviceInfo->SetAlignment(B_ALIGN_CENTER);
225ef046e3bSJohn Scipione 	groupView->AddChild(fDeviceInfo);
2268b46ee25SAdrien Destugues 
2278bf216d6SAxel Dörfler 	float scaling = std::max(1.0f, be_plain_font->Size() / 12.0f);
2288bf216d6SAxel Dörfler 	fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0 * scaling,
2298bf216d6SAxel Dörfler 			80.0 * scaling), "monitor", screen.Frame().IntegerWidth() + 1,
230c9e8f97aSAdrien Destugues 		screen.Frame().IntegerHeight() + 1);
231ef046e3bSJohn Scipione 	fMonitorView->SetToolTip(B_TRANSLATE("Set background" B_UTF8_ELLIPSIS));
232ef046e3bSJohn Scipione 	groupView->AddChild(fMonitorView);
2335a78744bSAxel Dörfler 
234ef046e3bSJohn Scipione 	// brightness slider
235ef046e3bSJohn Scipione 	fBrightnessSlider = new BSlider("brightness", B_TRANSLATE("Brightness:"),
236ef046e3bSJohn Scipione 		NULL, 0, 255, B_HORIZONTAL);
237ef046e3bSJohn Scipione 	groupView->AddChild(fBrightnessSlider);
238ef046e3bSJohn Scipione 
239ef046e3bSJohn Scipione 	if (screen.GetBrightness(&fOriginalBrightness) == B_OK) {
240ef046e3bSJohn Scipione 		fBrightnessSlider->SetModificationMessage(
241ef046e3bSJohn Scipione 			new BMessage(SLIDER_BRIGHTNESS_MSG));
242ef046e3bSJohn Scipione 		fBrightnessSlider->SetValue(fOriginalBrightness * 255);
243ef046e3bSJohn Scipione 	} else {
244ef046e3bSJohn Scipione 		// The driver does not support changing the brightness,
245ef046e3bSJohn Scipione 		// so hide the slider
246ef046e3bSJohn Scipione 		fBrightnessSlider->Hide();
247ef046e3bSJohn Scipione 		fOriginalBrightness = -1;
248ef046e3bSJohn Scipione 	}
249ef046e3bSJohn Scipione 
250ef046e3bSJohn Scipione 	// box on the left below the screen box with workspaces
251ef046e3bSJohn Scipione 
252ef046e3bSJohn Scipione 	BBox* workspacesBox = new BBox("workspaces box");
253ef046e3bSJohn Scipione 	workspacesBox->SetLabel(B_TRANSLATE("Workspaces"));
254ef046e3bSJohn Scipione 
255ef046e3bSJohn Scipione 	BGroupLayout* workspacesLayout = new BGroupLayout(B_VERTICAL);
256ef046e3bSJohn Scipione 	workspacesLayout->SetInsets(B_USE_DEFAULT_SPACING,
257ef046e3bSJohn Scipione 		be_control_look->DefaultItemSpacing() * 2, B_USE_DEFAULT_SPACING,
258ef046e3bSJohn Scipione 		B_USE_DEFAULT_SPACING);
259ef046e3bSJohn Scipione 	workspacesBox->SetLayout(workspacesLayout);
260e1c88201SJohn Scipione 
261a3fa81bdSJohn Scipione 	fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"),
262b21d610eSAxel Dörfler 		new BMessage(kMsgWorkspaceColumnsChanged));
263a3fa81bdSJohn Scipione 	fColumnsControl->SetAlignment(B_ALIGN_RIGHT);
264a3fa81bdSJohn Scipione 	fColumnsControl->SetRange(1, 32);
265b21d610eSAxel Dörfler 
266a3fa81bdSJohn Scipione 	fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"),
267a3fa81bdSJohn Scipione 		new BMessage(kMsgWorkspaceRowsChanged));
268a3fa81bdSJohn Scipione 	fRowsControl->SetAlignment(B_ALIGN_RIGHT);
269a3fa81bdSJohn Scipione 	fRowsControl->SetRange(1, 32);
270a3fa81bdSJohn Scipione 
271a3fa81bdSJohn Scipione 	uint32 columns;
272a3fa81bdSJohn Scipione 	uint32 rows;
273a3fa81bdSJohn Scipione 	BPrivate::get_workspaces_layout(&columns, &rows);
274a3fa81bdSJohn Scipione 	fColumnsControl->SetValue(columns);
275a3fa81bdSJohn Scipione 	fRowsControl->SetValue(rows);
276a3fa81bdSJohn Scipione 
277ef046e3bSJohn Scipione 	workspacesBox->AddChild(BLayoutBuilder::Group<>()
278e1c88201SJohn Scipione 		.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
2794dcc9761SJohn Scipione 			.AddGroup(B_HORIZONTAL, 0)
2804dcc9761SJohn Scipione 				.AddGlue()
281a3fa81bdSJohn Scipione 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
282e1c88201SJohn Scipione 					// columns
283e1c88201SJohn Scipione 					.Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0)
284a3fa81bdSJohn Scipione 					.Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0)
285e1c88201SJohn Scipione 					// rows
286e1c88201SJohn Scipione 					.Add(fRowsControl->CreateLabelLayoutItem(), 0, 1)
287a3fa81bdSJohn Scipione 					.Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1)
288b21d610eSAxel Dörfler 					.End()
2894dcc9761SJohn Scipione 				.AddGlue()
2904dcc9761SJohn Scipione 				.End()
29125fd5c7bSAlex Wilson 			.End()
29225fd5c7bSAlex Wilson 		.View());
293b21d610eSAxel Dörfler 
294ef046e3bSJohn Scipione 	// put workspaces slider in a vertical group with a half space above so
295ef046e3bSJohn Scipione 	// if hidden you won't see the extra space.
296ef046e3bSJohn Scipione 	BView* workspacesView = BLayoutBuilder::Group<>(B_VERTICAL, 0)
297ef046e3bSJohn Scipione 		.AddStrut(B_USE_HALF_ITEM_SPACING)
298ef046e3bSJohn Scipione 		.Add(workspacesBox)
299ef046e3bSJohn Scipione 		.View();
300a10cf76eSAxel Dörfler 
301a10cf76eSAxel Dörfler 	// box on the right with screen resolution, etc.
302a10cf76eSAxel Dörfler 
303b21d610eSAxel Dörfler 	BBox* controlsBox = new BBox("controls box");
304b21d610eSAxel Dörfler 	controlsBox->SetLabel(workspaceMenuField);
3056048f541SJohn Scipione 	BGroupView* outerControlsView = new BGroupView(B_VERTICAL);
3066048f541SJohn Scipione 	outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING,
3076048f541SJohn Scipione 		B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
308b21d610eSAxel Dörfler 	controlsBox->AddChild(outerControlsView);
309a10cf76eSAxel Dörfler 
3104c28b3f1SPulkoMandy 	menu_layout layout = B_ITEMS_IN_COLUMN;
311a10cf76eSAxel Dörfler 
3124c28b3f1SPulkoMandy 	// There are modes in the list with the same resolution but different bpp or refresh rates.
3134c28b3f1SPulkoMandy 	// We don't want to take these into account when computing the menu layout, so we need to
3144c28b3f1SPulkoMandy 	// count how many entries we will really have in the menu.
3154c28b3f1SPulkoMandy 	int fullModeCount = fScreenMode.CountModes();
3164c28b3f1SPulkoMandy 	int modeCount = 0;
3174c28b3f1SPulkoMandy 	int index = 0;
31866ab1666SAxel Dörfler 	uint16 maxWidth = 0;
31966ab1666SAxel Dörfler 	uint16 maxHeight = 0;
32066ab1666SAxel Dörfler 	uint16 previousWidth = 0;
32166ab1666SAxel Dörfler 	uint16 previousHeight = 0;
3224c28b3f1SPulkoMandy 	for (int32 i = 0; i < fullModeCount; i++) {
3234c28b3f1SPulkoMandy 		screen_mode mode = fScreenMode.ModeAt(i);
3244c28b3f1SPulkoMandy 
3254c28b3f1SPulkoMandy 		if (mode.width == previousWidth && mode.height == previousHeight)
3264c28b3f1SPulkoMandy 			continue;
3274c28b3f1SPulkoMandy 		modeCount++;
3284c28b3f1SPulkoMandy 		previousWidth = mode.width;
3294c28b3f1SPulkoMandy 		previousHeight = mode.height;
3304c28b3f1SPulkoMandy 		if (maxWidth < mode.width)
3314c28b3f1SPulkoMandy 			maxWidth = mode.width;
3324c28b3f1SPulkoMandy 		if (maxHeight < mode.height)
3334c28b3f1SPulkoMandy 			maxHeight = mode.height;
3344c28b3f1SPulkoMandy 	}
3354c28b3f1SPulkoMandy 
3364c28b3f1SPulkoMandy 	if (modeCount > 16)
3374c28b3f1SPulkoMandy 		layout = B_ITEMS_IN_MATRIX;
3384c28b3f1SPulkoMandy 
3394c28b3f1SPulkoMandy 	fResolutionMenu = new BPopUpMenu("resolution", true, true, layout);
3404c28b3f1SPulkoMandy 
3414c28b3f1SPulkoMandy 	// Compute the size we should allocate to each item in the menu
3424c28b3f1SPulkoMandy 	BRect itemRect;
3434c28b3f1SPulkoMandy 	if (layout == B_ITEMS_IN_MATRIX) {
3444c28b3f1SPulkoMandy 		BFont menuFont;
3454c28b3f1SPulkoMandy 		font_height fontHeight;
3464c28b3f1SPulkoMandy 
3474c28b3f1SPulkoMandy 		fResolutionMenu->GetFont(&menuFont);
3484c28b3f1SPulkoMandy 		menuFont.GetHeight(&fontHeight);
3494c28b3f1SPulkoMandy 		itemRect.left = itemRect.top = 0;
3504c28b3f1SPulkoMandy 		itemRect.bottom = fontHeight.ascent + fontHeight.descent + 4;
3514c28b3f1SPulkoMandy 		itemRect.right = menuFont.StringWidth("99999x99999") + 16;
3524c28b3f1SPulkoMandy 		rows = modeCount / 3 + 1;
3534c28b3f1SPulkoMandy 	}
3544c28b3f1SPulkoMandy 
3554c28b3f1SPulkoMandy 	index = 0;
3564c28b3f1SPulkoMandy 	for (int32 i = 0; i < fullModeCount; i++) {
357a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
358a10cf76eSAxel Dörfler 
359a10cf76eSAxel Dörfler 		if (mode.width == previousWidth && mode.height == previousHeight)
360a10cf76eSAxel Dörfler 			continue;
361a10cf76eSAxel Dörfler 
362a10cf76eSAxel Dörfler 		previousWidth = mode.width;
363a10cf76eSAxel Dörfler 		previousHeight = mode.height;
364a10cf76eSAxel Dörfler 
365a10cf76eSAxel Dörfler 		BMessage* message = new BMessage(POP_RESOLUTION_MSG);
366a10cf76eSAxel Dörfler 		message->AddInt32("width", mode.width);
367a10cf76eSAxel Dörfler 		message->AddInt32("height", mode.height);
368a10cf76eSAxel Dörfler 
369a10cf76eSAxel Dörfler 		BString name;
3703961af9fSHumdinger 		name.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32,
3713961af9fSHumdinger 			"The '×' is the Unicode multiplication sign U+00D7"),
3723961af9fSHumdinger 			mode.width, mode.height);
373a10cf76eSAxel Dörfler 
3744c28b3f1SPulkoMandy 		if (layout == B_ITEMS_IN_COLUMN)
375a10cf76eSAxel Dörfler 			fResolutionMenu->AddItem(new BMenuItem(name.String(), message));
3764c28b3f1SPulkoMandy 		else {
3774c28b3f1SPulkoMandy 			int y = index % rows;
3784c28b3f1SPulkoMandy 			int x = index / rows;
3794c28b3f1SPulkoMandy 			itemRect.OffsetTo(x * itemRect.Width(), y * itemRect.Height());
3804c28b3f1SPulkoMandy 			fResolutionMenu->AddItem(new BMenuItem(name.String(), message), itemRect);
3814c28b3f1SPulkoMandy 		}
3824c28b3f1SPulkoMandy 
3834c28b3f1SPulkoMandy 		index++;
384a10cf76eSAxel Dörfler 	}
385a10cf76eSAxel Dörfler 
38666ab1666SAxel Dörfler 	fMonitorView->SetMaxResolution(maxWidth, maxHeight);
38766ab1666SAxel Dörfler 
388c9e8f97aSAdrien Destugues 	fResolutionField = new BMenuField("ResolutionMenu",
38910dfe897SAxel Dörfler 		B_TRANSLATE("Resolution:"), fResolutionMenu);
3906048f541SJohn Scipione 	fResolutionField->SetAlignment(B_ALIGN_RIGHT);
391a10cf76eSAxel Dörfler 
392551c9f15SSiarzhuk Zharski 	fColorsMenu = new BPopUpMenu("colors", true, false);
393a10cf76eSAxel Dörfler 
394a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
3951fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
3961fc4cb1fSAxel Dörfler 			continue;
3971fc4cb1fSAxel Dörfler 
398a10cf76eSAxel Dörfler 		BMessage* message = new BMessage(POP_COLORS_MSG);
399a10cf76eSAxel Dörfler 		message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
400a10cf76eSAxel Dörfler 		message->AddInt32("space", kColorSpaces[i].space);
401a10cf76eSAxel Dörfler 
4021fc4cb1fSAxel Dörfler 		BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message);
4031fc4cb1fSAxel Dörfler 		if (kColorSpaces[i].space == screen.ColorSpace())
4041fc4cb1fSAxel Dörfler 			fUserSelectedColorSpace = item;
4051fc4cb1fSAxel Dörfler 
4061fc4cb1fSAxel Dörfler 		fColorsMenu->AddItem(item);
407a10cf76eSAxel Dörfler 	}
408a10cf76eSAxel Dörfler 
409c9e8f97aSAdrien Destugues 	fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"),
41010dfe897SAxel Dörfler 		fColorsMenu);
4116048f541SJohn Scipione 	fColorsField->SetAlignment(B_ALIGN_RIGHT);
412a10cf76eSAxel Dörfler 
413551c9f15SSiarzhuk Zharski 	fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
414a10cf76eSAxel Dörfler 
41529e8a73aSAxel Dörfler 	float min, max;
416ec495b30SRene Gollent 	if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) {
417ec495b30SRene Gollent 		// if we couldn't obtain the refresh limits, reset to the default
418ec495b30SRene Gollent 		// range. Constraints from detected monitors will fine-tune this
419ec495b30SRene Gollent 		// later.
420ec495b30SRene Gollent 		min = kRefreshRates[0];
421ec495b30SRene Gollent 		max = kRefreshRates[kRefreshRateCount - 1];
422ec495b30SRene Gollent 	}
423ec495b30SRene Gollent 
424ec495b30SRene Gollent 	if (min == max) {
42529e8a73aSAxel Dörfler 		// This is a special case for drivers that only support a single
42629e8a73aSAxel Dörfler 		// frequency, like the VESA driver
42729e8a73aSAxel Dörfler 		BString name;
4287e44de36SRene Gollent 		refresh_rate_to_string(min, name);
429cf076964SRene Gollent 		BMessage *message = new BMessage(POP_REFRESH_MSG);
430cf076964SRene Gollent 		message->AddFloat("refresh", min);
431cf076964SRene Gollent 		BMenuItem *item = new BMenuItem(name.String(), message);
4320efb8b66SJerome Duval 		fRefreshMenu->AddItem(item);
43329e8a73aSAxel Dörfler 		item->SetEnabled(false);
43429e8a73aSAxel Dörfler 	} else {
43570a2b1b5SAxel Dörfler 		monitor_info info;
43670a2b1b5SAxel Dörfler 		if (fScreenMode.GetMonitorInfo(info) == B_OK) {
43770a2b1b5SAxel Dörfler 			min = max_c(info.min_vertical_frequency, min);
43870a2b1b5SAxel Dörfler 			max = min_c(info.max_vertical_frequency, max);
43970a2b1b5SAxel Dörfler 		}
44070a2b1b5SAxel Dörfler 
441a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kRefreshRateCount; ++i) {
44270a2b1b5SAxel Dörfler 			if (kRefreshRates[i] < min || kRefreshRates[i] > max)
44370a2b1b5SAxel Dörfler 				continue;
44470a2b1b5SAxel Dörfler 
445a10cf76eSAxel Dörfler 			BString name;
446551c9f15SSiarzhuk Zharski 			name << kRefreshRates[i] << " " << B_TRANSLATE("Hz");
447a10cf76eSAxel Dörfler 
4480efb8b66SJerome Duval 			BMessage *message = new BMessage(POP_REFRESH_MSG);
449a10cf76eSAxel Dörfler 			message->AddFloat("refresh", kRefreshRates[i]);
450a10cf76eSAxel Dörfler 
451a10cf76eSAxel Dörfler 			fRefreshMenu->AddItem(new BMenuItem(name.String(), message));
452a10cf76eSAxel Dörfler 		}
453a10cf76eSAxel Dörfler 
454c9e8f97aSAdrien Destugues 		fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS),
4550efb8b66SJerome Duval 			new BMessage(POP_OTHER_REFRESH_MSG));
456a10cf76eSAxel Dörfler 		fRefreshMenu->AddItem(fOtherRefresh);
45729e8a73aSAxel Dörfler 	}
458a10cf76eSAxel Dörfler 
459c9e8f97aSAdrien Destugues 	fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"),
46010dfe897SAxel Dörfler 		fRefreshMenu);
4616048f541SJohn Scipione 	fRefreshField->SetAlignment(B_ALIGN_RIGHT);
462b21d610eSAxel Dörfler 
46312580984SAxel Dörfler 	if (_IsVesa())
46412580984SAxel Dörfler 		fRefreshField->Hide();
465a10cf76eSAxel Dörfler 
466a10cf76eSAxel Dörfler 	// enlarged area for multi-monitor settings
467a10cf76eSAxel Dörfler 	{
468a10cf76eSAxel Dörfler 		bool dummy;
469a10cf76eSAxel Dörfler 		uint32 dummy32;
470a10cf76eSAxel Dörfler 		bool multiMonSupport;
471a10cf76eSAxel Dörfler 		bool useLaptopPanelSupport;
472a10cf76eSAxel Dörfler 		bool tvStandardSupport;
473a10cf76eSAxel Dörfler 
474a10cf76eSAxel Dörfler 		multiMonSupport = TestMultiMonSupport(&screen) == B_OK;
475a10cf76eSAxel Dörfler 		useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK;
476a10cf76eSAxel Dörfler 		tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK;
477a10cf76eSAxel Dörfler 
478a10cf76eSAxel Dörfler 		// even if there is no support, we still create all controls
479a10cf76eSAxel Dörfler 		// to make sure we don't access NULL pointers later on
480a10cf76eSAxel Dörfler 
481551c9f15SSiarzhuk Zharski 		fCombineMenu = new BPopUpMenu("CombineDisplays",
482c9e8f97aSAdrien Destugues 			true, true);
483a10cf76eSAxel Dörfler 
484a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kCombineModeCount; i++) {
4850efb8b66SJerome Duval 			BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG);
486a10cf76eSAxel Dörfler 			message->AddInt32("mode", kCombineModes[i].mode);
487a10cf76eSAxel Dörfler 
488d1516993SAxel Dörfler 			fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name,
489d1516993SAxel Dörfler 				message));
490a10cf76eSAxel Dörfler 		}
491a10cf76eSAxel Dörfler 
492b21d610eSAxel Dörfler 		fCombineField = new BMenuField("CombineMenu",
49310dfe897SAxel Dörfler 			B_TRANSLATE("Combine displays:"), fCombineMenu);
4946048f541SJohn Scipione 		fCombineField->SetAlignment(B_ALIGN_RIGHT);
495a10cf76eSAxel Dörfler 
496a10cf76eSAxel Dörfler 		if (!multiMonSupport)
497df3f5bacSStephan Aßmus 			fCombineField->Hide();
498a10cf76eSAxel Dörfler 
499551c9f15SSiarzhuk Zharski 		fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays",
500c9e8f97aSAdrien Destugues 			true, true);
501a10cf76eSAxel Dörfler 
502a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
5030efb8b66SJerome Duval 		BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG);
504a10cf76eSAxel Dörfler 		message->AddBool("swap", false);
505c9e8f97aSAdrien Destugues 		fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message));
506a10cf76eSAxel Dörfler 
507a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
508a10cf76eSAxel Dörfler 		message->AddBool("swap", true);
509c9e8f97aSAdrien Destugues 		fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message));
510a10cf76eSAxel Dörfler 
511c9e8f97aSAdrien Destugues 		fSwapDisplaysField = new BMenuField("SwapMenu",
51210dfe897SAxel Dörfler 			B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu);
5136048f541SJohn Scipione 		fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT);
514a10cf76eSAxel Dörfler 
515a10cf76eSAxel Dörfler 		if (!multiMonSupport)
516df3f5bacSStephan Aßmus 			fSwapDisplaysField->Hide();
517a10cf76eSAxel Dörfler 
518551c9f15SSiarzhuk Zharski 		fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel",
519c9e8f97aSAdrien Destugues 			true, true);
520a10cf76eSAxel Dörfler 
521a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
522a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
523a10cf76eSAxel Dörfler 		message->AddBool("use", false);
524c9e8f97aSAdrien Destugues 		fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"),
525c9e8f97aSAdrien Destugues 			message));
526a10cf76eSAxel Dörfler 
527a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
528a10cf76eSAxel Dörfler 		message->AddBool("use", true);
529c9e8f97aSAdrien Destugues 		fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"),
530c9e8f97aSAdrien Destugues 			message));
531a10cf76eSAxel Dörfler 
532b21d610eSAxel Dörfler 		fUseLaptopPanelField = new BMenuField("UseLaptopPanel",
53310dfe897SAxel Dörfler 			B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu);
5346048f541SJohn Scipione 		fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT);
535a10cf76eSAxel Dörfler 
536a10cf76eSAxel Dörfler 		if (!useLaptopPanelSupport)
537df3f5bacSStephan Aßmus 			fUseLaptopPanelField->Hide();
538a10cf76eSAxel Dörfler 
539551c9f15SSiarzhuk Zharski 		fTVStandardMenu = new BPopUpMenu("TVStandard", true, true);
540a10cf76eSAxel Dörfler 
541a10cf76eSAxel Dörfler 		// arbitrary limit
542a10cf76eSAxel Dörfler 		uint32 i;
543a10cf76eSAxel Dörfler 		for (i = 0; i < 100; ++i) {
544a10cf76eSAxel Dörfler 			uint32 mode;
545a10cf76eSAxel Dörfler 			if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK)
546a10cf76eSAxel Dörfler 				break;
547a10cf76eSAxel Dörfler 
548a10cf76eSAxel Dörfler 			BString name = tv_standard_to_string(mode);
549a10cf76eSAxel Dörfler 
550a10cf76eSAxel Dörfler 			message = new BMessage(POP_TV_STANDARD_MSG);
551a10cf76eSAxel Dörfler 			message->AddInt32("tv_standard", mode);
552a10cf76eSAxel Dörfler 
553a10cf76eSAxel Dörfler 			fTVStandardMenu->AddItem(new BMenuItem(name.String(), message));
554a10cf76eSAxel Dörfler 		}
555a10cf76eSAxel Dörfler 
556c9e8f97aSAdrien Destugues 		fTVStandardField = new BMenuField("tv standard",
55710dfe897SAxel Dörfler 			B_TRANSLATE("Video format:"), fTVStandardMenu);
558df3f5bacSStephan Aßmus 		fTVStandardField->SetAlignment(B_ALIGN_RIGHT);
559a10cf76eSAxel Dörfler 
560b21d610eSAxel Dörfler 		if (!tvStandardSupport || i == 0)
561df3f5bacSStephan Aßmus 			fTVStandardField->Hide();
562a10cf76eSAxel Dörfler 	}
563a10cf76eSAxel Dörfler 
56425fd5c7bSAlex Wilson 	BLayoutBuilder::Group<>(outerControlsView)
5656048f541SJohn Scipione 		.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
5666048f541SJohn Scipione 			.Add(fResolutionField->CreateLabelLayoutItem(), 0, 0)
5676048f541SJohn Scipione 			.Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0)
5686048f541SJohn Scipione 			.Add(fColorsField->CreateLabelLayoutItem(), 0, 1)
5696048f541SJohn Scipione 			.Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1)
5706048f541SJohn Scipione 			.Add(fRefreshField->CreateLabelLayoutItem(), 0, 2)
5716048f541SJohn Scipione 			.Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2)
5726048f541SJohn Scipione 			.Add(fCombineField->CreateLabelLayoutItem(), 0, 3)
5736048f541SJohn Scipione 			.Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3)
5746048f541SJohn Scipione 			.Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4)
5756048f541SJohn Scipione 			.Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4)
5766048f541SJohn Scipione 			.Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5)
5776048f541SJohn Scipione 			.Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5)
5786048f541SJohn Scipione 			.Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6)
5796048f541SJohn Scipione 			.Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6)
58025fd5c7bSAlex Wilson 		.End();
581df3f5bacSStephan Aßmus 
582abc649b8SWaldemar Kornewald 	// TODO: we don't support getting the screen's preferred settings
583abc649b8SWaldemar Kornewald 	/* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults",
584b21d610eSAxel Dörfler 		new BMessage(BUTTON_DEFAULTS_MSG));*/
585a10cf76eSAxel Dörfler 
586c9e8f97aSAdrien Destugues 	fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"),
587df3f5bacSStephan Aßmus 		new BMessage(BUTTON_APPLY_MSG));
588df3f5bacSStephan Aßmus 	fApplyButton->SetEnabled(false);
58925fd5c7bSAlex Wilson 	BLayoutBuilder::Group<>(outerControlsView)
590b21d610eSAxel Dörfler 		.AddGlue()
59125fd5c7bSAlex Wilson 		.AddGroup(B_HORIZONTAL)
59225fd5c7bSAlex Wilson 			.AddGlue()
59325fd5c7bSAlex Wilson 			.Add(fApplyButton);
594b21d610eSAxel Dörfler 
595c9e8f97aSAdrien Destugues 	fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"),
596b21d610eSAxel Dörfler 		new BMessage(BUTTON_REVERT_MSG));
597b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(false);
598b21d610eSAxel Dörfler 
5994666484fSJohn Scipione 	BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING)
6004666484fSJohn Scipione 		.AddGroup(B_HORIZONTAL)
601a2cb1737SAdrien Destugues 			.AddGroup(B_VERTICAL, 0, 1)
602ef046e3bSJohn Scipione 				.AddStrut(floorf(controlsBox->TopBorderOffset()
603ef046e3bSJohn Scipione 					- fScreenBox->TopBorderOffset()))
604ef046e3bSJohn Scipione 				.Add(fScreenBox)
605ef046e3bSJohn Scipione 				.Add(workspacesView)
60683cc66b3SJohn Scipione 				.End()
6073a2b67b5SAdrien Destugues 			.AddGroup(B_VERTICAL, 0, 1)
608a2cb1737SAdrien Destugues 				.Add(controlsBox, 2)
6093a2b67b5SAdrien Destugues 				.End()
610b21d610eSAxel Dörfler 			.End()
6114666484fSJohn Scipione 		.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
612b21d610eSAxel Dörfler 			.Add(fRevertButton)
6134666484fSJohn Scipione 			.AddGlue()
6144666484fSJohn Scipione 			.End()
615d0ac6099SHumdinger 		.SetInsets(B_USE_WINDOW_SPACING);
616b21d610eSAxel Dörfler 
6175de171daSAxel Dörfler 	_UpdateControls();
61812966d04SAxel Dörfler 	_UpdateMonitor();
6198bf216d6SAxel Dörfler 
6208bf216d6SAxel Dörfler 	MoveOnScreen();
621a10cf76eSAxel Dörfler }
622a10cf76eSAxel Dörfler 
623a10cf76eSAxel Dörfler 
~ScreenWindow()624a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow()
625a10cf76eSAxel Dörfler {
626a10cf76eSAxel Dörfler 	delete fSettings;
627a10cf76eSAxel Dörfler }
628a10cf76eSAxel Dörfler 
629a10cf76eSAxel Dörfler 
630a10cf76eSAxel Dörfler bool
QuitRequested()631a10cf76eSAxel Dörfler ScreenWindow::QuitRequested()
632a10cf76eSAxel Dörfler {
633a10cf76eSAxel Dörfler 	fSettings->SetWindowFrame(Frame());
634199893c3SAxel Dörfler 
635199893c3SAxel Dörfler 	// Write mode of workspace 0 (the boot workspace) to the vesa settings file
636199893c3SAxel Dörfler 	screen_mode vesaMode;
637199893c3SAxel Dörfler 	if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) {
638199893c3SAxel Dörfler 		status_t status = _WriteVesaModeFile(vesaMode);
63912580984SAxel Dörfler 		if (status < B_OK) {
640c9e8f97aSAdrien Destugues 			BString warning = B_TRANSLATE("Could not write VESA mode settings"
641c9e8f97aSAdrien Destugues 				" file:\n\t");
64212580984SAxel Dörfler 			warning << strerror(status);
643aed35104SHumdinger 			BAlert* alert = new BAlert(B_TRANSLATE("Warning"),
644aed35104SHumdinger 				warning.String(), B_TRANSLATE("OK"), NULL,
645aed35104SHumdinger 				NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
646aed35104SHumdinger 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
647aed35104SHumdinger 			alert->Go();
64812580984SAxel Dörfler 		}
64912580984SAxel Dörfler 	}
65012580984SAxel Dörfler 
651a10cf76eSAxel Dörfler 	be_app->PostMessage(B_QUIT_REQUESTED);
652a10cf76eSAxel Dörfler 
653a10cf76eSAxel Dörfler 	return BWindow::QuitRequested();
654a10cf76eSAxel Dörfler }
655a10cf76eSAxel Dörfler 
656a10cf76eSAxel Dörfler 
6575de171daSAxel Dörfler /*!	Update resolution list according to combine mode
6581fc4cb1fSAxel Dörfler 	(some resolutions may not be combinable due to memory restrictions).
659a10cf76eSAxel Dörfler */
660a10cf76eSAxel Dörfler void
_CheckResolutionMenu()6615de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu()
662a10cf76eSAxel Dörfler {
663a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fResolutionMenu->CountItems(); i++)
664a10cf76eSAxel Dörfler 		fResolutionMenu->ItemAt(i)->SetEnabled(false);
665a10cf76eSAxel Dörfler 
666a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
667a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
668a10cf76eSAxel Dörfler 		if (mode.combine != fSelected.combine)
669a10cf76eSAxel Dörfler 			continue;
670a10cf76eSAxel Dörfler 
671a10cf76eSAxel Dörfler 		BString name;
6723961af9fSHumdinger 		name.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32,
6733961af9fSHumdinger 			"The '×' is the Unicode multiplication sign U+00D7"),
6743961af9fSHumdinger 			mode.width, mode.height);
675a10cf76eSAxel Dörfler 
676a10cf76eSAxel Dörfler 		BMenuItem *item = fResolutionMenu->FindItem(name.String());
677a10cf76eSAxel Dörfler 		if (item != NULL)
678a10cf76eSAxel Dörfler 			item->SetEnabled(true);
679a10cf76eSAxel Dörfler 	}
680a10cf76eSAxel Dörfler }
681a10cf76eSAxel Dörfler 
682a10cf76eSAxel Dörfler 
6835de171daSAxel Dörfler /*!	Update color and refresh options according to current mode
6845de171daSAxel Dörfler 	(a color space is made active if there is any mode with
6855de171daSAxel Dörfler 	given resolution and this colour space; same applies for
6865de171daSAxel Dörfler 	refresh rate, though "Other…" is always possible)
687a10cf76eSAxel Dörfler */
688a10cf76eSAxel Dörfler void
_CheckColorMenu()6895de171daSAxel Dörfler ScreenWindow::_CheckColorMenu()
690a10cf76eSAxel Dörfler {
6911fc4cb1fSAxel Dörfler 	int32 supportsAnything = false;
6921fc4cb1fSAxel Dörfler 	int32 index = 0;
6931fc4cb1fSAxel Dörfler 
694a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
6951fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
6961fc4cb1fSAxel Dörfler 			continue;
6971fc4cb1fSAxel Dörfler 
698a10cf76eSAxel Dörfler 		bool supported = false;
699a10cf76eSAxel Dörfler 
700a10cf76eSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
701a10cf76eSAxel Dörfler 			screen_mode mode = fScreenMode.ModeAt(j);
702a10cf76eSAxel Dörfler 
703a10cf76eSAxel Dörfler 			if (fSelected.width == mode.width
704a10cf76eSAxel Dörfler 				&& fSelected.height == mode.height
7051fc4cb1fSAxel Dörfler 				&& kColorSpaces[i].space == mode.space
706a10cf76eSAxel Dörfler 				&& fSelected.combine == mode.combine) {
7071fc4cb1fSAxel Dörfler 				supportsAnything = true;
708a10cf76eSAxel Dörfler 				supported = true;
709a10cf76eSAxel Dörfler 				break;
710a10cf76eSAxel Dörfler 			}
711a10cf76eSAxel Dörfler 		}
712a10cf76eSAxel Dörfler 
7131fc4cb1fSAxel Dörfler 		BMenuItem* item = fColorsMenu->ItemAt(index++);
714a10cf76eSAxel Dörfler 		if (item)
715a10cf76eSAxel Dörfler 			item->SetEnabled(supported);
716a10cf76eSAxel Dörfler 	}
7171fc4cb1fSAxel Dörfler 
7181fc4cb1fSAxel Dörfler 	fColorsField->SetEnabled(supportsAnything);
7191fc4cb1fSAxel Dörfler 
7201fc4cb1fSAxel Dörfler 	if (!supportsAnything)
7211fc4cb1fSAxel Dörfler 		return;
7221fc4cb1fSAxel Dörfler 
7231fc4cb1fSAxel Dörfler 	// Make sure a valid item is selected
7241fc4cb1fSAxel Dörfler 
7251fc4cb1fSAxel Dörfler 	BMenuItem* item = fColorsMenu->FindMarked();
7261fc4cb1fSAxel Dörfler 	bool changed = false;
7271fc4cb1fSAxel Dörfler 
7281fc4cb1fSAxel Dörfler 	if (item != fUserSelectedColorSpace) {
7291fc4cb1fSAxel Dörfler 		if (fUserSelectedColorSpace != NULL
7301fc4cb1fSAxel Dörfler 			&& fUserSelectedColorSpace->IsEnabled()) {
7311fc4cb1fSAxel Dörfler 			fUserSelectedColorSpace->SetMarked(true);
7321fc4cb1fSAxel Dörfler 			item = fUserSelectedColorSpace;
7331fc4cb1fSAxel Dörfler 			changed = true;
7341fc4cb1fSAxel Dörfler 		}
7351fc4cb1fSAxel Dörfler 	}
7361fc4cb1fSAxel Dörfler 	if (item != NULL && !item->IsEnabled()) {
7371fc4cb1fSAxel Dörfler 		// find the next best item
7381fc4cb1fSAxel Dörfler 		int32 index = fColorsMenu->IndexOf(item);
7391fc4cb1fSAxel Dörfler 		bool found = false;
7401fc4cb1fSAxel Dörfler 
7411fc4cb1fSAxel Dörfler 		for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) {
7421fc4cb1fSAxel Dörfler 			item = fColorsMenu->ItemAt(i);
7431fc4cb1fSAxel Dörfler 			if (item->IsEnabled()) {
7441fc4cb1fSAxel Dörfler 				found = true;
7451fc4cb1fSAxel Dörfler 				break;
7461fc4cb1fSAxel Dörfler 			}
7471fc4cb1fSAxel Dörfler 		}
7481fc4cb1fSAxel Dörfler 		if (!found) {
7491fc4cb1fSAxel Dörfler 			// search backwards as well
7501fc4cb1fSAxel Dörfler 			for (int32 i = index - 1; i >= 0; i--) {
7511fc4cb1fSAxel Dörfler 				item = fColorsMenu->ItemAt(i);
7521fc4cb1fSAxel Dörfler 				if (item->IsEnabled())
7531fc4cb1fSAxel Dörfler 					break;
7541fc4cb1fSAxel Dörfler 			}
7551fc4cb1fSAxel Dörfler 		}
7561fc4cb1fSAxel Dörfler 
7571fc4cb1fSAxel Dörfler 		item->SetMarked(true);
7581fc4cb1fSAxel Dörfler 		changed = true;
7591fc4cb1fSAxel Dörfler 	}
7601fc4cb1fSAxel Dörfler 
7611fc4cb1fSAxel Dörfler 	if (changed) {
7621fc4cb1fSAxel Dörfler 		// Update selected space
7631fc4cb1fSAxel Dörfler 
7641fc4cb1fSAxel Dörfler 		BMessage* message = item->Message();
7651fc4cb1fSAxel Dörfler 		int32 space;
7661fc4cb1fSAxel Dörfler 		if (message->FindInt32("space", &space) == B_OK) {
7671fc4cb1fSAxel Dörfler 			fSelected.space = (color_space)space;
7681fc4cb1fSAxel Dörfler 			_UpdateColorLabel();
7691fc4cb1fSAxel Dörfler 		}
7701fc4cb1fSAxel Dörfler 	}
771a10cf76eSAxel Dörfler }
772a10cf76eSAxel Dörfler 
773a10cf76eSAxel Dörfler 
7745de171daSAxel Dörfler /*!	Enable/disable refresh options according to current mode. */
775a10cf76eSAxel Dörfler void
_CheckRefreshMenu()7765de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu()
777a10cf76eSAxel Dörfler {
77829e8a73aSAxel Dörfler 	float min, max;
77929e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max)
78029e8a73aSAxel Dörfler 		return;
781a10cf76eSAxel Dörfler 
78229e8a73aSAxel Dörfler 	for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) {
78329e8a73aSAxel Dörfler 		BMenuItem* item = fRefreshMenu->ItemAt(i);
78429e8a73aSAxel Dörfler 		BMessage* message = item->Message();
78529e8a73aSAxel Dörfler 		float refresh;
78629e8a73aSAxel Dörfler 		if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK)
78729e8a73aSAxel Dörfler 			item->SetEnabled(refresh >= min && refresh <= max);
788a10cf76eSAxel Dörfler 	}
789a10cf76eSAxel Dörfler }
790a10cf76eSAxel Dörfler 
791a10cf76eSAxel Dörfler 
7925de171daSAxel Dörfler /*!	Activate appropriate menu item according to selected refresh rate */
793a10cf76eSAxel Dörfler void
_UpdateRefreshControl()7945de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl()
795a10cf76eSAxel Dörfler {
796e96dd823SPulkoMandy 	if (isnan(fSelected.refresh)) {
797e96dd823SPulkoMandy 		fRefreshMenu->SetEnabled(false);
798e96dd823SPulkoMandy 		fOtherRefresh->SetLabel(B_TRANSLATE("Unknown"));
799e96dd823SPulkoMandy 		fOtherRefresh->SetMarked(true);
800e96dd823SPulkoMandy 		return;
801e96dd823SPulkoMandy 	} else {
802e96dd823SPulkoMandy 		fRefreshMenu->SetEnabled(true);
803e96dd823SPulkoMandy 	}
804e96dd823SPulkoMandy 
8057e44de36SRene Gollent 	for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) {
8067e44de36SRene Gollent 		BMenuItem* item = fRefreshMenu->ItemAt(i);
8077e44de36SRene Gollent 		if (item->Message()->FindFloat("refresh") == fSelected.refresh) {
808a10cf76eSAxel Dörfler 			item->SetMarked(true);
80926747978SAdrien Destugues 			// "Other" items only contains a refresh rate when active
810122d4ef7SMurai Takashi 			if (fOtherRefresh != NULL)
81126747978SAdrien Destugues 				fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS));
812a10cf76eSAxel Dörfler 			return;
813a10cf76eSAxel Dörfler 		}
8147e44de36SRene Gollent 	}
815a10cf76eSAxel Dörfler 
816a10cf76eSAxel Dörfler 	// this is a non-standard refresh rate
8177e44de36SRene Gollent 	if (fOtherRefresh != NULL) {
818a10cf76eSAxel Dörfler 		fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh);
819a10cf76eSAxel Dörfler 		fOtherRefresh->SetMarked(true);
820a10cf76eSAxel Dörfler 
8217e44de36SRene Gollent 		BString string;
8227e44de36SRene Gollent 		refresh_rate_to_string(fSelected.refresh, string);
823a10cf76eSAxel Dörfler 		fRefreshMenu->Superitem()->SetLabel(string.String());
824a10cf76eSAxel Dörfler 
825c9e8f97aSAdrien Destugues 		string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS));
826a10cf76eSAxel Dörfler 		fOtherRefresh->SetLabel(string.String());
827a10cf76eSAxel Dörfler 	}
8287e44de36SRene Gollent }
829a10cf76eSAxel Dörfler 
830a10cf76eSAxel Dörfler 
831a10cf76eSAxel Dörfler void
_UpdateMonitorView()8325de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView()
833a10cf76eSAxel Dörfler {
834a10cf76eSAxel Dörfler 	BMessage updateMessage(UPDATE_DESKTOP_MSG);
835a10cf76eSAxel Dörfler 	updateMessage.AddInt32("width", fSelected.width);
836a10cf76eSAxel Dörfler 	updateMessage.AddInt32("height", fSelected.height);
837a10cf76eSAxel Dörfler 
838a10cf76eSAxel Dörfler 	PostMessage(&updateMessage, fMonitorView);
839a10cf76eSAxel Dörfler }
840a10cf76eSAxel Dörfler 
841a10cf76eSAxel Dörfler 
842a10cf76eSAxel Dörfler void
_UpdateControls()8435de171daSAxel Dörfler ScreenWindow::_UpdateControls()
844a10cf76eSAxel Dörfler {
845b21d610eSAxel Dörfler 	_UpdateWorkspaceButtons();
846b21d610eSAxel Dörfler 
847a10cf76eSAxel Dörfler 	BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays);
848c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
849a10cf76eSAxel Dörfler 		item->SetMarked(true);
850a10cf76eSAxel Dörfler 
851a10cf76eSAxel Dörfler 	item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel);
852c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
853a10cf76eSAxel Dörfler 		item->SetMarked(true);
854a10cf76eSAxel Dörfler 
855a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) {
856a10cf76eSAxel Dörfler 		item = fTVStandardMenu->ItemAt(i);
857a10cf76eSAxel Dörfler 
858a10cf76eSAxel Dörfler 		uint32 tvStandard;
859a10cf76eSAxel Dörfler 		item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard);
860a10cf76eSAxel Dörfler 		if (tvStandard == fSelected.tv_standard) {
861a10cf76eSAxel Dörfler 			if (!item->IsMarked())
862a10cf76eSAxel Dörfler 				item->SetMarked(true);
863a10cf76eSAxel Dörfler 			break;
864a10cf76eSAxel Dörfler 		}
865a10cf76eSAxel Dörfler 	}
866a10cf76eSAxel Dörfler 
8675de171daSAxel Dörfler 	_CheckResolutionMenu();
8685de171daSAxel Dörfler 	_CheckColorMenu();
8695de171daSAxel Dörfler 	_CheckRefreshMenu();
870a10cf76eSAxel Dörfler 
871a10cf76eSAxel Dörfler 	BString string;
872a10cf76eSAxel Dörfler 	resolution_to_string(fSelected, string);
873a10cf76eSAxel Dörfler 	item = fResolutionMenu->FindItem(string.String());
874a10cf76eSAxel Dörfler 
875a10cf76eSAxel Dörfler 	if (item != NULL) {
876a10cf76eSAxel Dörfler 		if (!item->IsMarked())
877a10cf76eSAxel Dörfler 			item->SetMarked(true);
878a10cf76eSAxel Dörfler 	} else {
879a10cf76eSAxel Dörfler 		// this is bad luck - if mode has been set via screen references,
880a10cf76eSAxel Dörfler 		// this case cannot occur; there are three possible solutions:
881a10cf76eSAxel Dörfler 		// 1. add a new resolution to list
882a10cf76eSAxel Dörfler 		//    - we had to remove it as soon as a "valid" one is selected
883a10cf76eSAxel Dörfler 		//    - we don't know which frequencies/bit depths are supported
884a10cf76eSAxel Dörfler 		//    - as long as we haven't the GMT formula to create
885a10cf76eSAxel Dörfler 		//      parameters for any resolution given, we cannot
886a10cf76eSAxel Dörfler 		//      really set current mode - it's just not in the list
887a10cf76eSAxel Dörfler 		// 2. choose nearest resolution
888a10cf76eSAxel Dörfler 		//    - probably a good idea, but implies coding and testing
889a10cf76eSAxel Dörfler 		// 3. choose lowest resolution
890a10cf76eSAxel Dörfler 		//    - do you really think we are so lazy? yes, we are
891a10cf76eSAxel Dörfler 		item = fResolutionMenu->ItemAt(0);
892a10cf76eSAxel Dörfler 		if (item)
893a10cf76eSAxel Dörfler 			item->SetMarked(true);
894a10cf76eSAxel Dörfler 
895a10cf76eSAxel Dörfler 		// okay - at least we set menu label to active resolution
896a10cf76eSAxel Dörfler 		fResolutionMenu->Superitem()->SetLabel(string.String());
897a10cf76eSAxel Dörfler 	}
898a10cf76eSAxel Dörfler 
899a10cf76eSAxel Dörfler 	// mark active combine mode
900a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kCombineModeCount; i++) {
901a10cf76eSAxel Dörfler 		if (kCombineModes[i].mode == fSelected.combine) {
902a10cf76eSAxel Dörfler 			item = fCombineMenu->ItemAt(i);
903c33a865cSJohn Scipione 			if (item != NULL && !item->IsMarked())
904a10cf76eSAxel Dörfler 				item->SetMarked(true);
905a10cf76eSAxel Dörfler 			break;
906a10cf76eSAxel Dörfler 		}
907a10cf76eSAxel Dörfler 	}
908a10cf76eSAxel Dörfler 
909a10cf76eSAxel Dörfler 	item = fColorsMenu->ItemAt(0);
910a10cf76eSAxel Dörfler 
9111fc4cb1fSAxel Dörfler 	for (int32 i = 0, index = 0; i <  kColorSpaceCount; i++) {
9121fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
9131fc4cb1fSAxel Dörfler 			continue;
9141fc4cb1fSAxel Dörfler 
9151fc4cb1fSAxel Dörfler 		if (kColorSpaces[i].space == fSelected.space) {
9161fc4cb1fSAxel Dörfler 			item = fColorsMenu->ItemAt(index);
917a10cf76eSAxel Dörfler 			break;
918a10cf76eSAxel Dörfler 		}
9191fc4cb1fSAxel Dörfler 
9201fc4cb1fSAxel Dörfler 		index++;
921a10cf76eSAxel Dörfler 	}
922a10cf76eSAxel Dörfler 
923c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
924a10cf76eSAxel Dörfler 		item->SetMarked(true);
925a10cf76eSAxel Dörfler 
9261fc4cb1fSAxel Dörfler 	_UpdateColorLabel();
9275de171daSAxel Dörfler 	_UpdateMonitorView();
9285de171daSAxel Dörfler 	_UpdateRefreshControl();
929a10cf76eSAxel Dörfler 
9305de171daSAxel Dörfler 	_CheckApplyEnabled();
931a10cf76eSAxel Dörfler }
932a10cf76eSAxel Dörfler 
933a10cf76eSAxel Dörfler 
93412580984SAxel Dörfler /*! Reflect active mode in chosen settings */
935a10cf76eSAxel Dörfler void
_UpdateActiveMode()9365de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode()
937a10cf76eSAxel Dörfler {
938c491b5adSJohn Scipione 	_UpdateActiveMode(current_workspace());
939c491b5adSJohn Scipione }
940c491b5adSJohn Scipione 
941c491b5adSJohn Scipione 
942c491b5adSJohn Scipione void
_UpdateActiveMode(int32 workspace)943c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace)
944c491b5adSJohn Scipione {
94512580984SAxel Dörfler 	// Usually, this function gets called after a mode
946a10cf76eSAxel Dörfler 	// has been set manually; still, as the graphics driver
947a10cf76eSAxel Dörfler 	// is free to fiddle with mode passed, we better ask
948a10cf76eSAxel Dörfler 	// what kind of mode we actually got
949c491b5adSJohn Scipione 	if (fScreenMode.Get(fActive, workspace) == B_OK) {
950a10cf76eSAxel Dörfler 		fSelected = fActive;
951a10cf76eSAxel Dörfler 
95212966d04SAxel Dörfler 		_UpdateMonitor();
953c491b5adSJohn Scipione 		_BuildSupportedColorSpaces();
9545de171daSAxel Dörfler 		_UpdateControls();
955a10cf76eSAxel Dörfler 	}
956c491b5adSJohn Scipione }
957a10cf76eSAxel Dörfler 
958a10cf76eSAxel Dörfler 
959a10cf76eSAxel Dörfler void
_UpdateWorkspaceButtons()960b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons()
961b21d610eSAxel Dörfler {
962b21d610eSAxel Dörfler 	uint32 columns;
963b21d610eSAxel Dörfler 	uint32 rows;
964b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
965b21d610eSAxel Dörfler 
966a3fa81bdSJohn Scipione 	// Set the max values enabling/disabling the up/down arrows
967b21d610eSAxel Dörfler 
968a3fa81bdSJohn Scipione 	if (rows == 1)
969a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(32);
970a3fa81bdSJohn Scipione 	else if (rows == 2)
971a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(16);
972a3fa81bdSJohn Scipione 	else if (rows <= 4)
973a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(8);
974a3fa81bdSJohn Scipione 	else if (rows <= 8)
975a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(4);
976a3fa81bdSJohn Scipione 	else if (rows <= 16)
977a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(2);
978a3fa81bdSJohn Scipione 	else if (rows <= 32)
979a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(1);
980b21d610eSAxel Dörfler 
981a3fa81bdSJohn Scipione 	if (columns == 1)
982a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(32);
983a3fa81bdSJohn Scipione 	else if (columns == 2)
984a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(16);
985a3fa81bdSJohn Scipione 	else if (columns <= 4)
986a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(8);
987a3fa81bdSJohn Scipione 	else if (columns <= 8)
988a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(4);
989a3fa81bdSJohn Scipione 	else if (columns <= 16)
990a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(2);
991a3fa81bdSJohn Scipione 	else if (columns <= 32)
992a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(1);
993b21d610eSAxel Dörfler }
994b21d610eSAxel Dörfler 
995b21d610eSAxel Dörfler 
996b21d610eSAxel Dörfler void
ScreenChanged(BRect frame,color_space mode)997a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode)
998a10cf76eSAxel Dörfler {
999a10cf76eSAxel Dörfler 	// move window on screen, if necessary
1000a10cf76eSAxel Dörfler 	if (frame.right <= Frame().right
1001a10cf76eSAxel Dörfler 		&& frame.bottom <= Frame().bottom) {
1002a10cf76eSAxel Dörfler 		MoveTo((frame.Width() - Frame().Width()) / 2,
1003a10cf76eSAxel Dörfler 			(frame.Height() - Frame().Height()) / 2);
1004a10cf76eSAxel Dörfler 	}
1005a10cf76eSAxel Dörfler }
1006a10cf76eSAxel Dörfler 
1007a10cf76eSAxel Dörfler 
1008a10cf76eSAxel Dörfler void
WorkspaceActivated(int32 workspace,bool state)1009a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state)
1010a10cf76eSAxel Dörfler {
1011c491b5adSJohn Scipione 	if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) {
1012c491b5adSJohn Scipione 		_UpdateActiveMode(workspace);
1013a10cf76eSAxel Dörfler 
10146edaa0f6SStefano Ceccherini 		BMessage message(UPDATE_DESKTOP_COLOR_MSG);
10156edaa0f6SStefano Ceccherini 		PostMessage(&message, fMonitorView);
1016a10cf76eSAxel Dörfler 	}
1017c491b5adSJohn Scipione }
1018a10cf76eSAxel Dörfler 
1019a10cf76eSAxel Dörfler 
1020a10cf76eSAxel Dörfler void
MessageReceived(BMessage * message)1021a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message)
1022a10cf76eSAxel Dörfler {
1023a10cf76eSAxel Dörfler 	switch (message->what) {
1024a10cf76eSAxel Dörfler 		case WORKSPACE_CHECK_MSG:
10255de171daSAxel Dörfler 			_CheckApplyEnabled();
1026a10cf76eSAxel Dörfler 			break;
1027a10cf76eSAxel Dörfler 
1028b21d610eSAxel Dörfler 		case kMsgWorkspaceColumnsChanged:
1029b21d610eSAxel Dörfler 		{
1030a3fa81bdSJohn Scipione 			uint32 newColumns = (uint32)fColumnsControl->Value();
1031b21d610eSAxel Dörfler 
1032b21d610eSAxel Dörfler 			uint32 rows;
1033b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(NULL, &rows);
1034b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(newColumns, rows);
1035b21d610eSAxel Dörfler 
1036b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
1037a3fa81bdSJohn Scipione 			fRowsControl->SetValue(rows);
1038a3fa81bdSJohn Scipione 				// enables/disables up/down arrows
1039b21d610eSAxel Dörfler 			_CheckApplyEnabled();
1040a3fa81bdSJohn Scipione 
1041b21d610eSAxel Dörfler 			break;
1042b21d610eSAxel Dörfler 		}
1043b21d610eSAxel Dörfler 
1044b21d610eSAxel Dörfler 		case kMsgWorkspaceRowsChanged:
1045b21d610eSAxel Dörfler 		{
1046a3fa81bdSJohn Scipione 			uint32 newRows = (uint32)fRowsControl->Value();
1047b21d610eSAxel Dörfler 
1048b21d610eSAxel Dörfler 			uint32 columns;
1049b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(&columns, NULL);
1050b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(columns, newRows);
1051b21d610eSAxel Dörfler 
1052b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
1053a3fa81bdSJohn Scipione 			fColumnsControl->SetValue(columns);
1054a3fa81bdSJohn Scipione 				// enables/disables up/down arrows
1055b21d610eSAxel Dörfler 			_CheckApplyEnabled();
1056a10cf76eSAxel Dörfler 			break;
1057a10cf76eSAxel Dörfler 		}
1058a10cf76eSAxel Dörfler 
1059a10cf76eSAxel Dörfler 		case POP_RESOLUTION_MSG:
1060a10cf76eSAxel Dörfler 		{
1061a10cf76eSAxel Dörfler 			message->FindInt32("width", &fSelected.width);
1062a10cf76eSAxel Dörfler 			message->FindInt32("height", &fSelected.height);
1063a10cf76eSAxel Dörfler 
10645de171daSAxel Dörfler 			_CheckColorMenu();
10655de171daSAxel Dörfler 			_CheckRefreshMenu();
1066a10cf76eSAxel Dörfler 
10675de171daSAxel Dörfler 			_UpdateMonitorView();
10685de171daSAxel Dörfler 			_UpdateRefreshControl();
1069a10cf76eSAxel Dörfler 
10705de171daSAxel Dörfler 			_CheckApplyEnabled();
1071a10cf76eSAxel Dörfler 			break;
1072a10cf76eSAxel Dörfler 		}
1073a10cf76eSAxel Dörfler 
1074a10cf76eSAxel Dörfler 		case POP_COLORS_MSG:
1075a10cf76eSAxel Dörfler 		{
10761fc4cb1fSAxel Dörfler 			int32 space;
10771fc4cb1fSAxel Dörfler 			if (message->FindInt32("space", &space) != B_OK)
10781fc4cb1fSAxel Dörfler 				break;
1079a10cf76eSAxel Dörfler 
10801fc4cb1fSAxel Dörfler 			int32 index;
10811fc4cb1fSAxel Dörfler 			if (message->FindInt32("index", &index) == B_OK
10821fc4cb1fSAxel Dörfler 				&& fColorsMenu->ItemAt(index) != NULL)
10831fc4cb1fSAxel Dörfler 				fUserSelectedColorSpace = fColorsMenu->ItemAt(index);
10841fc4cb1fSAxel Dörfler 
10851fc4cb1fSAxel Dörfler 			fSelected.space = (color_space)space;
10861fc4cb1fSAxel Dörfler 			_UpdateColorLabel();
1087a10cf76eSAxel Dörfler 
10885de171daSAxel Dörfler 			_CheckApplyEnabled();
1089a10cf76eSAxel Dörfler 			break;
1090a10cf76eSAxel Dörfler 		}
1091a10cf76eSAxel Dörfler 
1092a10cf76eSAxel Dörfler 		case POP_REFRESH_MSG:
1093a40498e2SWaldemar Kornewald 		{
1094a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
1095c9e8f97aSAdrien Destugues 			fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS));
10961fc4cb1fSAxel Dörfler 				// revert "Other…" label - it might have a refresh rate prefix
1097a10cf76eSAxel Dörfler 
10985de171daSAxel Dörfler 			_CheckApplyEnabled();
1099a10cf76eSAxel Dörfler 			break;
1100a40498e2SWaldemar Kornewald 		}
1101a10cf76eSAxel Dörfler 
1102a10cf76eSAxel Dörfler 		case POP_OTHER_REFRESH_MSG:
1103a10cf76eSAxel Dörfler 		{
110429e8a73aSAxel Dörfler 			// make sure menu shows something useful
11055de171daSAxel Dörfler 			_UpdateRefreshControl();
1106a10cf76eSAxel Dörfler 
110729e8a73aSAxel Dörfler 			float min = 0, max = 999;
110829e8a73aSAxel Dörfler 			fScreenMode.GetRefreshLimits(fSelected, min, max);
110929e8a73aSAxel Dörfler 			if (min < gMinRefresh)
111029e8a73aSAxel Dörfler 				min = gMinRefresh;
111129e8a73aSAxel Dörfler 			if (max > gMaxRefresh)
111229e8a73aSAxel Dörfler 				max = gMaxRefresh;
111329e8a73aSAxel Dörfler 
111470a2b1b5SAxel Dörfler 			monitor_info info;
111570a2b1b5SAxel Dörfler 			if (fScreenMode.GetMonitorInfo(info) == B_OK) {
111670a2b1b5SAxel Dörfler 				min = max_c(info.min_vertical_frequency, min);
111770a2b1b5SAxel Dörfler 				max = min_c(info.max_vertical_frequency, max);
111870a2b1b5SAxel Dörfler 			}
111970a2b1b5SAxel Dörfler 
1120c5d10f7aSAxel Dörfler 			RefreshWindow *fRefreshWindow = new RefreshWindow(
112170a2b1b5SAxel Dörfler 				fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh,
112270a2b1b5SAxel Dörfler 				min, max);
1123a10cf76eSAxel Dörfler 			fRefreshWindow->Show();
1124a10cf76eSAxel Dörfler 			break;
1125a10cf76eSAxel Dörfler 		}
1126a10cf76eSAxel Dörfler 
1127a10cf76eSAxel Dörfler 		case SET_CUSTOM_REFRESH_MSG:
1128a10cf76eSAxel Dörfler 		{
1129a10cf76eSAxel Dörfler 			// user pressed "done" in "Other…" refresh dialog;
1130a10cf76eSAxel Dörfler 			// select the refresh rate chosen
1131a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
1132a10cf76eSAxel Dörfler 
11335de171daSAxel Dörfler 			_UpdateRefreshControl();
11345de171daSAxel Dörfler 			_CheckApplyEnabled();
1135a10cf76eSAxel Dörfler 			break;
1136a10cf76eSAxel Dörfler 		}
1137a10cf76eSAxel Dörfler 
1138a10cf76eSAxel Dörfler 		case POP_COMBINE_DISPLAYS_MSG:
1139a10cf76eSAxel Dörfler 		{
1140a10cf76eSAxel Dörfler 			// new combine mode has bee chosen
1141a10cf76eSAxel Dörfler 			int32 mode;
1142a10cf76eSAxel Dörfler 			if (message->FindInt32("mode", &mode) == B_OK)
1143a10cf76eSAxel Dörfler 				fSelected.combine = (combine_mode)mode;
1144a10cf76eSAxel Dörfler 
11455de171daSAxel Dörfler 			_CheckResolutionMenu();
11465de171daSAxel Dörfler 			_CheckApplyEnabled();
1147a10cf76eSAxel Dörfler 			break;
1148a10cf76eSAxel Dörfler 		}
1149a10cf76eSAxel Dörfler 
1150a10cf76eSAxel Dörfler 		case POP_SWAP_DISPLAYS_MSG:
1151a10cf76eSAxel Dörfler 			message->FindBool("swap", &fSelected.swap_displays);
11525de171daSAxel Dörfler 			_CheckApplyEnabled();
1153a10cf76eSAxel Dörfler 			break;
1154a10cf76eSAxel Dörfler 
1155a10cf76eSAxel Dörfler 		case POP_USE_LAPTOP_PANEL_MSG:
1156a10cf76eSAxel Dörfler 			message->FindBool("use", &fSelected.use_laptop_panel);
11575de171daSAxel Dörfler 			_CheckApplyEnabled();
1158a10cf76eSAxel Dörfler 			break;
1159a10cf76eSAxel Dörfler 
1160a10cf76eSAxel Dörfler 		case POP_TV_STANDARD_MSG:
1161a10cf76eSAxel Dörfler 			message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard);
11625de171daSAxel Dörfler 			_CheckApplyEnabled();
1163a10cf76eSAxel Dörfler 			break;
1164a10cf76eSAxel Dörfler 
1165df3f5bacSStephan Aßmus 		case BUTTON_LAUNCH_BACKGROUNDS_MSG:
11666f095d6aSRyan Leavengood 			if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) {
11676f095d6aSRyan Leavengood 				app_info info;
11686f095d6aSRyan Leavengood 				be_roster->GetAppInfo(kBackgroundsSignature, &info);
11696f095d6aSRyan Leavengood 				be_roster->ActivateApp(info.team);
11706f095d6aSRyan Leavengood 			}
1171df3f5bacSStephan Aßmus 			break;
1172df3f5bacSStephan Aßmus 
1173a10cf76eSAxel Dörfler 		case BUTTON_DEFAULTS_MSG:
1174a10cf76eSAxel Dörfler 		{
11754be51fe3SWaldemar Kornewald 			// TODO: get preferred settings of screen
1176a10cf76eSAxel Dörfler 			fSelected.width = 640;
1177a10cf76eSAxel Dörfler 			fSelected.height = 480;
1178a10cf76eSAxel Dörfler 			fSelected.space = B_CMAP8;
1179a10cf76eSAxel Dörfler 			fSelected.refresh = 60.0;
1180a10cf76eSAxel Dörfler 			fSelected.combine = kCombineDisable;
1181a10cf76eSAxel Dörfler 			fSelected.swap_displays = false;
1182a10cf76eSAxel Dörfler 			fSelected.use_laptop_panel = false;
1183a10cf76eSAxel Dörfler 			fSelected.tv_standard = 0;
1184a10cf76eSAxel Dörfler 
1185b21d610eSAxel Dörfler 			// TODO: workspace defaults
1186abc649b8SWaldemar Kornewald 
11875de171daSAxel Dörfler 			_UpdateControls();
1188a10cf76eSAxel Dörfler 			break;
1189a10cf76eSAxel Dörfler 		}
1190a10cf76eSAxel Dörfler 
119110e9b12fSWaldemar Kornewald 		case BUTTON_UNDO_MSG:
119261c5c89bSAxel Dörfler 			fUndoScreenMode.Revert();
11935de171daSAxel Dörfler 			_UpdateActiveMode();
1194abc649b8SWaldemar Kornewald 			break;
1195abc649b8SWaldemar Kornewald 
1196abc649b8SWaldemar Kornewald 		case BUTTON_REVERT_MSG:
1197abc649b8SWaldemar Kornewald 		{
1198abc649b8SWaldemar Kornewald 			fModified = false;
1199199893c3SAxel Dörfler 			fBootWorkspaceApplied = false;
1200abc649b8SWaldemar Kornewald 
1201b21d610eSAxel Dörfler 			// ScreenMode::Revert() assumes that we first set the correct
1202b21d610eSAxel Dörfler 			// number of workspaces
1203b21d610eSAxel Dörfler 
1204b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns,
1205b21d610eSAxel Dörfler 				fOriginalWorkspacesRows);
1206b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
1207b21d610eSAxel Dörfler 
1208a10cf76eSAxel Dörfler 			fScreenMode.Revert();
12093a2b67b5SAdrien Destugues 
12103a2b67b5SAdrien Destugues 			BScreen screen(this);
12113a2b67b5SAdrien Destugues 			screen.SetBrightness(fOriginalBrightness);
12123a2b67b5SAdrien Destugues 			fBrightnessSlider->SetValue(fOriginalBrightness * 255);
12131f2666fdSJadedTuna 
12141f2666fdSJadedTuna 			_UpdateActiveMode();
1215a10cf76eSAxel Dörfler 			break;
1216abc649b8SWaldemar Kornewald 		}
1217a10cf76eSAxel Dörfler 
1218a10cf76eSAxel Dörfler 		case BUTTON_APPLY_MSG:
12195de171daSAxel Dörfler 			_Apply();
1220a10cf76eSAxel Dörfler 			break;
1221a10cf76eSAxel Dörfler 
1222abc649b8SWaldemar Kornewald 		case MAKE_INITIAL_MSG:
1223abc649b8SWaldemar Kornewald 			// user pressed "keep" in confirmation dialog
1224abc649b8SWaldemar Kornewald 			fModified = true;
12255de171daSAxel Dörfler 			_UpdateActiveMode();
1226a10cf76eSAxel Dörfler 			break;
1227a10cf76eSAxel Dörfler 
1228b8a61399SBrian Hill 		case UPDATE_DESKTOP_COLOR_MSG:
1229b8a61399SBrian Hill 			PostMessage(message, fMonitorView);
1230b8a61399SBrian Hill 			break;
1231b8a61399SBrian Hill 
12323a2b67b5SAdrien Destugues 		case SLIDER_BRIGHTNESS_MSG:
12333a2b67b5SAdrien Destugues 		{
12343a2b67b5SAdrien Destugues 			BScreen screen(this);
12353a2b67b5SAdrien Destugues 			screen.SetBrightness(message->FindInt32("be:value") / 255.f);
12363a2b67b5SAdrien Destugues 			_CheckApplyEnabled();
12373a2b67b5SAdrien Destugues 			break;
12383a2b67b5SAdrien Destugues 		}
12393a2b67b5SAdrien Destugues 
1240a10cf76eSAxel Dörfler 		default:
1241a10cf76eSAxel Dörfler 			BWindow::MessageReceived(message);
1242a10cf76eSAxel Dörfler 	}
1243a10cf76eSAxel Dörfler }
1244a10cf76eSAxel Dörfler 
1245a10cf76eSAxel Dörfler 
124612580984SAxel Dörfler status_t
_WriteVesaModeFile(const screen_mode & mode) const124712580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const
124812580984SAxel Dörfler {
124912580984SAxel Dörfler 	BPath path;
125012580984SAxel Dörfler 	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
125112580984SAxel Dörfler 	if (status < B_OK)
125212580984SAxel Dörfler 		return status;
125312580984SAxel Dörfler 
125412580984SAxel Dörfler 	path.Append("kernel/drivers");
125512580984SAxel Dörfler 	status = create_directory(path.Path(), 0755);
125612580984SAxel Dörfler 	if (status < B_OK)
125712580984SAxel Dörfler 		return status;
125812580984SAxel Dörfler 
125912580984SAxel Dörfler 	path.Append("vesa");
126012580984SAxel Dörfler 	BFile file;
126112580984SAxel Dörfler 	status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
126212580984SAxel Dörfler 	if (status < B_OK)
126312580984SAxel Dörfler 		return status;
126412580984SAxel Dörfler 
126512580984SAxel Dörfler 	char buffer[256];
12665084d0d4SAlex Smith 	snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %"
12675084d0d4SAlex Smith 		B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel());
126812580984SAxel Dörfler 
126912580984SAxel Dörfler 	ssize_t bytesWritten = file.Write(buffer, strlen(buffer));
127012580984SAxel Dörfler 	if (bytesWritten < B_OK)
127112580984SAxel Dörfler 		return bytesWritten;
127212580984SAxel Dörfler 
127312580984SAxel Dörfler 	return B_OK;
127412580984SAxel Dörfler }
127512580984SAxel Dörfler 
127612580984SAxel Dörfler 
1277a10cf76eSAxel Dörfler void
_BuildSupportedColorSpaces()12781fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces()
12791fc4cb1fSAxel Dörfler {
12801fc4cb1fSAxel Dörfler 	fSupportedColorSpaces = 0;
12811fc4cb1fSAxel Dörfler 
12821fc4cb1fSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
12831fc4cb1fSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
12841fc4cb1fSAxel Dörfler 			if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) {
12851fc4cb1fSAxel Dörfler 				fSupportedColorSpaces |= 1 << i;
12861fc4cb1fSAxel Dörfler 				break;
12871fc4cb1fSAxel Dörfler 			}
12881fc4cb1fSAxel Dörfler 		}
12891fc4cb1fSAxel Dörfler 	}
12901fc4cb1fSAxel Dörfler }
12911fc4cb1fSAxel Dörfler 
12921fc4cb1fSAxel Dörfler 
12931fc4cb1fSAxel Dörfler void
_CheckApplyEnabled()12945de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled()
1295a10cf76eSAxel Dörfler {
129695ef5044SJanus 	bool applyEnabled = true;
129795ef5044SJanus 
129895ef5044SJanus 	if (fSelected == fActive) {
129995ef5044SJanus 		applyEnabled = false;
130095ef5044SJanus 		if (fAllWorkspacesItem->IsMarked()) {
130195ef5044SJanus 			screen_mode screenMode;
130295ef5044SJanus 			const int32 workspaceCount = count_workspaces();
130395ef5044SJanus 			for (int32 i = 0; i < workspaceCount; i++) {
130495ef5044SJanus 				fScreenMode.Get(screenMode, i);
130595ef5044SJanus 				if (screenMode != fSelected) {
130695ef5044SJanus 					applyEnabled = true;
130795ef5044SJanus 					break;
130895ef5044SJanus 				}
130995ef5044SJanus 			}
131095ef5044SJanus 		}
131195ef5044SJanus 	}
131295ef5044SJanus 
131395ef5044SJanus 	fApplyButton->SetEnabled(applyEnabled);
1314b21d610eSAxel Dörfler 
1315b21d610eSAxel Dörfler 	uint32 columns;
1316b21d610eSAxel Dörfler 	uint32 rows;
1317b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
1318b21d610eSAxel Dörfler 
13193a2b67b5SAdrien Destugues 	BScreen screen(this);
13203a2b67b5SAdrien Destugues 	float brightness = -1;
13213a2b67b5SAdrien Destugues 	screen.GetBrightness(&brightness);
13223a2b67b5SAdrien Destugues 
1323b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns
1324b21d610eSAxel Dörfler 		|| rows != fOriginalWorkspacesRows
13253a2b67b5SAdrien Destugues 		|| brightness != fOriginalBrightness
13265de171daSAxel Dörfler 		|| fSelected != fOriginal);
1327a10cf76eSAxel Dörfler }
1328a10cf76eSAxel Dörfler 
1329a10cf76eSAxel Dörfler 
1330a10cf76eSAxel Dörfler void
_UpdateOriginal()13315de171daSAxel Dörfler ScreenWindow::_UpdateOriginal()
1332abc649b8SWaldemar Kornewald {
1333b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns,
1334b21d610eSAxel Dörfler 		&fOriginalWorkspacesRows);
1335b21d610eSAxel Dörfler 
1336abc649b8SWaldemar Kornewald 	fScreenMode.Get(fOriginal);
1337abc649b8SWaldemar Kornewald 	fScreenMode.UpdateOriginalModes();
1338abc649b8SWaldemar Kornewald }
1339abc649b8SWaldemar Kornewald 
1340abc649b8SWaldemar Kornewald 
1341abc649b8SWaldemar Kornewald void
_UpdateMonitor()134212966d04SAxel Dörfler ScreenWindow::_UpdateMonitor()
134312966d04SAxel Dörfler {
134412966d04SAxel Dörfler 	monitor_info info;
134512966d04SAxel Dörfler 	float diagonalInches;
134612966d04SAxel Dörfler 	status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches);
134755030977SAxel Dörfler 	if (status == B_OK) {
13481a8af605SAxel Dörfler 		char text[512];
134966ab1666SAxel Dörfler 		snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor,
135066ab1666SAxel Dörfler 			info.name[0] ? " " : "", info.name, diagonalInches);
135112966d04SAxel Dörfler 
1352ef046e3bSJohn Scipione 		fScreenBox->SetLabel(text);
135355030977SAxel Dörfler 	} else {
1354ef046e3bSJohn Scipione 		fScreenBox->SetLabel(B_TRANSLATE("Display info"));
135555030977SAxel Dörfler 	}
1356af8f9c31SAxel Dörfler 
13578b46ee25SAdrien Destugues 	// Add info about the graphics device
13588b46ee25SAdrien Destugues 
13598b46ee25SAdrien Destugues 	accelerant_device_info deviceInfo;
13608b46ee25SAdrien Destugues 
13618b46ee25SAdrien Destugues 	if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK) {
13628b46ee25SAdrien Destugues 		BString deviceString;
13638b46ee25SAdrien Destugues 
13648b46ee25SAdrien Destugues 		if (deviceInfo.name[0] && deviceInfo.chipset[0]) {
13658b46ee25SAdrien Destugues 			deviceString.SetToFormat("%s (%s)", deviceInfo.name,
13668b46ee25SAdrien Destugues 				deviceInfo.chipset);
13678b46ee25SAdrien Destugues 		} else if (deviceInfo.name[0] || deviceInfo.chipset[0]) {
13688b46ee25SAdrien Destugues 			deviceString
13698b46ee25SAdrien Destugues 				= deviceInfo.name[0] ? deviceInfo.name : deviceInfo.chipset;
13708b46ee25SAdrien Destugues 		}
13718b46ee25SAdrien Destugues 
13728b46ee25SAdrien Destugues 		fDeviceInfo->SetText(deviceString);
13738b46ee25SAdrien Destugues 	}
13748b46ee25SAdrien Destugues 
13758b46ee25SAdrien Destugues 
137655030977SAxel Dörfler 	char text[512];
13771a8af605SAxel Dörfler 	size_t length = 0;
13781a8af605SAxel Dörfler 	text[0] = 0;
13791a8af605SAxel Dörfler 
138055030977SAxel Dörfler 	if (status == B_OK) {
1381af8f9c31SAxel Dörfler 		if (info.min_horizontal_frequency != 0
1382af8f9c31SAxel Dörfler 			&& info.min_vertical_frequency != 0
1383af8f9c31SAxel Dörfler 			&& info.max_pixel_clock != 0) {
13841a8af605SAxel Dörfler 			length = snprintf(text, sizeof(text),
1385c9e8f97aSAdrien Destugues 				B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n"
13869c1a9b92SAdrien Destugues 					"Vertical frequency:\t%lu - %lu Hz\n\n"
1387c9e8f97aSAdrien Destugues 					"Maximum pixel clock:\t%g MHz"),
13887eab6b48SPulkoMandy 				(long unsigned)info.min_horizontal_frequency,
13897eab6b48SPulkoMandy 				(long unsigned)info.max_horizontal_frequency,
13907eab6b48SPulkoMandy 				(long unsigned)info.min_vertical_frequency,
13917eab6b48SPulkoMandy 				(long unsigned)info.max_vertical_frequency,
13921a8af605SAxel Dörfler 				info.max_pixel_clock / 1000.0);
1393af8f9c31SAxel Dörfler 		}
13941a8af605SAxel Dörfler 		if (info.serial_number[0] && length < sizeof(text)) {
1395e96dd823SPulkoMandy 			if (length > 0) {
1396e96dd823SPulkoMandy 				text[length++] = '\n';
1397e96dd823SPulkoMandy 				text[length++] = '\n';
1398e96dd823SPulkoMandy 				text[length] = '\0';
1399e96dd823SPulkoMandy 			}
14001a8af605SAxel Dörfler 			length += snprintf(text + length, sizeof(text) - length,
1401e96dd823SPulkoMandy 				B_TRANSLATE("Serial no.: %s"), info.serial_number);
14021a8af605SAxel Dörfler 			if (info.produced.week != 0 && info.produced.year != 0
14031a8af605SAxel Dörfler 				&& length < sizeof(text)) {
14041a8af605SAxel Dörfler 				length += snprintf(text + length, sizeof(text) - length,
14051a8af605SAxel Dörfler 					" (%u/%u)", info.produced.week, info.produced.year);
14061a8af605SAxel Dörfler 			}
14071a8af605SAxel Dörfler 		}
140855030977SAxel Dörfler 	}
140961c5c89bSAxel Dörfler 
14101a8af605SAxel Dörfler 	if (text[0])
14111a8af605SAxel Dörfler 		fMonitorView->SetToolTip(text);
141212966d04SAxel Dörfler }
141312966d04SAxel Dörfler 
141412966d04SAxel Dörfler 
141512966d04SAxel Dörfler void
_UpdateColorLabel()14161fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel()
14171fc4cb1fSAxel Dörfler {
14181fc4cb1fSAxel Dörfler 	BString string;
1419551c9f15SSiarzhuk Zharski 	string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel");
14201fc4cb1fSAxel Dörfler 	fColorsMenu->Superitem()->SetLabel(string.String());
14211fc4cb1fSAxel Dörfler }
14221fc4cb1fSAxel Dörfler 
14231fc4cb1fSAxel Dörfler 
14241fc4cb1fSAxel Dörfler void
_Apply()14255de171daSAxel Dörfler ScreenWindow::_Apply()
1426a10cf76eSAxel Dörfler {
1427abc649b8SWaldemar Kornewald 	// make checkpoint, so we can undo these changes
142861c5c89bSAxel Dörfler 	fUndoScreenMode.UpdateOriginalModes();
142961c5c89bSAxel Dörfler 
143007184a9eSAxel Dörfler 	status_t status = fScreenMode.Set(fSelected);
143107184a9eSAxel Dörfler 	if (status == B_OK) {
1432abc649b8SWaldemar Kornewald 		// use the mode that has eventually been set and
1433abc649b8SWaldemar Kornewald 		// thus we know to be working; it can differ from
1434abc649b8SWaldemar Kornewald 		// the mode selected by user due to hardware limitation
1435abc649b8SWaldemar Kornewald 		display_mode newMode;
1436abc649b8SWaldemar Kornewald 		BScreen screen(this);
1437abc649b8SWaldemar Kornewald 		screen.GetMode(&newMode);
1438abc649b8SWaldemar Kornewald 
1439abc649b8SWaldemar Kornewald 		if (fAllWorkspacesItem->IsMarked()) {
1440abc649b8SWaldemar Kornewald 			int32 originatingWorkspace = current_workspace();
144195ef5044SJanus 			const int32 workspaceCount = count_workspaces();
144295ef5044SJanus 			for (int32 i = 0; i < workspaceCount; i++) {
1443abc649b8SWaldemar Kornewald 				if (i != originatingWorkspace)
1444abc649b8SWaldemar Kornewald 					screen.SetMode(i, &newMode, true);
1445abc649b8SWaldemar Kornewald 			}
1446199893c3SAxel Dörfler 			fBootWorkspaceApplied = true;
1447199893c3SAxel Dörfler 		} else {
1448199893c3SAxel Dörfler 			if (current_workspace() == 0)
1449199893c3SAxel Dörfler 				fBootWorkspaceApplied = true;
1450abc649b8SWaldemar Kornewald 		}
1451abc649b8SWaldemar Kornewald 
1452a10cf76eSAxel Dörfler 		fActive = fSelected;
1453a10cf76eSAxel Dörfler 
1454abc649b8SWaldemar Kornewald 		// TODO: only show alert when this is an unknown mode
145541f43d56SAugustin Cavalier 		BAlert* window = new AlertWindow(this);
145641f43d56SAugustin Cavalier 		window->Go(NULL);
145707184a9eSAxel Dörfler 	} else {
145807184a9eSAxel Dörfler 		char message[256];
145907184a9eSAxel Dörfler 		snprintf(message, sizeof(message),
1460c9e8f97aSAdrien Destugues 			B_TRANSLATE("The screen mode could not be set:\n\t%s\n"),
1461c9e8f97aSAdrien Destugues 			screen_errors(status));
1462551c9f15SSiarzhuk Zharski 		BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message,
1463c9e8f97aSAdrien Destugues 			B_TRANSLATE("OK"), NULL, NULL,
146407184a9eSAxel Dörfler 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
1465aed35104SHumdinger 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
146607184a9eSAxel Dörfler 		alert->Go();
1467a10cf76eSAxel Dörfler 	}
146807184a9eSAxel Dörfler }
1469