xref: /haiku/src/preferences/screen/ScreenWindow.cpp (revision d0ac609964842f8cdb6d54b3c539c6c15293e172)
1a10cf76eSAxel Dörfler /*
2*8bf216d6SAxel 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 <MenuItem.h>
37b21d610eSAxel Dörfler #include <MenuField.h>
38b21d610eSAxel Dörfler #include <Messenger.h>
39b21d610eSAxel Dörfler #include <Path.h>
40b21d610eSAxel Dörfler #include <PopUpMenu.h>
41b21d610eSAxel Dörfler #include <Screen.h>
42e1c88201SJohn Scipione #include <SpaceLayoutItem.h>
43a3fa81bdSJohn Scipione #include <Spinner.h>
44b21d610eSAxel Dörfler #include <String.h>
45b21d610eSAxel Dörfler #include <StringView.h>
46b21d610eSAxel Dörfler #include <Roster.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 };
88b21d610eSAxel Dörfler static const int32 kColorSpaceCount
89b21d610eSAxel Dörfler 	= sizeof(kColorSpaces) / sizeof(kColorSpaces[0]);
90a10cf76eSAxel Dörfler 
91a10cf76eSAxel Dörfler // list of standard refresh rates
92a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 };
93b21d610eSAxel Dörfler static const int32 kRefreshRateCount
94b21d610eSAxel Dörfler 	= sizeof(kRefreshRates) / sizeof(kRefreshRates[0]);
95a10cf76eSAxel Dörfler 
96a10cf76eSAxel Dörfler // list of combine modes
97a10cf76eSAxel Dörfler static const struct {
98a10cf76eSAxel Dörfler 	combine_mode	mode;
99a10cf76eSAxel Dörfler 	const char		*name;
100a10cf76eSAxel Dörfler } kCombineModes[] = {
101c9e8f97aSAdrien Destugues 	{ kCombineDisable, B_TRANSLATE("disable") },
102c9e8f97aSAdrien Destugues 	{ kCombineHorizontally, B_TRANSLATE("horizontally") },
103c9e8f97aSAdrien Destugues 	{ kCombineVertically, B_TRANSLATE("vertically") }
104a10cf76eSAxel Dörfler };
105b21d610eSAxel Dörfler static const int32 kCombineModeCount
106b21d610eSAxel Dörfler 	= sizeof(kCombineModes) / sizeof(kCombineModes[0]);
10729e8a73aSAxel Dörfler 
108a10cf76eSAxel Dörfler 
109a10cf76eSAxel Dörfler static BString
110a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode)
111a10cf76eSAxel Dörfler {
112a10cf76eSAxel Dörfler 	switch (mode) {
113a10cf76eSAxel Dörfler 		case 0:		return "disabled";
114a10cf76eSAxel Dörfler 		case 1:		return "NTSC";
115a10cf76eSAxel Dörfler 		case 2:		return "NTSC Japan";
116a10cf76eSAxel Dörfler 		case 3:		return "PAL BDGHI";
117a10cf76eSAxel Dörfler 		case 4:		return "PAL M";
118a10cf76eSAxel Dörfler 		case 5:		return "PAL N";
119a10cf76eSAxel Dörfler 		case 6:		return "SECAM";
120a10cf76eSAxel Dörfler 		case 101:	return "NTSC 443";
121a10cf76eSAxel Dörfler 		case 102:	return "PAL 60";
122a10cf76eSAxel Dörfler 		case 103:	return "PAL NC";
123a10cf76eSAxel Dörfler 		default:
124a10cf76eSAxel Dörfler 		{
125a10cf76eSAxel Dörfler 			BString name;
126a10cf76eSAxel Dörfler 			name << "??? (" << mode << ")";
127a10cf76eSAxel Dörfler 
128a10cf76eSAxel Dörfler 			return name;
129a10cf76eSAxel Dörfler 		}
130a10cf76eSAxel Dörfler 	}
131a10cf76eSAxel Dörfler }
132a10cf76eSAxel Dörfler 
133a10cf76eSAxel Dörfler 
134a10cf76eSAxel Dörfler static void
135a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string)
136a10cf76eSAxel Dörfler {
137a10cf76eSAxel Dörfler 	string << mode.width << " x " << mode.height;
138a10cf76eSAxel Dörfler }
139a10cf76eSAxel Dörfler 
140a10cf76eSAxel Dörfler 
141a10cf76eSAxel Dörfler static void
142a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string,
143a10cf76eSAxel Dörfler 	bool appendUnit = true, bool alwaysWithFraction = false)
144a10cf76eSAxel Dörfler {
1458bf23e3cSAxel Dörfler 	snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3,
1468bf23e3cSAxel Dörfler 		refresh);
147a10cf76eSAxel Dörfler 	string.UnlockBuffer();
148a10cf76eSAxel Dörfler 
149a10cf76eSAxel Dörfler 	if (appendUnit)
150551c9f15SSiarzhuk Zharski 		string << " " << B_TRANSLATE("Hz");
151a10cf76eSAxel Dörfler }
152a10cf76eSAxel Dörfler 
153a10cf76eSAxel Dörfler 
15407184a9eSAxel Dörfler static const char*
15507184a9eSAxel Dörfler screen_errors(status_t status)
15607184a9eSAxel Dörfler {
15707184a9eSAxel Dörfler 	switch (status) {
15807184a9eSAxel Dörfler 		case B_ENTRY_NOT_FOUND:
159c9e8f97aSAdrien Destugues 			return B_TRANSLATE("Unknown mode");
16007184a9eSAxel Dörfler 		// TODO: add more?
16107184a9eSAxel Dörfler 
16207184a9eSAxel Dörfler 		default:
16307184a9eSAxel Dörfler 			return strerror(status);
16407184a9eSAxel Dörfler 	}
16507184a9eSAxel Dörfler }
16607184a9eSAxel Dörfler 
16729e8a73aSAxel Dörfler 
168a3fa81bdSJohn Scipione //	#pragma mark - ScreenWindow
1693dfd20c0SStephan Aßmus 
1703dfd20c0SStephan Aßmus 
1715a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings* settings)
172b21d610eSAxel Dörfler 	:
173560ff447SJonas Sundström 	BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Screen"),
174958e0ca5SJohn Scipione 		B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE
175958e0ca5SJohn Scipione 			| B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES),
1763f953a72SAxel Dörfler 	fIsVesa(false),
177199893c3SAxel Dörfler 	fBootWorkspaceApplied(false),
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 
215b21d610eSAxel Dörfler 	BBox* screenBox = new BBox("screen box");
216e1c88201SJohn Scipione 	BGroupLayout* layout = new BGroupLayout(B_VERTICAL, B_USE_SMALL_SPACING);
217e1c88201SJohn Scipione 	layout->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
218e1c88201SJohn Scipione 		B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
219b21d610eSAxel Dörfler 	screenBox->SetLayout(layout);
220a10cf76eSAxel Dörfler 
22112966d04SAxel Dörfler 	fMonitorInfo = new BStringView("monitor info", "");
222e1c88201SJohn Scipione 	fMonitorInfo->SetAlignment(B_ALIGN_CENTER);
22312966d04SAxel Dörfler 	screenBox->AddChild(fMonitorInfo);
22412966d04SAxel Dörfler 
2258b46ee25SAdrien Destugues 	fDeviceInfo = new BStringView("monitor info", "");
2268b46ee25SAdrien Destugues 	fDeviceInfo->SetAlignment(B_ALIGN_CENTER);
2278b46ee25SAdrien Destugues 	screenBox->AddChild(fDeviceInfo);
2288b46ee25SAdrien Destugues 
229*8bf216d6SAxel Dörfler 	float scaling = std::max(1.0f, be_plain_font->Size() / 12.0f);
230*8bf216d6SAxel Dörfler 	fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0 * scaling,
231*8bf216d6SAxel Dörfler 			80.0 * scaling), "monitor", screen.Frame().IntegerWidth() + 1,
232c9e8f97aSAdrien Destugues 		screen.Frame().IntegerHeight() + 1);
233b21d610eSAxel Dörfler 	screenBox->AddChild(fMonitorView);
2345a78744bSAxel Dörfler 
235e1c88201SJohn Scipione 	BStringView* workspaces = new BStringView("workspaces",
236e1c88201SJohn Scipione 		B_TRANSLATE("Workspaces"));
237e1c88201SJohn Scipione 	workspaces->SetAlignment(B_ALIGN_CENTER);
238e1c88201SJohn Scipione 
239a3fa81bdSJohn Scipione 	fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"),
240b21d610eSAxel Dörfler 		new BMessage(kMsgWorkspaceColumnsChanged));
241a3fa81bdSJohn Scipione 	fColumnsControl->SetAlignment(B_ALIGN_RIGHT);
242a3fa81bdSJohn Scipione 	fColumnsControl->SetRange(1, 32);
243b21d610eSAxel Dörfler 
244a3fa81bdSJohn Scipione 	fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"),
245a3fa81bdSJohn Scipione 		new BMessage(kMsgWorkspaceRowsChanged));
246a3fa81bdSJohn Scipione 	fRowsControl->SetAlignment(B_ALIGN_RIGHT);
247a3fa81bdSJohn Scipione 	fRowsControl->SetRange(1, 32);
248a3fa81bdSJohn Scipione 
249a3fa81bdSJohn Scipione 	uint32 columns;
250a3fa81bdSJohn Scipione 	uint32 rows;
251a3fa81bdSJohn Scipione 	BPrivate::get_workspaces_layout(&columns, &rows);
252a3fa81bdSJohn Scipione 	fColumnsControl->SetValue(columns);
253a3fa81bdSJohn Scipione 	fRowsControl->SetValue(rows);
254a3fa81bdSJohn Scipione 
255e1c88201SJohn Scipione 	screenBox->AddChild(BLayoutBuilder::Group<>()
256e1c88201SJohn Scipione 		.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
257e1c88201SJohn Scipione 			.Add(workspaces)
258a3fa81bdSJohn Scipione 			.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
259e1c88201SJohn Scipione 				// columns
260e1c88201SJohn Scipione 				.Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0)
261a3fa81bdSJohn Scipione 				.Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0)
262e1c88201SJohn Scipione 				// rows
263e1c88201SJohn Scipione 				.Add(fRowsControl->CreateLabelLayoutItem(), 0, 1)
264a3fa81bdSJohn Scipione 				.Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1)
265b21d610eSAxel Dörfler 				.End()
26625fd5c7bSAlex Wilson 			.End()
26725fd5c7bSAlex Wilson 		.View());
268b21d610eSAxel Dörfler 
269b21d610eSAxel Dörfler 	fBackgroundsButton = new BButton("BackgroundsButton",
270c9e8f97aSAdrien Destugues 		B_TRANSLATE("Set background" B_UTF8_ELLIPSIS),
271b21d610eSAxel Dörfler 		new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG));
272b21d610eSAxel Dörfler 	fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9);
273b21d610eSAxel Dörfler 	screenBox->AddChild(fBackgroundsButton);
274a10cf76eSAxel Dörfler 
275a10cf76eSAxel Dörfler 	// box on the right with screen resolution, etc.
276a10cf76eSAxel Dörfler 
277b21d610eSAxel Dörfler 	BBox* controlsBox = new BBox("controls box");
278b21d610eSAxel Dörfler 	controlsBox->SetLabel(workspaceMenuField);
2796048f541SJohn Scipione 	BGroupView* outerControlsView = new BGroupView(B_VERTICAL);
2806048f541SJohn Scipione 	outerControlsView->GroupLayout()->SetInsets(B_USE_DEFAULT_SPACING,
2816048f541SJohn Scipione 		B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
282b21d610eSAxel Dörfler 	controlsBox->AddChild(outerControlsView);
283a10cf76eSAxel Dörfler 
284551c9f15SSiarzhuk Zharski 	fResolutionMenu = new BPopUpMenu("resolution", true, true);
285a10cf76eSAxel Dörfler 
28666ab1666SAxel Dörfler 	uint16 maxWidth = 0;
28766ab1666SAxel Dörfler 	uint16 maxHeight = 0;
28866ab1666SAxel Dörfler 	uint16 previousWidth = 0;
28966ab1666SAxel Dörfler 	uint16 previousHeight = 0;
290a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
291a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
292a10cf76eSAxel Dörfler 
293a10cf76eSAxel Dörfler 		if (mode.width == previousWidth && mode.height == previousHeight)
294a10cf76eSAxel Dörfler 			continue;
295a10cf76eSAxel Dörfler 
296a10cf76eSAxel Dörfler 		previousWidth = mode.width;
297a10cf76eSAxel Dörfler 		previousHeight = mode.height;
29866ab1666SAxel Dörfler 		if (maxWidth < mode.width)
29966ab1666SAxel Dörfler 			maxWidth = mode.width;
30066ab1666SAxel Dörfler 		if (maxHeight < mode.height)
30166ab1666SAxel Dörfler 			maxHeight = mode.height;
302a10cf76eSAxel Dörfler 
303a10cf76eSAxel Dörfler 		BMessage* message = new BMessage(POP_RESOLUTION_MSG);
304a10cf76eSAxel Dörfler 		message->AddInt32("width", mode.width);
305a10cf76eSAxel Dörfler 		message->AddInt32("height", mode.height);
306a10cf76eSAxel Dörfler 
307a10cf76eSAxel Dörfler 		BString name;
308a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
309a10cf76eSAxel Dörfler 
310a10cf76eSAxel Dörfler 		fResolutionMenu->AddItem(new BMenuItem(name.String(), message));
311a10cf76eSAxel Dörfler 	}
312a10cf76eSAxel Dörfler 
31366ab1666SAxel Dörfler 	fMonitorView->SetMaxResolution(maxWidth, maxHeight);
31466ab1666SAxel Dörfler 
315c9e8f97aSAdrien Destugues 	fResolutionField = new BMenuField("ResolutionMenu",
31610dfe897SAxel Dörfler 		B_TRANSLATE("Resolution:"), fResolutionMenu);
3176048f541SJohn Scipione 	fResolutionField->SetAlignment(B_ALIGN_RIGHT);
318a10cf76eSAxel Dörfler 
319551c9f15SSiarzhuk Zharski 	fColorsMenu = new BPopUpMenu("colors", true, false);
320a10cf76eSAxel Dörfler 
321a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
3221fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
3231fc4cb1fSAxel Dörfler 			continue;
3241fc4cb1fSAxel Dörfler 
325a10cf76eSAxel Dörfler 		BMessage* message = new BMessage(POP_COLORS_MSG);
326a10cf76eSAxel Dörfler 		message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
327a10cf76eSAxel Dörfler 		message->AddInt32("space", kColorSpaces[i].space);
328a10cf76eSAxel Dörfler 
3291fc4cb1fSAxel Dörfler 		BMenuItem* item = new BMenuItem(kColorSpaces[i].label, message);
3301fc4cb1fSAxel Dörfler 		if (kColorSpaces[i].space == screen.ColorSpace())
3311fc4cb1fSAxel Dörfler 			fUserSelectedColorSpace = item;
3321fc4cb1fSAxel Dörfler 
3331fc4cb1fSAxel Dörfler 		fColorsMenu->AddItem(item);
334a10cf76eSAxel Dörfler 	}
335a10cf76eSAxel Dörfler 
336c9e8f97aSAdrien Destugues 	fColorsField = new BMenuField("ColorsMenu", B_TRANSLATE("Colors:"),
33710dfe897SAxel Dörfler 		fColorsMenu);
3386048f541SJohn Scipione 	fColorsField->SetAlignment(B_ALIGN_RIGHT);
339a10cf76eSAxel Dörfler 
340551c9f15SSiarzhuk Zharski 	fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
341a10cf76eSAxel Dörfler 
34229e8a73aSAxel Dörfler 	float min, max;
343ec495b30SRene Gollent 	if (fScreenMode.GetRefreshLimits(fActive, min, max) != B_OK) {
344ec495b30SRene Gollent 		// if we couldn't obtain the refresh limits, reset to the default
345ec495b30SRene Gollent 		// range. Constraints from detected monitors will fine-tune this
346ec495b30SRene Gollent 		// later.
347ec495b30SRene Gollent 		min = kRefreshRates[0];
348ec495b30SRene Gollent 		max = kRefreshRates[kRefreshRateCount - 1];
349ec495b30SRene Gollent 	}
350ec495b30SRene Gollent 
351ec495b30SRene Gollent 	if (min == max) {
35229e8a73aSAxel Dörfler 		// This is a special case for drivers that only support a single
35329e8a73aSAxel Dörfler 		// frequency, like the VESA driver
35429e8a73aSAxel Dörfler 		BString name;
3557e44de36SRene Gollent 		refresh_rate_to_string(min, name);
356cf076964SRene Gollent 		BMessage *message = new BMessage(POP_REFRESH_MSG);
357cf076964SRene Gollent 		message->AddFloat("refresh", min);
358cf076964SRene Gollent 		BMenuItem *item = new BMenuItem(name.String(), message);
3590efb8b66SJerome Duval 		fRefreshMenu->AddItem(item);
36029e8a73aSAxel Dörfler 		item->SetEnabled(false);
36129e8a73aSAxel Dörfler 	} else {
36270a2b1b5SAxel Dörfler 		monitor_info info;
36370a2b1b5SAxel Dörfler 		if (fScreenMode.GetMonitorInfo(info) == B_OK) {
36470a2b1b5SAxel Dörfler 			min = max_c(info.min_vertical_frequency, min);
36570a2b1b5SAxel Dörfler 			max = min_c(info.max_vertical_frequency, max);
36670a2b1b5SAxel Dörfler 		}
36770a2b1b5SAxel Dörfler 
368a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kRefreshRateCount; ++i) {
36970a2b1b5SAxel Dörfler 			if (kRefreshRates[i] < min || kRefreshRates[i] > max)
37070a2b1b5SAxel Dörfler 				continue;
37170a2b1b5SAxel Dörfler 
372a10cf76eSAxel Dörfler 			BString name;
373551c9f15SSiarzhuk Zharski 			name << kRefreshRates[i] << " " << B_TRANSLATE("Hz");
374a10cf76eSAxel Dörfler 
3750efb8b66SJerome Duval 			BMessage *message = new BMessage(POP_REFRESH_MSG);
376a10cf76eSAxel Dörfler 			message->AddFloat("refresh", kRefreshRates[i]);
377a10cf76eSAxel Dörfler 
378a10cf76eSAxel Dörfler 			fRefreshMenu->AddItem(new BMenuItem(name.String(), message));
379a10cf76eSAxel Dörfler 		}
380a10cf76eSAxel Dörfler 
381c9e8f97aSAdrien Destugues 		fOtherRefresh = new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS),
3820efb8b66SJerome Duval 			new BMessage(POP_OTHER_REFRESH_MSG));
383a10cf76eSAxel Dörfler 		fRefreshMenu->AddItem(fOtherRefresh);
38429e8a73aSAxel Dörfler 	}
385a10cf76eSAxel Dörfler 
386c9e8f97aSAdrien Destugues 	fRefreshField = new BMenuField("RefreshMenu", B_TRANSLATE("Refresh rate:"),
38710dfe897SAxel Dörfler 		fRefreshMenu);
3886048f541SJohn Scipione 	fRefreshField->SetAlignment(B_ALIGN_RIGHT);
389b21d610eSAxel Dörfler 
39012580984SAxel Dörfler 	if (_IsVesa())
39112580984SAxel Dörfler 		fRefreshField->Hide();
392a10cf76eSAxel Dörfler 
393a10cf76eSAxel Dörfler 	// enlarged area for multi-monitor settings
394a10cf76eSAxel Dörfler 	{
395a10cf76eSAxel Dörfler 		bool dummy;
396a10cf76eSAxel Dörfler 		uint32 dummy32;
397a10cf76eSAxel Dörfler 		bool multiMonSupport;
398a10cf76eSAxel Dörfler 		bool useLaptopPanelSupport;
399a10cf76eSAxel Dörfler 		bool tvStandardSupport;
400a10cf76eSAxel Dörfler 
401a10cf76eSAxel Dörfler 		multiMonSupport = TestMultiMonSupport(&screen) == B_OK;
402a10cf76eSAxel Dörfler 		useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK;
403a10cf76eSAxel Dörfler 		tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK;
404a10cf76eSAxel Dörfler 
405a10cf76eSAxel Dörfler 		// even if there is no support, we still create all controls
406a10cf76eSAxel Dörfler 		// to make sure we don't access NULL pointers later on
407a10cf76eSAxel Dörfler 
408551c9f15SSiarzhuk Zharski 		fCombineMenu = new BPopUpMenu("CombineDisplays",
409c9e8f97aSAdrien Destugues 			true, true);
410a10cf76eSAxel Dörfler 
411a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kCombineModeCount; i++) {
4120efb8b66SJerome Duval 			BMessage *message = new BMessage(POP_COMBINE_DISPLAYS_MSG);
413a10cf76eSAxel Dörfler 			message->AddInt32("mode", kCombineModes[i].mode);
414a10cf76eSAxel Dörfler 
415d1516993SAxel Dörfler 			fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name,
416d1516993SAxel Dörfler 				message));
417a10cf76eSAxel Dörfler 		}
418a10cf76eSAxel Dörfler 
419b21d610eSAxel Dörfler 		fCombineField = new BMenuField("CombineMenu",
42010dfe897SAxel Dörfler 			B_TRANSLATE("Combine displays:"), fCombineMenu);
4216048f541SJohn Scipione 		fCombineField->SetAlignment(B_ALIGN_RIGHT);
422a10cf76eSAxel Dörfler 
423a10cf76eSAxel Dörfler 		if (!multiMonSupport)
424df3f5bacSStephan Aßmus 			fCombineField->Hide();
425a10cf76eSAxel Dörfler 
426551c9f15SSiarzhuk Zharski 		fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays",
427c9e8f97aSAdrien Destugues 			true, true);
428a10cf76eSAxel Dörfler 
429a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
4300efb8b66SJerome Duval 		BMessage *message = new BMessage(POP_SWAP_DISPLAYS_MSG);
431a10cf76eSAxel Dörfler 		message->AddBool("swap", false);
432c9e8f97aSAdrien Destugues 		fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("no"), message));
433a10cf76eSAxel Dörfler 
434a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
435a10cf76eSAxel Dörfler 		message->AddBool("swap", true);
436c9e8f97aSAdrien Destugues 		fSwapDisplaysMenu->AddItem(new BMenuItem(B_TRANSLATE("yes"), message));
437a10cf76eSAxel Dörfler 
438c9e8f97aSAdrien Destugues 		fSwapDisplaysField = new BMenuField("SwapMenu",
43910dfe897SAxel Dörfler 			B_TRANSLATE("Swap displays:"), fSwapDisplaysMenu);
4406048f541SJohn Scipione 		fSwapDisplaysField->SetAlignment(B_ALIGN_RIGHT);
441a10cf76eSAxel Dörfler 
442a10cf76eSAxel Dörfler 		if (!multiMonSupport)
443df3f5bacSStephan Aßmus 			fSwapDisplaysField->Hide();
444a10cf76eSAxel Dörfler 
445551c9f15SSiarzhuk Zharski 		fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel",
446c9e8f97aSAdrien Destugues 			true, true);
447a10cf76eSAxel Dörfler 
448a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
449a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
450a10cf76eSAxel Dörfler 		message->AddBool("use", false);
451c9e8f97aSAdrien Destugues 		fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("if needed"),
452c9e8f97aSAdrien Destugues 			message));
453a10cf76eSAxel Dörfler 
454a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
455a10cf76eSAxel Dörfler 		message->AddBool("use", true);
456c9e8f97aSAdrien Destugues 		fUseLaptopPanelMenu->AddItem(new BMenuItem(B_TRANSLATE("always"),
457c9e8f97aSAdrien Destugues 			message));
458a10cf76eSAxel Dörfler 
459b21d610eSAxel Dörfler 		fUseLaptopPanelField = new BMenuField("UseLaptopPanel",
46010dfe897SAxel Dörfler 			B_TRANSLATE("Use laptop panel:"), fUseLaptopPanelMenu);
4616048f541SJohn Scipione 		fUseLaptopPanelField->SetAlignment(B_ALIGN_RIGHT);
462a10cf76eSAxel Dörfler 
463a10cf76eSAxel Dörfler 		if (!useLaptopPanelSupport)
464df3f5bacSStephan Aßmus 			fUseLaptopPanelField->Hide();
465a10cf76eSAxel Dörfler 
466551c9f15SSiarzhuk Zharski 		fTVStandardMenu = new BPopUpMenu("TVStandard", true, true);
467a10cf76eSAxel Dörfler 
468a10cf76eSAxel Dörfler 		// arbitrary limit
469a10cf76eSAxel Dörfler 		uint32 i;
470a10cf76eSAxel Dörfler 		for (i = 0; i < 100; ++i) {
471a10cf76eSAxel Dörfler 			uint32 mode;
472a10cf76eSAxel Dörfler 			if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK)
473a10cf76eSAxel Dörfler 				break;
474a10cf76eSAxel Dörfler 
475a10cf76eSAxel Dörfler 			BString name = tv_standard_to_string(mode);
476a10cf76eSAxel Dörfler 
477a10cf76eSAxel Dörfler 			message = new BMessage(POP_TV_STANDARD_MSG);
478a10cf76eSAxel Dörfler 			message->AddInt32("tv_standard", mode);
479a10cf76eSAxel Dörfler 
480a10cf76eSAxel Dörfler 			fTVStandardMenu->AddItem(new BMenuItem(name.String(), message));
481a10cf76eSAxel Dörfler 		}
482a10cf76eSAxel Dörfler 
483c9e8f97aSAdrien Destugues 		fTVStandardField = new BMenuField("tv standard",
48410dfe897SAxel Dörfler 			B_TRANSLATE("Video format:"), fTVStandardMenu);
485df3f5bacSStephan Aßmus 		fTVStandardField->SetAlignment(B_ALIGN_RIGHT);
486a10cf76eSAxel Dörfler 
487b21d610eSAxel Dörfler 		if (!tvStandardSupport || i == 0)
488df3f5bacSStephan Aßmus 			fTVStandardField->Hide();
489a10cf76eSAxel Dörfler 	}
490a10cf76eSAxel Dörfler 
49125fd5c7bSAlex Wilson 	BLayoutBuilder::Group<>(outerControlsView)
4926048f541SJohn Scipione 		.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
4936048f541SJohn Scipione 			.Add(fResolutionField->CreateLabelLayoutItem(), 0, 0)
4946048f541SJohn Scipione 			.Add(fResolutionField->CreateMenuBarLayoutItem(), 1, 0)
4956048f541SJohn Scipione 			.Add(fColorsField->CreateLabelLayoutItem(), 0, 1)
4966048f541SJohn Scipione 			.Add(fColorsField->CreateMenuBarLayoutItem(), 1, 1)
4976048f541SJohn Scipione 			.Add(fRefreshField->CreateLabelLayoutItem(), 0, 2)
4986048f541SJohn Scipione 			.Add(fRefreshField->CreateMenuBarLayoutItem(), 1, 2)
4996048f541SJohn Scipione 			.Add(fCombineField->CreateLabelLayoutItem(), 0, 3)
5006048f541SJohn Scipione 			.Add(fCombineField->CreateMenuBarLayoutItem(), 1, 3)
5016048f541SJohn Scipione 			.Add(fSwapDisplaysField->CreateLabelLayoutItem(), 0, 4)
5026048f541SJohn Scipione 			.Add(fSwapDisplaysField->CreateMenuBarLayoutItem(), 1, 4)
5036048f541SJohn Scipione 			.Add(fUseLaptopPanelField->CreateLabelLayoutItem(), 0, 5)
5046048f541SJohn Scipione 			.Add(fUseLaptopPanelField->CreateMenuBarLayoutItem(), 1, 5)
5056048f541SJohn Scipione 			.Add(fTVStandardField->CreateLabelLayoutItem(), 0, 6)
5066048f541SJohn Scipione 			.Add(fTVStandardField->CreateMenuBarLayoutItem(), 1, 6)
50725fd5c7bSAlex Wilson 		.End();
508df3f5bacSStephan Aßmus 
509abc649b8SWaldemar Kornewald 	// TODO: we don't support getting the screen's preferred settings
510abc649b8SWaldemar Kornewald 	/* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults",
511b21d610eSAxel Dörfler 		new BMessage(BUTTON_DEFAULTS_MSG));*/
512a10cf76eSAxel Dörfler 
513c9e8f97aSAdrien Destugues 	fApplyButton = new BButton("ApplyButton", B_TRANSLATE("Apply"),
514df3f5bacSStephan Aßmus 		new BMessage(BUTTON_APPLY_MSG));
515df3f5bacSStephan Aßmus 	fApplyButton->SetEnabled(false);
51625fd5c7bSAlex Wilson 	BLayoutBuilder::Group<>(outerControlsView)
517b21d610eSAxel Dörfler 		.AddGlue()
51825fd5c7bSAlex Wilson 		.AddGroup(B_HORIZONTAL)
51925fd5c7bSAlex Wilson 			.AddGlue()
52025fd5c7bSAlex Wilson 			.Add(fApplyButton);
521b21d610eSAxel Dörfler 
522c9e8f97aSAdrien Destugues 	fRevertButton = new BButton("RevertButton", B_TRANSLATE("Revert"),
523b21d610eSAxel Dörfler 		new BMessage(BUTTON_REVERT_MSG));
524b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(false);
525b21d610eSAxel Dörfler 
5264666484fSJohn Scipione 	BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING)
5274666484fSJohn Scipione 		.AddGroup(B_HORIZONTAL)
528a2cb1737SAdrien Destugues 			.AddGroup(B_VERTICAL, 0, 1)
52983cc66b3SJohn Scipione 				.AddStrut(floorf(controlsBox->TopBorderOffset()) - 1)
530b21d610eSAxel Dörfler 				.Add(screenBox)
53183cc66b3SJohn Scipione 				.End()
532a2cb1737SAdrien Destugues 			.Add(controlsBox, 2)
533b21d610eSAxel Dörfler 			.End()
5344666484fSJohn Scipione 		.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
535b21d610eSAxel Dörfler 			.Add(fRevertButton)
5364666484fSJohn Scipione 			.AddGlue()
5374666484fSJohn Scipione 			.End()
538d0ac6099SHumdinger 		.SetInsets(B_USE_WINDOW_SPACING);
539b21d610eSAxel Dörfler 
5405de171daSAxel Dörfler 	_UpdateControls();
54112966d04SAxel Dörfler 	_UpdateMonitor();
542*8bf216d6SAxel Dörfler 
543*8bf216d6SAxel Dörfler 	MoveOnScreen();
544a10cf76eSAxel Dörfler }
545a10cf76eSAxel Dörfler 
546a10cf76eSAxel Dörfler 
547a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow()
548a10cf76eSAxel Dörfler {
549a10cf76eSAxel Dörfler 	delete fSettings;
550a10cf76eSAxel Dörfler }
551a10cf76eSAxel Dörfler 
552a10cf76eSAxel Dörfler 
553a10cf76eSAxel Dörfler bool
554a10cf76eSAxel Dörfler ScreenWindow::QuitRequested()
555a10cf76eSAxel Dörfler {
556a10cf76eSAxel Dörfler 	fSettings->SetWindowFrame(Frame());
557199893c3SAxel Dörfler 
558199893c3SAxel Dörfler 	// Write mode of workspace 0 (the boot workspace) to the vesa settings file
559199893c3SAxel Dörfler 	screen_mode vesaMode;
560199893c3SAxel Dörfler 	if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) {
561199893c3SAxel Dörfler 		status_t status = _WriteVesaModeFile(vesaMode);
56212580984SAxel Dörfler 		if (status < B_OK) {
563c9e8f97aSAdrien Destugues 			BString warning = B_TRANSLATE("Could not write VESA mode settings"
564c9e8f97aSAdrien Destugues 				" file:\n\t");
56512580984SAxel Dörfler 			warning << strerror(status);
566aed35104SHumdinger 			BAlert* alert = new BAlert(B_TRANSLATE("Warning"),
567aed35104SHumdinger 				warning.String(), B_TRANSLATE("OK"), NULL,
568aed35104SHumdinger 				NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
569aed35104SHumdinger 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
570aed35104SHumdinger 			alert->Go();
57112580984SAxel Dörfler 		}
57212580984SAxel Dörfler 	}
57312580984SAxel Dörfler 
574a10cf76eSAxel Dörfler 	be_app->PostMessage(B_QUIT_REQUESTED);
575a10cf76eSAxel Dörfler 
576a10cf76eSAxel Dörfler 	return BWindow::QuitRequested();
577a10cf76eSAxel Dörfler }
578a10cf76eSAxel Dörfler 
579a10cf76eSAxel Dörfler 
5805de171daSAxel Dörfler /*!	Update resolution list according to combine mode
5811fc4cb1fSAxel Dörfler 	(some resolutions may not be combinable due to memory restrictions).
582a10cf76eSAxel Dörfler */
583a10cf76eSAxel Dörfler void
5845de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu()
585a10cf76eSAxel Dörfler {
586a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fResolutionMenu->CountItems(); i++)
587a10cf76eSAxel Dörfler 		fResolutionMenu->ItemAt(i)->SetEnabled(false);
588a10cf76eSAxel Dörfler 
589a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
590a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
591a10cf76eSAxel Dörfler 		if (mode.combine != fSelected.combine)
592a10cf76eSAxel Dörfler 			continue;
593a10cf76eSAxel Dörfler 
594a10cf76eSAxel Dörfler 		BString name;
595a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
596a10cf76eSAxel Dörfler 
597a10cf76eSAxel Dörfler 		BMenuItem *item = fResolutionMenu->FindItem(name.String());
598a10cf76eSAxel Dörfler 		if (item != NULL)
599a10cf76eSAxel Dörfler 			item->SetEnabled(true);
600a10cf76eSAxel Dörfler 	}
601a10cf76eSAxel Dörfler }
602a10cf76eSAxel Dörfler 
603a10cf76eSAxel Dörfler 
6045de171daSAxel Dörfler /*!	Update color and refresh options according to current mode
6055de171daSAxel Dörfler 	(a color space is made active if there is any mode with
6065de171daSAxel Dörfler 	given resolution and this colour space; same applies for
6075de171daSAxel Dörfler 	refresh rate, though "Other…" is always possible)
608a10cf76eSAxel Dörfler */
609a10cf76eSAxel Dörfler void
6105de171daSAxel Dörfler ScreenWindow::_CheckColorMenu()
611a10cf76eSAxel Dörfler {
6121fc4cb1fSAxel Dörfler 	int32 supportsAnything = false;
6131fc4cb1fSAxel Dörfler 	int32 index = 0;
6141fc4cb1fSAxel Dörfler 
615a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
6161fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
6171fc4cb1fSAxel Dörfler 			continue;
6181fc4cb1fSAxel Dörfler 
619a10cf76eSAxel Dörfler 		bool supported = false;
620a10cf76eSAxel Dörfler 
621a10cf76eSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
622a10cf76eSAxel Dörfler 			screen_mode mode = fScreenMode.ModeAt(j);
623a10cf76eSAxel Dörfler 
624a10cf76eSAxel Dörfler 			if (fSelected.width == mode.width
625a10cf76eSAxel Dörfler 				&& fSelected.height == mode.height
6261fc4cb1fSAxel Dörfler 				&& kColorSpaces[i].space == mode.space
627a10cf76eSAxel Dörfler 				&& fSelected.combine == mode.combine) {
6281fc4cb1fSAxel Dörfler 				supportsAnything = true;
629a10cf76eSAxel Dörfler 				supported = true;
630a10cf76eSAxel Dörfler 				break;
631a10cf76eSAxel Dörfler 			}
632a10cf76eSAxel Dörfler 		}
633a10cf76eSAxel Dörfler 
6341fc4cb1fSAxel Dörfler 		BMenuItem* item = fColorsMenu->ItemAt(index++);
635a10cf76eSAxel Dörfler 		if (item)
636a10cf76eSAxel Dörfler 			item->SetEnabled(supported);
637a10cf76eSAxel Dörfler 	}
6381fc4cb1fSAxel Dörfler 
6391fc4cb1fSAxel Dörfler 	fColorsField->SetEnabled(supportsAnything);
6401fc4cb1fSAxel Dörfler 
6411fc4cb1fSAxel Dörfler 	if (!supportsAnything)
6421fc4cb1fSAxel Dörfler 		return;
6431fc4cb1fSAxel Dörfler 
6441fc4cb1fSAxel Dörfler 	// Make sure a valid item is selected
6451fc4cb1fSAxel Dörfler 
6461fc4cb1fSAxel Dörfler 	BMenuItem* item = fColorsMenu->FindMarked();
6471fc4cb1fSAxel Dörfler 	bool changed = false;
6481fc4cb1fSAxel Dörfler 
6491fc4cb1fSAxel Dörfler 	if (item != fUserSelectedColorSpace) {
6501fc4cb1fSAxel Dörfler 		if (fUserSelectedColorSpace != NULL
6511fc4cb1fSAxel Dörfler 			&& fUserSelectedColorSpace->IsEnabled()) {
6521fc4cb1fSAxel Dörfler 			fUserSelectedColorSpace->SetMarked(true);
6531fc4cb1fSAxel Dörfler 			item = fUserSelectedColorSpace;
6541fc4cb1fSAxel Dörfler 			changed = true;
6551fc4cb1fSAxel Dörfler 		}
6561fc4cb1fSAxel Dörfler 	}
6571fc4cb1fSAxel Dörfler 	if (item != NULL && !item->IsEnabled()) {
6581fc4cb1fSAxel Dörfler 		// find the next best item
6591fc4cb1fSAxel Dörfler 		int32 index = fColorsMenu->IndexOf(item);
6601fc4cb1fSAxel Dörfler 		bool found = false;
6611fc4cb1fSAxel Dörfler 
6621fc4cb1fSAxel Dörfler 		for (int32 i = index + 1; i < fColorsMenu->CountItems(); i++) {
6631fc4cb1fSAxel Dörfler 			item = fColorsMenu->ItemAt(i);
6641fc4cb1fSAxel Dörfler 			if (item->IsEnabled()) {
6651fc4cb1fSAxel Dörfler 				found = true;
6661fc4cb1fSAxel Dörfler 				break;
6671fc4cb1fSAxel Dörfler 			}
6681fc4cb1fSAxel Dörfler 		}
6691fc4cb1fSAxel Dörfler 		if (!found) {
6701fc4cb1fSAxel Dörfler 			// search backwards as well
6711fc4cb1fSAxel Dörfler 			for (int32 i = index - 1; i >= 0; i--) {
6721fc4cb1fSAxel Dörfler 				item = fColorsMenu->ItemAt(i);
6731fc4cb1fSAxel Dörfler 				if (item->IsEnabled())
6741fc4cb1fSAxel Dörfler 					break;
6751fc4cb1fSAxel Dörfler 			}
6761fc4cb1fSAxel Dörfler 		}
6771fc4cb1fSAxel Dörfler 
6781fc4cb1fSAxel Dörfler 		item->SetMarked(true);
6791fc4cb1fSAxel Dörfler 		changed = true;
6801fc4cb1fSAxel Dörfler 	}
6811fc4cb1fSAxel Dörfler 
6821fc4cb1fSAxel Dörfler 	if (changed) {
6831fc4cb1fSAxel Dörfler 		// Update selected space
6841fc4cb1fSAxel Dörfler 
6851fc4cb1fSAxel Dörfler 		BMessage* message = item->Message();
6861fc4cb1fSAxel Dörfler 		int32 space;
6871fc4cb1fSAxel Dörfler 		if (message->FindInt32("space", &space) == B_OK) {
6881fc4cb1fSAxel Dörfler 			fSelected.space = (color_space)space;
6891fc4cb1fSAxel Dörfler 			_UpdateColorLabel();
6901fc4cb1fSAxel Dörfler 		}
6911fc4cb1fSAxel Dörfler 	}
692a10cf76eSAxel Dörfler }
693a10cf76eSAxel Dörfler 
694a10cf76eSAxel Dörfler 
6955de171daSAxel Dörfler /*!	Enable/disable refresh options according to current mode. */
696a10cf76eSAxel Dörfler void
6975de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu()
698a10cf76eSAxel Dörfler {
69929e8a73aSAxel Dörfler 	float min, max;
70029e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max)
70129e8a73aSAxel Dörfler 		return;
702a10cf76eSAxel Dörfler 
70329e8a73aSAxel Dörfler 	for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) {
70429e8a73aSAxel Dörfler 		BMenuItem* item = fRefreshMenu->ItemAt(i);
70529e8a73aSAxel Dörfler 		BMessage* message = item->Message();
70629e8a73aSAxel Dörfler 		float refresh;
70729e8a73aSAxel Dörfler 		if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK)
70829e8a73aSAxel Dörfler 			item->SetEnabled(refresh >= min && refresh <= max);
709a10cf76eSAxel Dörfler 	}
710a10cf76eSAxel Dörfler }
711a10cf76eSAxel Dörfler 
712a10cf76eSAxel Dörfler 
7135de171daSAxel Dörfler /*!	Activate appropriate menu item according to selected refresh rate */
714a10cf76eSAxel Dörfler void
7155de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl()
716a10cf76eSAxel Dörfler {
7177e44de36SRene Gollent 	for (int32 i = 0; i < fRefreshMenu->CountItems(); i++) {
7187e44de36SRene Gollent 		BMenuItem* item = fRefreshMenu->ItemAt(i);
7197e44de36SRene Gollent 		if (item->Message()->FindFloat("refresh") == fSelected.refresh) {
720a10cf76eSAxel Dörfler 			item->SetMarked(true);
72126747978SAdrien Destugues 			// "Other" items only contains a refresh rate when active
72226747978SAdrien Destugues 			fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS));
723a10cf76eSAxel Dörfler 			return;
724a10cf76eSAxel Dörfler 		}
7257e44de36SRene Gollent 	}
726a10cf76eSAxel Dörfler 
727a10cf76eSAxel Dörfler 	// this is a non-standard refresh rate
7287e44de36SRene Gollent 	if (fOtherRefresh != NULL) {
729a10cf76eSAxel Dörfler 		fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh);
730a10cf76eSAxel Dörfler 		fOtherRefresh->SetMarked(true);
731a10cf76eSAxel Dörfler 
7327e44de36SRene Gollent 		BString string;
7337e44de36SRene Gollent 		refresh_rate_to_string(fSelected.refresh, string);
734a10cf76eSAxel Dörfler 		fRefreshMenu->Superitem()->SetLabel(string.String());
735a10cf76eSAxel Dörfler 
736c9e8f97aSAdrien Destugues 		string.Append(B_TRANSLATE("/other" B_UTF8_ELLIPSIS));
737a10cf76eSAxel Dörfler 		fOtherRefresh->SetLabel(string.String());
738a10cf76eSAxel Dörfler 	}
7397e44de36SRene Gollent }
740a10cf76eSAxel Dörfler 
741a10cf76eSAxel Dörfler 
742a10cf76eSAxel Dörfler void
7435de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView()
744a10cf76eSAxel Dörfler {
745a10cf76eSAxel Dörfler 	BMessage updateMessage(UPDATE_DESKTOP_MSG);
746a10cf76eSAxel Dörfler 	updateMessage.AddInt32("width", fSelected.width);
747a10cf76eSAxel Dörfler 	updateMessage.AddInt32("height", fSelected.height);
748a10cf76eSAxel Dörfler 
749a10cf76eSAxel Dörfler 	PostMessage(&updateMessage, fMonitorView);
750a10cf76eSAxel Dörfler }
751a10cf76eSAxel Dörfler 
752a10cf76eSAxel Dörfler 
753a10cf76eSAxel Dörfler void
7545de171daSAxel Dörfler ScreenWindow::_UpdateControls()
755a10cf76eSAxel Dörfler {
756b21d610eSAxel Dörfler 	_UpdateWorkspaceButtons();
757b21d610eSAxel Dörfler 
758a10cf76eSAxel Dörfler 	BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays);
759c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
760a10cf76eSAxel Dörfler 		item->SetMarked(true);
761a10cf76eSAxel Dörfler 
762a10cf76eSAxel Dörfler 	item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel);
763c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
764a10cf76eSAxel Dörfler 		item->SetMarked(true);
765a10cf76eSAxel Dörfler 
766a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) {
767a10cf76eSAxel Dörfler 		item = fTVStandardMenu->ItemAt(i);
768a10cf76eSAxel Dörfler 
769a10cf76eSAxel Dörfler 		uint32 tvStandard;
770a10cf76eSAxel Dörfler 		item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard);
771a10cf76eSAxel Dörfler 		if (tvStandard == fSelected.tv_standard) {
772a10cf76eSAxel Dörfler 			if (!item->IsMarked())
773a10cf76eSAxel Dörfler 				item->SetMarked(true);
774a10cf76eSAxel Dörfler 			break;
775a10cf76eSAxel Dörfler 		}
776a10cf76eSAxel Dörfler 	}
777a10cf76eSAxel Dörfler 
7785de171daSAxel Dörfler 	_CheckResolutionMenu();
7795de171daSAxel Dörfler 	_CheckColorMenu();
7805de171daSAxel Dörfler 	_CheckRefreshMenu();
781a10cf76eSAxel Dörfler 
782a10cf76eSAxel Dörfler 	BString string;
783a10cf76eSAxel Dörfler 	resolution_to_string(fSelected, string);
784a10cf76eSAxel Dörfler 	item = fResolutionMenu->FindItem(string.String());
785a10cf76eSAxel Dörfler 
786a10cf76eSAxel Dörfler 	if (item != NULL) {
787a10cf76eSAxel Dörfler 		if (!item->IsMarked())
788a10cf76eSAxel Dörfler 			item->SetMarked(true);
789a10cf76eSAxel Dörfler 	} else {
790a10cf76eSAxel Dörfler 		// this is bad luck - if mode has been set via screen references,
791a10cf76eSAxel Dörfler 		// this case cannot occur; there are three possible solutions:
792a10cf76eSAxel Dörfler 		// 1. add a new resolution to list
793a10cf76eSAxel Dörfler 		//    - we had to remove it as soon as a "valid" one is selected
794a10cf76eSAxel Dörfler 		//    - we don't know which frequencies/bit depths are supported
795a10cf76eSAxel Dörfler 		//    - as long as we haven't the GMT formula to create
796a10cf76eSAxel Dörfler 		//      parameters for any resolution given, we cannot
797a10cf76eSAxel Dörfler 		//      really set current mode - it's just not in the list
798a10cf76eSAxel Dörfler 		// 2. choose nearest resolution
799a10cf76eSAxel Dörfler 		//    - probably a good idea, but implies coding and testing
800a10cf76eSAxel Dörfler 		// 3. choose lowest resolution
801a10cf76eSAxel Dörfler 		//    - do you really think we are so lazy? yes, we are
802a10cf76eSAxel Dörfler 		item = fResolutionMenu->ItemAt(0);
803a10cf76eSAxel Dörfler 		if (item)
804a10cf76eSAxel Dörfler 			item->SetMarked(true);
805a10cf76eSAxel Dörfler 
806a10cf76eSAxel Dörfler 		// okay - at least we set menu label to active resolution
807a10cf76eSAxel Dörfler 		fResolutionMenu->Superitem()->SetLabel(string.String());
808a10cf76eSAxel Dörfler 	}
809a10cf76eSAxel Dörfler 
810a10cf76eSAxel Dörfler 	// mark active combine mode
811a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kCombineModeCount; i++) {
812a10cf76eSAxel Dörfler 		if (kCombineModes[i].mode == fSelected.combine) {
813a10cf76eSAxel Dörfler 			item = fCombineMenu->ItemAt(i);
814c33a865cSJohn Scipione 			if (item != NULL && !item->IsMarked())
815a10cf76eSAxel Dörfler 				item->SetMarked(true);
816a10cf76eSAxel Dörfler 			break;
817a10cf76eSAxel Dörfler 		}
818a10cf76eSAxel Dörfler 	}
819a10cf76eSAxel Dörfler 
820a10cf76eSAxel Dörfler 	item = fColorsMenu->ItemAt(0);
821a10cf76eSAxel Dörfler 
8221fc4cb1fSAxel Dörfler 	for (int32 i = 0, index = 0; i <  kColorSpaceCount; i++) {
8231fc4cb1fSAxel Dörfler 		if ((fSupportedColorSpaces & (1 << i)) == 0)
8241fc4cb1fSAxel Dörfler 			continue;
8251fc4cb1fSAxel Dörfler 
8261fc4cb1fSAxel Dörfler 		if (kColorSpaces[i].space == fSelected.space) {
8271fc4cb1fSAxel Dörfler 			item = fColorsMenu->ItemAt(index);
828a10cf76eSAxel Dörfler 			break;
829a10cf76eSAxel Dörfler 		}
8301fc4cb1fSAxel Dörfler 
8311fc4cb1fSAxel Dörfler 		index++;
832a10cf76eSAxel Dörfler 	}
833a10cf76eSAxel Dörfler 
834c33a865cSJohn Scipione 	if (item != NULL && !item->IsMarked())
835a10cf76eSAxel Dörfler 		item->SetMarked(true);
836a10cf76eSAxel Dörfler 
8371fc4cb1fSAxel Dörfler 	_UpdateColorLabel();
8385de171daSAxel Dörfler 	_UpdateMonitorView();
8395de171daSAxel Dörfler 	_UpdateRefreshControl();
840a10cf76eSAxel Dörfler 
8415de171daSAxel Dörfler 	_CheckApplyEnabled();
842a10cf76eSAxel Dörfler }
843a10cf76eSAxel Dörfler 
844a10cf76eSAxel Dörfler 
84512580984SAxel Dörfler /*! Reflect active mode in chosen settings */
846a10cf76eSAxel Dörfler void
8475de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode()
848a10cf76eSAxel Dörfler {
849c491b5adSJohn Scipione 	_UpdateActiveMode(current_workspace());
850c491b5adSJohn Scipione }
851c491b5adSJohn Scipione 
852c491b5adSJohn Scipione 
853c491b5adSJohn Scipione void
854c491b5adSJohn Scipione ScreenWindow::_UpdateActiveMode(int32 workspace)
855c491b5adSJohn Scipione {
85612580984SAxel Dörfler 	// Usually, this function gets called after a mode
857a10cf76eSAxel Dörfler 	// has been set manually; still, as the graphics driver
858a10cf76eSAxel Dörfler 	// is free to fiddle with mode passed, we better ask
859a10cf76eSAxel Dörfler 	// what kind of mode we actually got
860c491b5adSJohn Scipione 	if (fScreenMode.Get(fActive, workspace) == B_OK) {
861a10cf76eSAxel Dörfler 		fSelected = fActive;
862a10cf76eSAxel Dörfler 
86312966d04SAxel Dörfler 		_UpdateMonitor();
864c491b5adSJohn Scipione 		_BuildSupportedColorSpaces();
8655de171daSAxel Dörfler 		_UpdateControls();
866a10cf76eSAxel Dörfler 	}
867c491b5adSJohn Scipione }
868a10cf76eSAxel Dörfler 
869a10cf76eSAxel Dörfler 
870a10cf76eSAxel Dörfler void
871b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons()
872b21d610eSAxel Dörfler {
873b21d610eSAxel Dörfler 	uint32 columns;
874b21d610eSAxel Dörfler 	uint32 rows;
875b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
876b21d610eSAxel Dörfler 
877a3fa81bdSJohn Scipione 	// Set the max values enabling/disabling the up/down arrows
878b21d610eSAxel Dörfler 
879a3fa81bdSJohn Scipione 	if (rows == 1)
880a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(32);
881a3fa81bdSJohn Scipione 	else if (rows == 2)
882a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(16);
883a3fa81bdSJohn Scipione 	else if (rows <= 4)
884a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(8);
885a3fa81bdSJohn Scipione 	else if (rows <= 8)
886a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(4);
887a3fa81bdSJohn Scipione 	else if (rows <= 16)
888a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(2);
889a3fa81bdSJohn Scipione 	else if (rows <= 32)
890a3fa81bdSJohn Scipione 		fColumnsControl->SetMaxValue(1);
891b21d610eSAxel Dörfler 
892a3fa81bdSJohn Scipione 	if (columns == 1)
893a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(32);
894a3fa81bdSJohn Scipione 	else if (columns == 2)
895a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(16);
896a3fa81bdSJohn Scipione 	else if (columns <= 4)
897a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(8);
898a3fa81bdSJohn Scipione 	else if (columns <= 8)
899a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(4);
900a3fa81bdSJohn Scipione 	else if (columns <= 16)
901a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(2);
902a3fa81bdSJohn Scipione 	else if (columns <= 32)
903a3fa81bdSJohn Scipione 		fRowsControl->SetMaxValue(1);
904b21d610eSAxel Dörfler }
905b21d610eSAxel Dörfler 
906b21d610eSAxel Dörfler 
907b21d610eSAxel Dörfler void
908a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode)
909a10cf76eSAxel Dörfler {
910a10cf76eSAxel Dörfler 	// move window on screen, if necessary
911a10cf76eSAxel Dörfler 	if (frame.right <= Frame().right
912a10cf76eSAxel Dörfler 		&& frame.bottom <= Frame().bottom) {
913a10cf76eSAxel Dörfler 		MoveTo((frame.Width() - Frame().Width()) / 2,
914a10cf76eSAxel Dörfler 			(frame.Height() - Frame().Height()) / 2);
915a10cf76eSAxel Dörfler 	}
916a10cf76eSAxel Dörfler }
917a10cf76eSAxel Dörfler 
918a10cf76eSAxel Dörfler 
919a10cf76eSAxel Dörfler void
920a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state)
921a10cf76eSAxel Dörfler {
922c491b5adSJohn Scipione 	if (fScreenMode.GetOriginalMode(fOriginal, workspace) == B_OK) {
923c491b5adSJohn Scipione 		_UpdateActiveMode(workspace);
924a10cf76eSAxel Dörfler 
9256edaa0f6SStefano Ceccherini 		BMessage message(UPDATE_DESKTOP_COLOR_MSG);
9266edaa0f6SStefano Ceccherini 		PostMessage(&message, fMonitorView);
927a10cf76eSAxel Dörfler 	}
928c491b5adSJohn Scipione }
929a10cf76eSAxel Dörfler 
930a10cf76eSAxel Dörfler 
931a10cf76eSAxel Dörfler void
932a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message)
933a10cf76eSAxel Dörfler {
934a10cf76eSAxel Dörfler 	switch (message->what) {
935a10cf76eSAxel Dörfler 		case WORKSPACE_CHECK_MSG:
9365de171daSAxel Dörfler 			_CheckApplyEnabled();
937a10cf76eSAxel Dörfler 			break;
938a10cf76eSAxel Dörfler 
939b21d610eSAxel Dörfler 		case kMsgWorkspaceColumnsChanged:
940b21d610eSAxel Dörfler 		{
941a3fa81bdSJohn Scipione 			uint32 newColumns = (uint32)fColumnsControl->Value();
942b21d610eSAxel Dörfler 
943b21d610eSAxel Dörfler 			uint32 rows;
944b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(NULL, &rows);
945b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(newColumns, rows);
946b21d610eSAxel Dörfler 
947b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
948a3fa81bdSJohn Scipione 			fRowsControl->SetValue(rows);
949a3fa81bdSJohn Scipione 				// enables/disables up/down arrows
950b21d610eSAxel Dörfler 			_CheckApplyEnabled();
951a3fa81bdSJohn Scipione 
952b21d610eSAxel Dörfler 			break;
953b21d610eSAxel Dörfler 		}
954b21d610eSAxel Dörfler 
955b21d610eSAxel Dörfler 		case kMsgWorkspaceRowsChanged:
956b21d610eSAxel Dörfler 		{
957a3fa81bdSJohn Scipione 			uint32 newRows = (uint32)fRowsControl->Value();
958b21d610eSAxel Dörfler 
959b21d610eSAxel Dörfler 			uint32 columns;
960b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(&columns, NULL);
961b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(columns, newRows);
962b21d610eSAxel Dörfler 
963b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
964a3fa81bdSJohn Scipione 			fColumnsControl->SetValue(columns);
965a3fa81bdSJohn Scipione 				// enables/disables up/down arrows
966b21d610eSAxel Dörfler 			_CheckApplyEnabled();
967a10cf76eSAxel Dörfler 			break;
968a10cf76eSAxel Dörfler 		}
969a10cf76eSAxel Dörfler 
970a10cf76eSAxel Dörfler 		case POP_RESOLUTION_MSG:
971a10cf76eSAxel Dörfler 		{
972a10cf76eSAxel Dörfler 			message->FindInt32("width", &fSelected.width);
973a10cf76eSAxel Dörfler 			message->FindInt32("height", &fSelected.height);
974a10cf76eSAxel Dörfler 
9755de171daSAxel Dörfler 			_CheckColorMenu();
9765de171daSAxel Dörfler 			_CheckRefreshMenu();
977a10cf76eSAxel Dörfler 
9785de171daSAxel Dörfler 			_UpdateMonitorView();
9795de171daSAxel Dörfler 			_UpdateRefreshControl();
980a10cf76eSAxel Dörfler 
9815de171daSAxel Dörfler 			_CheckApplyEnabled();
982a10cf76eSAxel Dörfler 			break;
983a10cf76eSAxel Dörfler 		}
984a10cf76eSAxel Dörfler 
985a10cf76eSAxel Dörfler 		case POP_COLORS_MSG:
986a10cf76eSAxel Dörfler 		{
9871fc4cb1fSAxel Dörfler 			int32 space;
9881fc4cb1fSAxel Dörfler 			if (message->FindInt32("space", &space) != B_OK)
9891fc4cb1fSAxel Dörfler 				break;
990a10cf76eSAxel Dörfler 
9911fc4cb1fSAxel Dörfler 			int32 index;
9921fc4cb1fSAxel Dörfler 			if (message->FindInt32("index", &index) == B_OK
9931fc4cb1fSAxel Dörfler 				&& fColorsMenu->ItemAt(index) != NULL)
9941fc4cb1fSAxel Dörfler 				fUserSelectedColorSpace = fColorsMenu->ItemAt(index);
9951fc4cb1fSAxel Dörfler 
9961fc4cb1fSAxel Dörfler 			fSelected.space = (color_space)space;
9971fc4cb1fSAxel Dörfler 			_UpdateColorLabel();
998a10cf76eSAxel Dörfler 
9995de171daSAxel Dörfler 			_CheckApplyEnabled();
1000a10cf76eSAxel Dörfler 			break;
1001a10cf76eSAxel Dörfler 		}
1002a10cf76eSAxel Dörfler 
1003a10cf76eSAxel Dörfler 		case POP_REFRESH_MSG:
1004a40498e2SWaldemar Kornewald 		{
1005a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
1006c9e8f97aSAdrien Destugues 			fOtherRefresh->SetLabel(B_TRANSLATE("Other" B_UTF8_ELLIPSIS));
10071fc4cb1fSAxel Dörfler 				// revert "Other…" label - it might have a refresh rate prefix
1008a10cf76eSAxel Dörfler 
10095de171daSAxel Dörfler 			_CheckApplyEnabled();
1010a10cf76eSAxel Dörfler 			break;
1011a40498e2SWaldemar Kornewald 		}
1012a10cf76eSAxel Dörfler 
1013a10cf76eSAxel Dörfler 		case POP_OTHER_REFRESH_MSG:
1014a10cf76eSAxel Dörfler 		{
101529e8a73aSAxel Dörfler 			// make sure menu shows something useful
10165de171daSAxel Dörfler 			_UpdateRefreshControl();
1017a10cf76eSAxel Dörfler 
101829e8a73aSAxel Dörfler 			float min = 0, max = 999;
101929e8a73aSAxel Dörfler 			fScreenMode.GetRefreshLimits(fSelected, min, max);
102029e8a73aSAxel Dörfler 			if (min < gMinRefresh)
102129e8a73aSAxel Dörfler 				min = gMinRefresh;
102229e8a73aSAxel Dörfler 			if (max > gMaxRefresh)
102329e8a73aSAxel Dörfler 				max = gMaxRefresh;
102429e8a73aSAxel Dörfler 
102570a2b1b5SAxel Dörfler 			monitor_info info;
102670a2b1b5SAxel Dörfler 			if (fScreenMode.GetMonitorInfo(info) == B_OK) {
102770a2b1b5SAxel Dörfler 				min = max_c(info.min_vertical_frequency, min);
102870a2b1b5SAxel Dörfler 				max = min_c(info.max_vertical_frequency, max);
102970a2b1b5SAxel Dörfler 			}
103070a2b1b5SAxel Dörfler 
1031c5d10f7aSAxel Dörfler 			RefreshWindow *fRefreshWindow = new RefreshWindow(
103270a2b1b5SAxel Dörfler 				fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh,
103370a2b1b5SAxel Dörfler 				min, max);
1034a10cf76eSAxel Dörfler 			fRefreshWindow->Show();
1035a10cf76eSAxel Dörfler 			break;
1036a10cf76eSAxel Dörfler 		}
1037a10cf76eSAxel Dörfler 
1038a10cf76eSAxel Dörfler 		case SET_CUSTOM_REFRESH_MSG:
1039a10cf76eSAxel Dörfler 		{
1040a10cf76eSAxel Dörfler 			// user pressed "done" in "Other…" refresh dialog;
1041a10cf76eSAxel Dörfler 			// select the refresh rate chosen
1042a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
1043a10cf76eSAxel Dörfler 
10445de171daSAxel Dörfler 			_UpdateRefreshControl();
10455de171daSAxel Dörfler 			_CheckApplyEnabled();
1046a10cf76eSAxel Dörfler 			break;
1047a10cf76eSAxel Dörfler 		}
1048a10cf76eSAxel Dörfler 
1049a10cf76eSAxel Dörfler 		case POP_COMBINE_DISPLAYS_MSG:
1050a10cf76eSAxel Dörfler 		{
1051a10cf76eSAxel Dörfler 			// new combine mode has bee chosen
1052a10cf76eSAxel Dörfler 			int32 mode;
1053a10cf76eSAxel Dörfler 			if (message->FindInt32("mode", &mode) == B_OK)
1054a10cf76eSAxel Dörfler 				fSelected.combine = (combine_mode)mode;
1055a10cf76eSAxel Dörfler 
10565de171daSAxel Dörfler 			_CheckResolutionMenu();
10575de171daSAxel Dörfler 			_CheckApplyEnabled();
1058a10cf76eSAxel Dörfler 			break;
1059a10cf76eSAxel Dörfler 		}
1060a10cf76eSAxel Dörfler 
1061a10cf76eSAxel Dörfler 		case POP_SWAP_DISPLAYS_MSG:
1062a10cf76eSAxel Dörfler 			message->FindBool("swap", &fSelected.swap_displays);
10635de171daSAxel Dörfler 			_CheckApplyEnabled();
1064a10cf76eSAxel Dörfler 			break;
1065a10cf76eSAxel Dörfler 
1066a10cf76eSAxel Dörfler 		case POP_USE_LAPTOP_PANEL_MSG:
1067a10cf76eSAxel Dörfler 			message->FindBool("use", &fSelected.use_laptop_panel);
10685de171daSAxel Dörfler 			_CheckApplyEnabled();
1069a10cf76eSAxel Dörfler 			break;
1070a10cf76eSAxel Dörfler 
1071a10cf76eSAxel Dörfler 		case POP_TV_STANDARD_MSG:
1072a10cf76eSAxel Dörfler 			message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard);
10735de171daSAxel Dörfler 			_CheckApplyEnabled();
1074a10cf76eSAxel Dörfler 			break;
1075a10cf76eSAxel Dörfler 
1076df3f5bacSStephan Aßmus 		case BUTTON_LAUNCH_BACKGROUNDS_MSG:
10776f095d6aSRyan Leavengood 			if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) {
10786f095d6aSRyan Leavengood 				app_info info;
10796f095d6aSRyan Leavengood 				be_roster->GetAppInfo(kBackgroundsSignature, &info);
10806f095d6aSRyan Leavengood 				be_roster->ActivateApp(info.team);
10816f095d6aSRyan Leavengood 			}
1082df3f5bacSStephan Aßmus 			break;
1083df3f5bacSStephan Aßmus 
1084a10cf76eSAxel Dörfler 		case BUTTON_DEFAULTS_MSG:
1085a10cf76eSAxel Dörfler 		{
10864be51fe3SWaldemar Kornewald 			// TODO: get preferred settings of screen
1087a10cf76eSAxel Dörfler 			fSelected.width = 640;
1088a10cf76eSAxel Dörfler 			fSelected.height = 480;
1089a10cf76eSAxel Dörfler 			fSelected.space = B_CMAP8;
1090a10cf76eSAxel Dörfler 			fSelected.refresh = 60.0;
1091a10cf76eSAxel Dörfler 			fSelected.combine = kCombineDisable;
1092a10cf76eSAxel Dörfler 			fSelected.swap_displays = false;
1093a10cf76eSAxel Dörfler 			fSelected.use_laptop_panel = false;
1094a10cf76eSAxel Dörfler 			fSelected.tv_standard = 0;
1095a10cf76eSAxel Dörfler 
1096b21d610eSAxel Dörfler 			// TODO: workspace defaults
1097abc649b8SWaldemar Kornewald 
10985de171daSAxel Dörfler 			_UpdateControls();
1099a10cf76eSAxel Dörfler 			break;
1100a10cf76eSAxel Dörfler 		}
1101a10cf76eSAxel Dörfler 
110210e9b12fSWaldemar Kornewald 		case BUTTON_UNDO_MSG:
110361c5c89bSAxel Dörfler 			fUndoScreenMode.Revert();
11045de171daSAxel Dörfler 			_UpdateActiveMode();
1105abc649b8SWaldemar Kornewald 			break;
1106abc649b8SWaldemar Kornewald 
1107abc649b8SWaldemar Kornewald 		case BUTTON_REVERT_MSG:
1108abc649b8SWaldemar Kornewald 		{
1109abc649b8SWaldemar Kornewald 			fModified = false;
1110199893c3SAxel Dörfler 			fBootWorkspaceApplied = false;
1111abc649b8SWaldemar Kornewald 
1112b21d610eSAxel Dörfler 			// ScreenMode::Revert() assumes that we first set the correct
1113b21d610eSAxel Dörfler 			// number of workspaces
1114b21d610eSAxel Dörfler 
1115b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns,
1116b21d610eSAxel Dörfler 				fOriginalWorkspacesRows);
1117b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
1118b21d610eSAxel Dörfler 
1119a10cf76eSAxel Dörfler 			fScreenMode.Revert();
11205de171daSAxel Dörfler 			_UpdateActiveMode();
1121a10cf76eSAxel Dörfler 			break;
1122abc649b8SWaldemar Kornewald 		}
1123a10cf76eSAxel Dörfler 
1124a10cf76eSAxel Dörfler 		case BUTTON_APPLY_MSG:
11255de171daSAxel Dörfler 			_Apply();
1126a10cf76eSAxel Dörfler 			break;
1127a10cf76eSAxel Dörfler 
1128abc649b8SWaldemar Kornewald 		case MAKE_INITIAL_MSG:
1129abc649b8SWaldemar Kornewald 			// user pressed "keep" in confirmation dialog
1130abc649b8SWaldemar Kornewald 			fModified = true;
11315de171daSAxel Dörfler 			_UpdateActiveMode();
1132a10cf76eSAxel Dörfler 			break;
1133a10cf76eSAxel Dörfler 
1134a10cf76eSAxel Dörfler 		default:
1135a10cf76eSAxel Dörfler 			BWindow::MessageReceived(message);
1136a10cf76eSAxel Dörfler 	}
1137a10cf76eSAxel Dörfler }
1138a10cf76eSAxel Dörfler 
1139a10cf76eSAxel Dörfler 
114012580984SAxel Dörfler status_t
114112580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const
114212580984SAxel Dörfler {
114312580984SAxel Dörfler 	BPath path;
114412580984SAxel Dörfler 	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
114512580984SAxel Dörfler 	if (status < B_OK)
114612580984SAxel Dörfler 		return status;
114712580984SAxel Dörfler 
114812580984SAxel Dörfler 	path.Append("kernel/drivers");
114912580984SAxel Dörfler 	status = create_directory(path.Path(), 0755);
115012580984SAxel Dörfler 	if (status < B_OK)
115112580984SAxel Dörfler 		return status;
115212580984SAxel Dörfler 
115312580984SAxel Dörfler 	path.Append("vesa");
115412580984SAxel Dörfler 	BFile file;
115512580984SAxel Dörfler 	status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
115612580984SAxel Dörfler 	if (status < B_OK)
115712580984SAxel Dörfler 		return status;
115812580984SAxel Dörfler 
115912580984SAxel Dörfler 	char buffer[256];
11605084d0d4SAlex Smith 	snprintf(buffer, sizeof(buffer), "mode %" B_PRId32 " %" B_PRId32 " %"
11615084d0d4SAlex Smith 		B_PRId32 "\n", mode.width, mode.height, mode.BitsPerPixel());
116212580984SAxel Dörfler 
116312580984SAxel Dörfler 	ssize_t bytesWritten = file.Write(buffer, strlen(buffer));
116412580984SAxel Dörfler 	if (bytesWritten < B_OK)
116512580984SAxel Dörfler 		return bytesWritten;
116612580984SAxel Dörfler 
116712580984SAxel Dörfler 	return B_OK;
116812580984SAxel Dörfler }
116912580984SAxel Dörfler 
117012580984SAxel Dörfler 
1171a10cf76eSAxel Dörfler void
11721fc4cb1fSAxel Dörfler ScreenWindow::_BuildSupportedColorSpaces()
11731fc4cb1fSAxel Dörfler {
11741fc4cb1fSAxel Dörfler 	fSupportedColorSpaces = 0;
11751fc4cb1fSAxel Dörfler 
11761fc4cb1fSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
11771fc4cb1fSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
11781fc4cb1fSAxel Dörfler 			if (fScreenMode.ModeAt(j).space == kColorSpaces[i].space) {
11791fc4cb1fSAxel Dörfler 				fSupportedColorSpaces |= 1 << i;
11801fc4cb1fSAxel Dörfler 				break;
11811fc4cb1fSAxel Dörfler 			}
11821fc4cb1fSAxel Dörfler 		}
11831fc4cb1fSAxel Dörfler 	}
11841fc4cb1fSAxel Dörfler }
11851fc4cb1fSAxel Dörfler 
11861fc4cb1fSAxel Dörfler 
11871fc4cb1fSAxel Dörfler void
11885de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled()
1189a10cf76eSAxel Dörfler {
119095ef5044SJanus 	bool applyEnabled = true;
119195ef5044SJanus 
119295ef5044SJanus 	if (fSelected == fActive) {
119395ef5044SJanus 		applyEnabled = false;
119495ef5044SJanus 		if (fAllWorkspacesItem->IsMarked()) {
119595ef5044SJanus 			screen_mode screenMode;
119695ef5044SJanus 			const int32 workspaceCount = count_workspaces();
119795ef5044SJanus 			for (int32 i = 0; i < workspaceCount; i++) {
119895ef5044SJanus 				fScreenMode.Get(screenMode, i);
119995ef5044SJanus 				if (screenMode != fSelected) {
120095ef5044SJanus 					applyEnabled = true;
120195ef5044SJanus 					break;
120295ef5044SJanus 				}
120395ef5044SJanus 			}
120495ef5044SJanus 		}
120595ef5044SJanus 	}
120695ef5044SJanus 
120795ef5044SJanus 	fApplyButton->SetEnabled(applyEnabled);
1208b21d610eSAxel Dörfler 
1209b21d610eSAxel Dörfler 	uint32 columns;
1210b21d610eSAxel Dörfler 	uint32 rows;
1211b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
1212b21d610eSAxel Dörfler 
1213b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns
1214b21d610eSAxel Dörfler 		|| rows != fOriginalWorkspacesRows
12155de171daSAxel Dörfler 		|| fSelected != fOriginal);
1216a10cf76eSAxel Dörfler }
1217a10cf76eSAxel Dörfler 
1218a10cf76eSAxel Dörfler 
1219a10cf76eSAxel Dörfler void
12205de171daSAxel Dörfler ScreenWindow::_UpdateOriginal()
1221abc649b8SWaldemar Kornewald {
1222b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns,
1223b21d610eSAxel Dörfler 		&fOriginalWorkspacesRows);
1224b21d610eSAxel Dörfler 
1225abc649b8SWaldemar Kornewald 	fScreenMode.Get(fOriginal);
1226abc649b8SWaldemar Kornewald 	fScreenMode.UpdateOriginalModes();
1227abc649b8SWaldemar Kornewald }
1228abc649b8SWaldemar Kornewald 
1229abc649b8SWaldemar Kornewald 
1230abc649b8SWaldemar Kornewald void
123112966d04SAxel Dörfler ScreenWindow::_UpdateMonitor()
123212966d04SAxel Dörfler {
123312966d04SAxel Dörfler 	monitor_info info;
123412966d04SAxel Dörfler 	float diagonalInches;
123512966d04SAxel Dörfler 	status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches);
123655030977SAxel Dörfler 	if (status == B_OK) {
12371a8af605SAxel Dörfler 		char text[512];
123866ab1666SAxel Dörfler 		snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor,
123966ab1666SAxel Dörfler 			info.name[0] ? " " : "", info.name, diagonalInches);
124012966d04SAxel Dörfler 
124112966d04SAxel Dörfler 		fMonitorInfo->SetText(text);
124212966d04SAxel Dörfler 
1243*8bf216d6SAxel Dörfler 		if (fMonitorInfo->IsHidden(fMonitorInfo))
124412966d04SAxel Dörfler 			fMonitorInfo->Show();
124555030977SAxel Dörfler 	} else {
1246*8bf216d6SAxel Dörfler 		if (!fMonitorInfo->IsHidden(fMonitorInfo))
124755030977SAxel Dörfler 			fMonitorInfo->Hide();
124855030977SAxel Dörfler 	}
1249af8f9c31SAxel Dörfler 
12508b46ee25SAdrien Destugues 	// Add info about the graphics device
12518b46ee25SAdrien Destugues 
12528b46ee25SAdrien Destugues 	accelerant_device_info deviceInfo;
12538b46ee25SAdrien Destugues 
12548b46ee25SAdrien Destugues 	if (fScreenMode.GetDeviceInfo(deviceInfo) == B_OK) {
12558b46ee25SAdrien Destugues 		BString deviceString;
12568b46ee25SAdrien Destugues 
12578b46ee25SAdrien Destugues 		if (deviceInfo.name[0] && deviceInfo.chipset[0]) {
12588b46ee25SAdrien Destugues 			deviceString.SetToFormat("%s (%s)", deviceInfo.name,
12598b46ee25SAdrien Destugues 				deviceInfo.chipset);
12608b46ee25SAdrien Destugues 		} else if (deviceInfo.name[0] || deviceInfo.chipset[0]) {
12618b46ee25SAdrien Destugues 			deviceString
12628b46ee25SAdrien Destugues 				= deviceInfo.name[0] ? deviceInfo.name : deviceInfo.chipset;
12638b46ee25SAdrien Destugues 		}
12648b46ee25SAdrien Destugues 
12658b46ee25SAdrien Destugues 		fDeviceInfo->SetText(deviceString);
12668b46ee25SAdrien Destugues 	}
12678b46ee25SAdrien Destugues 
12688b46ee25SAdrien Destugues 
126955030977SAxel Dörfler 	char text[512];
12701a8af605SAxel Dörfler 	size_t length = 0;
12711a8af605SAxel Dörfler 	text[0] = 0;
12721a8af605SAxel Dörfler 
127355030977SAxel Dörfler 	if (status == B_OK) {
1274af8f9c31SAxel Dörfler 		if (info.min_horizontal_frequency != 0
1275af8f9c31SAxel Dörfler 			&& info.min_vertical_frequency != 0
1276af8f9c31SAxel Dörfler 			&& info.max_pixel_clock != 0) {
12771a8af605SAxel Dörfler 			length = snprintf(text, sizeof(text),
1278c9e8f97aSAdrien Destugues 				B_TRANSLATE("Horizonal frequency:\t%lu - %lu kHz\n"
12799c1a9b92SAdrien Destugues 				"Vertical frequency:\t%lu - %lu Hz\n\n"
1280c9e8f97aSAdrien Destugues 				"Maximum pixel clock:\t%g MHz"),
12811a8af605SAxel Dörfler 				info.min_horizontal_frequency, info.max_horizontal_frequency,
12821a8af605SAxel Dörfler 				info.min_vertical_frequency, info.max_vertical_frequency,
12831a8af605SAxel Dörfler 				info.max_pixel_clock / 1000.0);
1284af8f9c31SAxel Dörfler 		}
12851a8af605SAxel Dörfler 		if (info.serial_number[0] && length < sizeof(text)) {
12861a8af605SAxel Dörfler 			length += snprintf(text + length, sizeof(text) - length,
1287c9e8f97aSAdrien Destugues 				B_TRANSLATE("%sSerial no.: %s"), length ? "\n\n" : "",
12881a8af605SAxel Dörfler 				info.serial_number);
12891a8af605SAxel Dörfler 			if (info.produced.week != 0 && info.produced.year != 0
12901a8af605SAxel Dörfler 				&& length < sizeof(text)) {
12911a8af605SAxel Dörfler 				length += snprintf(text + length, sizeof(text) - length,
12921a8af605SAxel Dörfler 					" (%u/%u)", info.produced.week, info.produced.year);
12931a8af605SAxel Dörfler 			}
12941a8af605SAxel Dörfler 		}
129555030977SAxel Dörfler 	}
129661c5c89bSAxel Dörfler 
12971a8af605SAxel Dörfler 	if (text[0])
12981a8af605SAxel Dörfler 		fMonitorView->SetToolTip(text);
129912966d04SAxel Dörfler }
130012966d04SAxel Dörfler 
130112966d04SAxel Dörfler 
130212966d04SAxel Dörfler void
13031fc4cb1fSAxel Dörfler ScreenWindow::_UpdateColorLabel()
13041fc4cb1fSAxel Dörfler {
13051fc4cb1fSAxel Dörfler 	BString string;
1306551c9f15SSiarzhuk Zharski 	string << fSelected.BitsPerPixel() << " " << B_TRANSLATE("bits/pixel");
13071fc4cb1fSAxel Dörfler 	fColorsMenu->Superitem()->SetLabel(string.String());
13081fc4cb1fSAxel Dörfler }
13091fc4cb1fSAxel Dörfler 
13101fc4cb1fSAxel Dörfler 
13111fc4cb1fSAxel Dörfler void
13125de171daSAxel Dörfler ScreenWindow::_Apply()
1313a10cf76eSAxel Dörfler {
1314abc649b8SWaldemar Kornewald 	// make checkpoint, so we can undo these changes
131561c5c89bSAxel Dörfler 	fUndoScreenMode.UpdateOriginalModes();
131661c5c89bSAxel Dörfler 
131707184a9eSAxel Dörfler 	status_t status = fScreenMode.Set(fSelected);
131807184a9eSAxel Dörfler 	if (status == B_OK) {
1319abc649b8SWaldemar Kornewald 		// use the mode that has eventually been set and
1320abc649b8SWaldemar Kornewald 		// thus we know to be working; it can differ from
1321abc649b8SWaldemar Kornewald 		// the mode selected by user due to hardware limitation
1322abc649b8SWaldemar Kornewald 		display_mode newMode;
1323abc649b8SWaldemar Kornewald 		BScreen screen(this);
1324abc649b8SWaldemar Kornewald 		screen.GetMode(&newMode);
1325abc649b8SWaldemar Kornewald 
1326abc649b8SWaldemar Kornewald 		if (fAllWorkspacesItem->IsMarked()) {
1327abc649b8SWaldemar Kornewald 			int32 originatingWorkspace = current_workspace();
132895ef5044SJanus 			const int32 workspaceCount = count_workspaces();
132995ef5044SJanus 			for (int32 i = 0; i < workspaceCount; i++) {
1330abc649b8SWaldemar Kornewald 				if (i != originatingWorkspace)
1331abc649b8SWaldemar Kornewald 					screen.SetMode(i, &newMode, true);
1332abc649b8SWaldemar Kornewald 			}
1333199893c3SAxel Dörfler 			fBootWorkspaceApplied = true;
1334199893c3SAxel Dörfler 		} else {
1335199893c3SAxel Dörfler 			if (current_workspace() == 0)
1336199893c3SAxel Dörfler 				fBootWorkspaceApplied = true;
1337abc649b8SWaldemar Kornewald 		}
1338abc649b8SWaldemar Kornewald 
1339a10cf76eSAxel Dörfler 		fActive = fSelected;
1340a10cf76eSAxel Dörfler 
1341abc649b8SWaldemar Kornewald 		// TODO: only show alert when this is an unknown mode
134241f43d56SAugustin Cavalier 		BAlert* window = new AlertWindow(this);
134341f43d56SAugustin Cavalier 		window->Go(NULL);
134407184a9eSAxel Dörfler 	} else {
134507184a9eSAxel Dörfler 		char message[256];
134607184a9eSAxel Dörfler 		snprintf(message, sizeof(message),
1347c9e8f97aSAdrien Destugues 			B_TRANSLATE("The screen mode could not be set:\n\t%s\n"),
1348c9e8f97aSAdrien Destugues 			screen_errors(status));
1349551c9f15SSiarzhuk Zharski 		BAlert* alert = new BAlert(B_TRANSLATE("Warning"), message,
1350c9e8f97aSAdrien Destugues 			B_TRANSLATE("OK"), NULL, NULL,
135107184a9eSAxel Dörfler 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
1352aed35104SHumdinger 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
135307184a9eSAxel Dörfler 		alert->Go();
1354a10cf76eSAxel Dörfler 	}
135507184a9eSAxel Dörfler }
1356