xref: /haiku/src/preferences/screen/ScreenWindow.cpp (revision 66ab1666891c73bdcda1c95ecedb6da98d124bd3)
1a10cf76eSAxel Dörfler /*
2b21d610eSAxel Dörfler  * Copyright 2001-2009, Haiku.
3a10cf76eSAxel Dörfler  * Distributed under the terms of the MIT License.
4a10cf76eSAxel Dörfler  *
5a10cf76eSAxel Dörfler  * Authors:
6a10cf76eSAxel Dörfler  *		Rafael Romo
7a10cf76eSAxel Dörfler  *		Stefano Ceccherini (burton666@libero.it)
8a10cf76eSAxel Dörfler  *		Andrew Bachmann
9a10cf76eSAxel Dörfler  *		Thomas Kurschel
10a10cf76eSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
11df3f5bacSStephan Aßmus  *		Stephan Aßmus <superstippi@gmx.de>
12b72c4836SAlexandre Deckner  *		Alexandre Deckner, alex@zappotek.com
13a10cf76eSAxel Dörfler  */
14a10cf76eSAxel Dörfler 
15a10cf76eSAxel Dörfler 
16b21d610eSAxel Dörfler #include "ScreenWindow.h"
17b21d610eSAxel Dörfler 
18b21d610eSAxel Dörfler #include <stdio.h>
19b21d610eSAxel Dörfler #include <stdlib.h>
20b21d610eSAxel Dörfler #include <string.h>
21b21d610eSAxel Dörfler 
22b21d610eSAxel Dörfler #include <Alert.h>
23b21d610eSAxel Dörfler #include <Application.h>
24b21d610eSAxel Dörfler #include <Box.h>
25b21d610eSAxel Dörfler #include <Button.h>
26b21d610eSAxel Dörfler #include <Directory.h>
27b21d610eSAxel Dörfler #include <File.h>
28b21d610eSAxel Dörfler #include <FindDirectory.h>
29b21d610eSAxel Dörfler #include <InterfaceDefs.h>
30b21d610eSAxel Dörfler #include <LayoutBuilder.h>
31b21d610eSAxel Dörfler #include <MenuBar.h>
32b21d610eSAxel Dörfler #include <MenuItem.h>
33b21d610eSAxel Dörfler #include <MenuField.h>
34b21d610eSAxel Dörfler #include <Messenger.h>
35b21d610eSAxel Dörfler #include <Path.h>
36b21d610eSAxel Dörfler #include <PopUpMenu.h>
37b21d610eSAxel Dörfler #include <Screen.h>
38b21d610eSAxel Dörfler #include <String.h>
39b21d610eSAxel Dörfler #include <StringView.h>
40b21d610eSAxel Dörfler #include <Roster.h>
41b21d610eSAxel Dörfler #include <Window.h>
42b21d610eSAxel Dörfler 
43b21d610eSAxel Dörfler #include <InterfacePrivate.h>
44b21d610eSAxel Dörfler 
45a10cf76eSAxel Dörfler #include "AlertWindow.h"
46a10cf76eSAxel Dörfler #include "Constants.h"
47a10cf76eSAxel Dörfler #include "RefreshWindow.h"
48a10cf76eSAxel Dörfler #include "MonitorView.h"
49a10cf76eSAxel Dörfler #include "ScreenSettings.h"
50a10cf76eSAxel Dörfler #include "Utility.h"
51a10cf76eSAxel Dörfler 
52a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant.
53a10cf76eSAxel Dörfler  * It's a solution that works with the current BeOS interface that Haiku
54a10cf76eSAxel Dörfler  * adopted.
55a10cf76eSAxel Dörfler  * However, it's not a nice and clean solution. Don't use this header in any
56a10cf76eSAxel Dörfler  * application if you can avoid it. No other driver is using this, or should
57a10cf76eSAxel Dörfler  * be using this.
58a10cf76eSAxel Dörfler  * It will be replaced as soon as we introduce an updated accelerant interface
59a10cf76eSAxel Dörfler  * which may even happen before R1 hits the streets.
60a10cf76eSAxel Dörfler  */
61a10cf76eSAxel Dörfler #include "multimon.h"	// the usual: DANGER WILL, ROBINSON!
62a10cf76eSAxel Dörfler 
63a10cf76eSAxel Dörfler 
64c5d80d47SAxel Dörfler const char* kBackgroundsSignature = "application/x-vnd.haiku-backgrounds";
65c5d80d47SAxel Dörfler 
66a10cf76eSAxel Dörfler // list of officially supported colour spaces
67a10cf76eSAxel Dörfler static const struct {
68a10cf76eSAxel Dörfler 	color_space	space;
69a10cf76eSAxel Dörfler 	int32		bits_per_pixel;
70a10cf76eSAxel Dörfler 	const char*	label;
71a10cf76eSAxel Dörfler } kColorSpaces[] = {
72a10cf76eSAxel Dörfler 	{ B_CMAP8, 8, "8 Bits/Pixel, 256 Colors" },
73a10cf76eSAxel Dörfler 	{ B_RGB15, 15, "15 Bits/Pixel, 32768 Colors" },
74a10cf76eSAxel Dörfler 	{ B_RGB16, 16, "16 Bits/Pixel, 65536 Colors" },
75a10cf76eSAxel Dörfler 	{ B_RGB32, 32, "32 Bits/Pixel, 16 Million Colors" }
76a10cf76eSAxel Dörfler };
77b21d610eSAxel Dörfler static const int32 kColorSpaceCount
78b21d610eSAxel Dörfler 	= sizeof(kColorSpaces) / sizeof(kColorSpaces[0]);
79a10cf76eSAxel Dörfler 
80a10cf76eSAxel Dörfler // list of standard refresh rates
81a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 };
82b21d610eSAxel Dörfler static const int32 kRefreshRateCount
83b21d610eSAxel Dörfler 	= sizeof(kRefreshRates) / sizeof(kRefreshRates[0]);
84a10cf76eSAxel Dörfler 
85a10cf76eSAxel Dörfler // list of combine modes
86a10cf76eSAxel Dörfler static const struct {
87a10cf76eSAxel Dörfler 	combine_mode	mode;
88a10cf76eSAxel Dörfler 	const char		*name;
89a10cf76eSAxel Dörfler } kCombineModes[] = {
90a10cf76eSAxel Dörfler 	{ kCombineDisable, "disable" },
91a10cf76eSAxel Dörfler 	{ kCombineHorizontally, "horizontally" },
92a10cf76eSAxel Dörfler 	{ kCombineVertically, "vertically" }
93a10cf76eSAxel Dörfler };
94b21d610eSAxel Dörfler static const int32 kCombineModeCount
95b21d610eSAxel Dörfler 	= sizeof(kCombineModes) / sizeof(kCombineModes[0]);
9629e8a73aSAxel Dörfler 
97a10cf76eSAxel Dörfler 
98a10cf76eSAxel Dörfler static BString
99a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode)
100a10cf76eSAxel Dörfler {
101a10cf76eSAxel Dörfler 	switch (mode) {
102a10cf76eSAxel Dörfler 		case 0:		return "disabled";
103a10cf76eSAxel Dörfler 		case 1:		return "NTSC";
104a10cf76eSAxel Dörfler 		case 2:		return "NTSC Japan";
105a10cf76eSAxel Dörfler 		case 3:		return "PAL BDGHI";
106a10cf76eSAxel Dörfler 		case 4:		return "PAL M";
107a10cf76eSAxel Dörfler 		case 5:		return "PAL N";
108a10cf76eSAxel Dörfler 		case 6:		return "SECAM";
109a10cf76eSAxel Dörfler 		case 101:	return "NTSC 443";
110a10cf76eSAxel Dörfler 		case 102:	return "PAL 60";
111a10cf76eSAxel Dörfler 		case 103:	return "PAL NC";
112a10cf76eSAxel Dörfler 		default:
113a10cf76eSAxel Dörfler 		{
114a10cf76eSAxel Dörfler 			BString name;
115a10cf76eSAxel Dörfler 			name << "??? (" << mode << ")";
116a10cf76eSAxel Dörfler 
117a10cf76eSAxel Dörfler 			return name;
118a10cf76eSAxel Dörfler 		}
119a10cf76eSAxel Dörfler 	}
120a10cf76eSAxel Dörfler }
121a10cf76eSAxel Dörfler 
122a10cf76eSAxel Dörfler 
123a10cf76eSAxel Dörfler static void
124a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string)
125a10cf76eSAxel Dörfler {
126a10cf76eSAxel Dörfler 	string << mode.width << " x " << mode.height;
127a10cf76eSAxel Dörfler }
128a10cf76eSAxel Dörfler 
129a10cf76eSAxel Dörfler 
130a10cf76eSAxel Dörfler static void
131a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string,
132a10cf76eSAxel Dörfler 	bool appendUnit = true, bool alwaysWithFraction = false)
133a10cf76eSAxel Dörfler {
134a10cf76eSAxel Dörfler 	snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, refresh);
135a10cf76eSAxel Dörfler 	string.UnlockBuffer();
136a10cf76eSAxel Dörfler 
137a10cf76eSAxel Dörfler 	if (appendUnit)
138a10cf76eSAxel Dörfler 		string << " Hz";
139a10cf76eSAxel Dörfler }
140a10cf76eSAxel Dörfler 
141a10cf76eSAxel Dörfler 
14207184a9eSAxel Dörfler static const char*
14307184a9eSAxel Dörfler screen_errors(status_t status)
14407184a9eSAxel Dörfler {
14507184a9eSAxel Dörfler 	switch (status) {
14607184a9eSAxel Dörfler 		case B_ENTRY_NOT_FOUND:
14707184a9eSAxel Dörfler 			return "Unknown Mode";
14807184a9eSAxel Dörfler 		// TODO: add more?
14907184a9eSAxel Dörfler 
15007184a9eSAxel Dörfler 		default:
15107184a9eSAxel Dörfler 			return strerror(status);
15207184a9eSAxel Dörfler 	}
15307184a9eSAxel Dörfler }
15407184a9eSAxel Dörfler 
15529e8a73aSAxel Dörfler 
1563dfd20c0SStephan Aßmus //	#pragma mark -
1573dfd20c0SStephan Aßmus 
1583dfd20c0SStephan Aßmus 
1595a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings* settings)
160b21d610eSAxel Dörfler 	:
161b21d610eSAxel Dörfler 	BWindow(settings->WindowFrame(), "Screen", B_TITLED_WINDOW,
162b21d610eSAxel Dörfler 		B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS,
163b21d610eSAxel Dörfler 		B_ALL_WORKSPACES),
164199893c3SAxel Dörfler 	fBootWorkspaceApplied(false),
165a10cf76eSAxel Dörfler 	fScreenMode(this),
166abc649b8SWaldemar Kornewald 	fTempScreenMode(this),
167abc649b8SWaldemar Kornewald 	fModified(false)
168a10cf76eSAxel Dörfler {
169a10cf76eSAxel Dörfler 	BScreen screen(this);
170a10cf76eSAxel Dörfler 
17112580984SAxel Dörfler 	accelerant_device_info info;
172d1516993SAxel Dörfler 	if (screen.GetDeviceInfo(&info) == B_OK
173d1516993SAxel Dörfler 		&& !strcasecmp(info.chipset, "VESA"))
17412580984SAxel Dörfler 		fIsVesa = true;
17512580984SAxel Dörfler 
1765de171daSAxel Dörfler 	_UpdateOriginal();
177a10cf76eSAxel Dörfler 	fActive = fSelected = fOriginal;
178a10cf76eSAxel Dörfler 
1795a78744bSAxel Dörfler 	fSettings = settings;
1805a78744bSAxel Dörfler 
1815a78744bSAxel Dörfler 	// we need the "Current Workspace" first to get its height
1825a78744bSAxel Dörfler 
1835a78744bSAxel Dörfler 	BPopUpMenu *popUpMenu = new BPopUpMenu("Current Workspace", true, true);
184d1516993SAxel Dörfler 	fAllWorkspacesItem = new BMenuItem("All Workspaces",
185d1516993SAxel Dörfler 		new BMessage(WORKSPACE_CHECK_MSG));
1865a78744bSAxel Dörfler 	popUpMenu->AddItem(fAllWorkspacesItem);
187d1516993SAxel Dörfler 	BMenuItem *item = new BMenuItem("Current Workspace",
188d1516993SAxel Dörfler 		new BMessage(WORKSPACE_CHECK_MSG));
189b72c4836SAlexandre Deckner 
1905a78744bSAxel Dörfler 	popUpMenu->AddItem(item);
19127c43a2dSRene Gollent 	fAllWorkspacesItem->SetMarked(true);
1925a78744bSAxel Dörfler 
193b21d610eSAxel Dörfler 	BMenuField* workspaceMenuField = new BMenuField("WorkspaceMenu", NULL,
194b21d610eSAxel Dörfler 		popUpMenu, NULL);
1955a78744bSAxel Dörfler 	workspaceMenuField->ResizeToPreferred();
196a10cf76eSAxel Dörfler 
197a10cf76eSAxel Dörfler 	// box on the left with workspace count and monitor view
198a10cf76eSAxel Dörfler 
199b21d610eSAxel Dörfler 	BBox* screenBox = new BBox("screen box");
200b21d610eSAxel Dörfler 	BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 10.0);
201b21d610eSAxel Dörfler 	layout->SetInsets(10, 10, 10, 10);
202b21d610eSAxel Dörfler 	screenBox->SetLayout(layout);
203a10cf76eSAxel Dörfler 
20412966d04SAxel Dörfler 	fMonitorInfo = new BStringView("monitor info", "");
20512966d04SAxel Dörfler 	screenBox->AddChild(fMonitorInfo);
20612966d04SAxel Dörfler 
207df3f5bacSStephan Aßmus 	fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), "monitor",
2086bda235aSStefano Ceccherini 		screen.Frame().IntegerWidth() + 1, screen.Frame().IntegerHeight() + 1);
209b21d610eSAxel Dörfler 	screenBox->AddChild(fMonitorView);
2105a78744bSAxel Dörfler 
211b21d610eSAxel Dörfler 	fColumnsControl = new BTextControl("Columns:", "0",
212b21d610eSAxel Dörfler 		new BMessage(kMsgWorkspaceColumnsChanged));
213b21d610eSAxel Dörfler 	fRowsControl = new BTextControl("Rows:", "0",
214b21d610eSAxel Dörfler 		new BMessage(kMsgWorkspaceRowsChanged));
215b21d610eSAxel Dörfler 
216b21d610eSAxel Dörfler 	screenBox->AddChild(BLayoutBuilder::Grid<>(5.0, 5.0)
217b21d610eSAxel Dörfler 		.Add(new BStringView("", "Workspaces"), 0, 0, 3)
218b21d610eSAxel Dörfler 		.AddTextControl(fColumnsControl, 0, 1, B_ALIGN_RIGHT)
219b21d610eSAxel Dörfler 		.AddGroup(B_HORIZONTAL, 0, 2, 1)
220b21d610eSAxel Dörfler 			.Add(_CreateColumnRowButton(true, false))
221b21d610eSAxel Dörfler 			.Add(_CreateColumnRowButton(true, true))
222b21d610eSAxel Dörfler 		.End()
223b21d610eSAxel Dörfler 		.AddTextControl(fRowsControl, 0, 2, B_ALIGN_RIGHT)
224b21d610eSAxel Dörfler 		.AddGroup(B_HORIZONTAL, 0, 2, 2)
225b21d610eSAxel Dörfler 			.Add(_CreateColumnRowButton(false, false))
226b21d610eSAxel Dörfler 			.Add(_CreateColumnRowButton(false, true))
227b21d610eSAxel Dörfler 		.End());
228b21d610eSAxel Dörfler 
229b21d610eSAxel Dörfler 	fBackgroundsButton = new BButton("BackgroundsButton",
230b21d610eSAxel Dörfler 		"Set Background" B_UTF8_ELLIPSIS,
231b21d610eSAxel Dörfler 		new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG));
232b21d610eSAxel Dörfler 	fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9);
233b21d610eSAxel Dörfler 	screenBox->AddChild(fBackgroundsButton);
234a10cf76eSAxel Dörfler 
235a10cf76eSAxel Dörfler 	// box on the right with screen resolution, etc.
236a10cf76eSAxel Dörfler 
237b21d610eSAxel Dörfler 	BBox* controlsBox = new BBox("controls box");
238b21d610eSAxel Dörfler 	controlsBox->SetLabel(workspaceMenuField);
239b21d610eSAxel Dörfler 	BView* outerControlsView = BLayoutBuilder::Group<>(B_VERTICAL, 10.0)
240b21d610eSAxel Dörfler 		.SetInsets(10, 10, 10, 10);
241b21d610eSAxel Dörfler 	controlsBox->AddChild(outerControlsView);
242a10cf76eSAxel Dörfler 
243a10cf76eSAxel Dörfler 	fResolutionMenu = new BPopUpMenu("resolution", true, true);
244a10cf76eSAxel Dörfler 
245*66ab1666SAxel Dörfler 	uint16 maxWidth = 0;
246*66ab1666SAxel Dörfler 	uint16 maxHeight = 0;
247*66ab1666SAxel Dörfler 	uint16 previousWidth = 0;
248*66ab1666SAxel Dörfler 	uint16 previousHeight = 0;
249a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
250a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
251a10cf76eSAxel Dörfler 
252a10cf76eSAxel Dörfler 		if (mode.width == previousWidth && mode.height == previousHeight)
253a10cf76eSAxel Dörfler 			continue;
254a10cf76eSAxel Dörfler 
255a10cf76eSAxel Dörfler 		previousWidth = mode.width;
256a10cf76eSAxel Dörfler 		previousHeight = mode.height;
257*66ab1666SAxel Dörfler 		if (maxWidth < mode.width)
258*66ab1666SAxel Dörfler 			maxWidth = mode.width;
259*66ab1666SAxel Dörfler 		if (maxHeight < mode.height)
260*66ab1666SAxel Dörfler 			maxHeight = mode.height;
261a10cf76eSAxel Dörfler 
262a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_RESOLUTION_MSG);
263a10cf76eSAxel Dörfler 		message->AddInt32("width", mode.width);
264a10cf76eSAxel Dörfler 		message->AddInt32("height", mode.height);
265a10cf76eSAxel Dörfler 
266a10cf76eSAxel Dörfler 		BString name;
267a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
268a10cf76eSAxel Dörfler 
269a10cf76eSAxel Dörfler 		fResolutionMenu->AddItem(new BMenuItem(name.String(), message));
270a10cf76eSAxel Dörfler 	}
271a10cf76eSAxel Dörfler 
272*66ab1666SAxel Dörfler 	fMonitorView->SetMaxResolution(maxWidth, maxHeight);
273*66ab1666SAxel Dörfler 
27429e8a73aSAxel Dörfler 	BRect rect(0.0, 0.0, 200.0, 15.0);
275df3f5bacSStephan Aßmus 	// fResolutionField needs to be at the correct
276df3f5bacSStephan Aßmus 	// left-top offset, because all other menu fields
277df3f5bacSStephan Aßmus 	// will be layouted relative to it
278b21d610eSAxel Dörfler 	fResolutionField = new BMenuField("ResolutionMenu", "Resolution:",
279b21d610eSAxel Dörfler 		fResolutionMenu, NULL);
280a10cf76eSAxel Dörfler 
281a10cf76eSAxel Dörfler 	fColorsMenu = new BPopUpMenu("colors", true, true);
282a10cf76eSAxel Dörfler 
283a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
284a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_COLORS_MSG);
285a10cf76eSAxel Dörfler 		message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
286a10cf76eSAxel Dörfler 		message->AddInt32("space", kColorSpaces[i].space);
287a10cf76eSAxel Dörfler 
288a10cf76eSAxel Dörfler 		fColorsMenu->AddItem(new BMenuItem(kColorSpaces[i].label, message));
289a10cf76eSAxel Dörfler 	}
290a10cf76eSAxel Dörfler 
291df3f5bacSStephan Aßmus 	rect.OffsetTo(B_ORIGIN);
292df3f5bacSStephan Aßmus 
293b21d610eSAxel Dörfler 	fColorsField = new BMenuField("ColorsMenu", "Colors:", fColorsMenu, NULL);
294a10cf76eSAxel Dörfler 
295a10cf76eSAxel Dörfler 	fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
296a10cf76eSAxel Dörfler 
29729e8a73aSAxel Dörfler 	BMessage *message;
29829e8a73aSAxel Dörfler 
29929e8a73aSAxel Dörfler 	float min, max;
30029e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fActive, min, max) && min == max) {
30129e8a73aSAxel Dörfler 		// This is a special case for drivers that only support a single
30229e8a73aSAxel Dörfler 		// frequency, like the VESA driver
30329e8a73aSAxel Dörfler 		BString name;
30429e8a73aSAxel Dörfler 		name << min << " Hz";
30529e8a73aSAxel Dörfler 
30629e8a73aSAxel Dörfler 		message = new BMessage(POP_REFRESH_MSG);
30729e8a73aSAxel Dörfler 		message->AddFloat("refresh", min);
30829e8a73aSAxel Dörfler 
30929e8a73aSAxel Dörfler 		fRefreshMenu->AddItem(item = new BMenuItem(name.String(), message));
31029e8a73aSAxel Dörfler 		item->SetEnabled(false);
31129e8a73aSAxel Dörfler 	} else {
312a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kRefreshRateCount; ++i) {
313a10cf76eSAxel Dörfler 			BString name;
314a10cf76eSAxel Dörfler 			name << kRefreshRates[i] << " Hz";
315a10cf76eSAxel Dörfler 
31629e8a73aSAxel Dörfler 			message = new BMessage(POP_REFRESH_MSG);
317a10cf76eSAxel Dörfler 			message->AddFloat("refresh", kRefreshRates[i]);
318a10cf76eSAxel Dörfler 
319a10cf76eSAxel Dörfler 			fRefreshMenu->AddItem(new BMenuItem(name.String(), message));
320a10cf76eSAxel Dörfler 		}
321a10cf76eSAxel Dörfler 
32229e8a73aSAxel Dörfler 		message = new BMessage(POP_OTHER_REFRESH_MSG);
323a10cf76eSAxel Dörfler 
324a10cf76eSAxel Dörfler 		fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message);
325a10cf76eSAxel Dörfler 		fRefreshMenu->AddItem(fOtherRefresh);
32629e8a73aSAxel Dörfler 	}
327a10cf76eSAxel Dörfler 
328b21d610eSAxel Dörfler 	fRefreshField = new BMenuField("RefreshMenu", "Refresh Rate:",
329b21d610eSAxel Dörfler 		fRefreshMenu, NULL);
330b21d610eSAxel Dörfler 
33112580984SAxel Dörfler 	if (_IsVesa())
33212580984SAxel Dörfler 		fRefreshField->Hide();
333a10cf76eSAxel Dörfler 
334a10cf76eSAxel Dörfler 	// enlarged area for multi-monitor settings
335a10cf76eSAxel Dörfler 	{
336a10cf76eSAxel Dörfler 		bool dummy;
337a10cf76eSAxel Dörfler 		uint32 dummy32;
338a10cf76eSAxel Dörfler 		bool multiMonSupport;
339a10cf76eSAxel Dörfler 		bool useLaptopPanelSupport;
340a10cf76eSAxel Dörfler 		bool tvStandardSupport;
341a10cf76eSAxel Dörfler 
342a10cf76eSAxel Dörfler 		multiMonSupport = TestMultiMonSupport(&screen) == B_OK;
343a10cf76eSAxel Dörfler 		useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK;
344a10cf76eSAxel Dörfler 		tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK;
345a10cf76eSAxel Dörfler 
346a10cf76eSAxel Dörfler 		// even if there is no support, we still create all controls
347a10cf76eSAxel Dörfler 		// to make sure we don't access NULL pointers later on
348a10cf76eSAxel Dörfler 
349a10cf76eSAxel Dörfler 		fCombineMenu = new BPopUpMenu("CombineDisplays", true, true);
350a10cf76eSAxel Dörfler 
351a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kCombineModeCount; i++) {
352a10cf76eSAxel Dörfler 			message = new BMessage(POP_COMBINE_DISPLAYS_MSG);
353a10cf76eSAxel Dörfler 			message->AddInt32("mode", kCombineModes[i].mode);
354a10cf76eSAxel Dörfler 
355d1516993SAxel Dörfler 			fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name,
356d1516993SAxel Dörfler 				message));
357a10cf76eSAxel Dörfler 		}
358a10cf76eSAxel Dörfler 
359b21d610eSAxel Dörfler 		fCombineField = new BMenuField("CombineMenu",
360b21d610eSAxel Dörfler 			"Combine Displays:", fCombineMenu, NULL);
361a10cf76eSAxel Dörfler 
362a10cf76eSAxel Dörfler 		if (!multiMonSupport)
363df3f5bacSStephan Aßmus 			fCombineField->Hide();
364a10cf76eSAxel Dörfler 
365a10cf76eSAxel Dörfler 		fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true);
366a10cf76eSAxel Dörfler 
367a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
368a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
369a10cf76eSAxel Dörfler 		message->AddBool("swap", false);
370a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("no", message));
371a10cf76eSAxel Dörfler 
372a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
373a10cf76eSAxel Dörfler 		message->AddBool("swap", true);
374a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message));
375a10cf76eSAxel Dörfler 
376b21d610eSAxel Dörfler 		fSwapDisplaysField = new BMenuField("SwapMenu", "Swap Displays:",
377b21d610eSAxel Dörfler 			fSwapDisplaysMenu, NULL);
378a10cf76eSAxel Dörfler 
379a10cf76eSAxel Dörfler 		if (!multiMonSupport)
380df3f5bacSStephan Aßmus 			fSwapDisplaysField->Hide();
381a10cf76eSAxel Dörfler 
382a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true);
383a10cf76eSAxel Dörfler 
384a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
385a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
386a10cf76eSAxel Dörfler 		message->AddBool("use", false);
387a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message));
388a10cf76eSAxel Dörfler 
389a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
390a10cf76eSAxel Dörfler 		message->AddBool("use", true);
391a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message));
392a10cf76eSAxel Dörfler 
393b21d610eSAxel Dörfler 		fUseLaptopPanelField = new BMenuField("UseLaptopPanel",
394b21d610eSAxel Dörfler 			"Use Laptop Panel:", fUseLaptopPanelMenu, NULL);
395a10cf76eSAxel Dörfler 
396a10cf76eSAxel Dörfler 		if (!useLaptopPanelSupport)
397df3f5bacSStephan Aßmus 			fUseLaptopPanelField->Hide();
398a10cf76eSAxel Dörfler 
399a10cf76eSAxel Dörfler 		fTVStandardMenu = new BPopUpMenu("TVStandard", true, true);
400a10cf76eSAxel Dörfler 
401a10cf76eSAxel Dörfler 		// arbitrary limit
402a10cf76eSAxel Dörfler 		uint32 i;
403a10cf76eSAxel Dörfler 		for (i = 0; i < 100; ++i) {
404a10cf76eSAxel Dörfler 			uint32 mode;
405a10cf76eSAxel Dörfler 			if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK)
406a10cf76eSAxel Dörfler 				break;
407a10cf76eSAxel Dörfler 
408a10cf76eSAxel Dörfler 			BString name = tv_standard_to_string(mode);
409a10cf76eSAxel Dörfler 
410a10cf76eSAxel Dörfler 			message = new BMessage(POP_TV_STANDARD_MSG);
411a10cf76eSAxel Dörfler 			message->AddInt32("tv_standard", mode);
412a10cf76eSAxel Dörfler 
413a10cf76eSAxel Dörfler 			fTVStandardMenu->AddItem(new BMenuItem(name.String(), message));
414a10cf76eSAxel Dörfler 		}
415a10cf76eSAxel Dörfler 
416b21d610eSAxel Dörfler 		fTVStandardField = new BMenuField("tv standard", "Video Format:",
417b21d610eSAxel Dörfler 			fTVStandardMenu, NULL);
418df3f5bacSStephan Aßmus 		fTVStandardField->SetAlignment(B_ALIGN_RIGHT);
419a10cf76eSAxel Dörfler 
420b21d610eSAxel Dörfler 		if (!tvStandardSupport || i == 0)
421df3f5bacSStephan Aßmus 			fTVStandardField->Hide();
422a10cf76eSAxel Dörfler 	}
423a10cf76eSAxel Dörfler 
424b21d610eSAxel Dörfler 	BView* controlsView = BLayoutBuilder::Grid<>(5.0, 5.0)
425b21d610eSAxel Dörfler 		.AddMenuField(fResolutionField, 0, 0, B_ALIGN_RIGHT)
426b21d610eSAxel Dörfler 		.AddMenuField(fColorsField, 0, 1, B_ALIGN_RIGHT)
427b21d610eSAxel Dörfler 		.AddMenuField(fRefreshField, 0, 2, B_ALIGN_RIGHT)
428b21d610eSAxel Dörfler 		.AddMenuField(fCombineField, 0, 3, B_ALIGN_RIGHT)
429b21d610eSAxel Dörfler 		.AddMenuField(fSwapDisplaysField, 0, 4, B_ALIGN_RIGHT)
430b21d610eSAxel Dörfler 		.AddMenuField(fUseLaptopPanelField, 0, 5, B_ALIGN_RIGHT)
431b21d610eSAxel Dörfler 		.AddMenuField(fTVStandardField, 0, 6, B_ALIGN_RIGHT);
432b21d610eSAxel Dörfler 	outerControlsView->AddChild(controlsView);
433df3f5bacSStephan Aßmus 
434abc649b8SWaldemar Kornewald 	// TODO: we don't support getting the screen's preferred settings
435abc649b8SWaldemar Kornewald 	/* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults",
436b21d610eSAxel Dörfler 		new BMessage(BUTTON_DEFAULTS_MSG));*/
437a10cf76eSAxel Dörfler 
438b21d610eSAxel Dörfler 	fApplyButton = new BButton("ApplyButton", "Apply",
439df3f5bacSStephan Aßmus 		new BMessage(BUTTON_APPLY_MSG));
440df3f5bacSStephan Aßmus 	fApplyButton->SetEnabled(false);
441b21d610eSAxel Dörfler 	outerControlsView->GetLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
442b21d610eSAxel Dörfler 	outerControlsView->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL)
443b21d610eSAxel Dörfler 		.AddGlue()
444b21d610eSAxel Dörfler 		.Add(fApplyButton));
445b21d610eSAxel Dörfler 
446b21d610eSAxel Dörfler 	fRevertButton = new BButton("RevertButton", "Revert",
447b21d610eSAxel Dörfler 		new BMessage(BUTTON_REVERT_MSG));
448b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(false);
449b21d610eSAxel Dörfler 
450b21d610eSAxel Dörfler 	SetLayout(new BGroupLayout(B_VERTICAL, 10.0));
451b21d610eSAxel Dörfler 	GetLayout()->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
452b21d610eSAxel Dörfler 
453b21d610eSAxel Dörfler 	BLayoutBuilder::Group<>(static_cast<BGroupLayout*>(GetLayout()))
454b21d610eSAxel Dörfler 		.SetInsets(10, 10, 10, 10)
455b21d610eSAxel Dörfler 		.AddGroup(B_HORIZONTAL, 10.0)
456b21d610eSAxel Dörfler 			.AddGroup(B_VERTICAL)
457b21d610eSAxel Dörfler 				.Add(screenBox)
458b21d610eSAxel Dörfler 			.End()
459b21d610eSAxel Dörfler 			.Add(controlsBox)
460b21d610eSAxel Dörfler 		.End()
461b21d610eSAxel Dörfler 		.AddGroup(B_HORIZONTAL, 10.0)
462b21d610eSAxel Dörfler 			.Add(fRevertButton)
463b21d610eSAxel Dörfler 			.AddGlue();
464b21d610eSAxel Dörfler 
465b21d610eSAxel Dörfler 	screenBox->Parent()->GetLayout()->AddItem(0,
466b21d610eSAxel Dörfler 		BSpaceLayoutItem::CreateVerticalStrut(
467b21d610eSAxel Dörfler 			controlsBox->TopBorderOffset() - 1));
4685a78744bSAxel Dörfler 
4695de171daSAxel Dörfler 	_UpdateControls();
47012966d04SAxel Dörfler 	_UpdateMonitor();
471a10cf76eSAxel Dörfler }
472a10cf76eSAxel Dörfler 
473a10cf76eSAxel Dörfler 
474a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow()
475a10cf76eSAxel Dörfler {
476a10cf76eSAxel Dörfler 	delete fSettings;
477a10cf76eSAxel Dörfler }
478a10cf76eSAxel Dörfler 
479a10cf76eSAxel Dörfler 
480a10cf76eSAxel Dörfler bool
481a10cf76eSAxel Dörfler ScreenWindow::QuitRequested()
482a10cf76eSAxel Dörfler {
483a10cf76eSAxel Dörfler 	fSettings->SetWindowFrame(Frame());
484199893c3SAxel Dörfler 
485199893c3SAxel Dörfler 	// Write mode of workspace 0 (the boot workspace) to the vesa settings file
486199893c3SAxel Dörfler 	screen_mode vesaMode;
487199893c3SAxel Dörfler 	if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) {
488199893c3SAxel Dörfler 		status_t status = _WriteVesaModeFile(vesaMode);
48912580984SAxel Dörfler 		if (status < B_OK) {
49012580984SAxel Dörfler 			BString warning = "Could not write VESA mode settings file:\n\t";
49112580984SAxel Dörfler 			warning << strerror(status);
49212580984SAxel Dörfler 			(new BAlert("VesaAlert", warning.String(), "Okay", NULL, NULL,
49312580984SAxel Dörfler 				B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
49412580984SAxel Dörfler 		}
49512580984SAxel Dörfler 	}
49612580984SAxel Dörfler 
497a10cf76eSAxel Dörfler 	be_app->PostMessage(B_QUIT_REQUESTED);
498a10cf76eSAxel Dörfler 
499a10cf76eSAxel Dörfler 	return BWindow::QuitRequested();
500a10cf76eSAxel Dörfler }
501a10cf76eSAxel Dörfler 
502a10cf76eSAxel Dörfler 
5035de171daSAxel Dörfler /*!	Update resolution list according to combine mode
5045de171daSAxel Dörfler 	(some resolution may not be combinable due to memory restrictions)
505a10cf76eSAxel Dörfler */
506a10cf76eSAxel Dörfler void
5075de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu()
508a10cf76eSAxel Dörfler {
509a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fResolutionMenu->CountItems(); i++)
510a10cf76eSAxel Dörfler 		fResolutionMenu->ItemAt(i)->SetEnabled(false);
511a10cf76eSAxel Dörfler 
512a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
513a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
514a10cf76eSAxel Dörfler 		if (mode.combine != fSelected.combine)
515a10cf76eSAxel Dörfler 			continue;
516a10cf76eSAxel Dörfler 
517a10cf76eSAxel Dörfler 		BString name;
518a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
519a10cf76eSAxel Dörfler 
520a10cf76eSAxel Dörfler 		BMenuItem *item = fResolutionMenu->FindItem(name.String());
521a10cf76eSAxel Dörfler 		if (item != NULL)
522a10cf76eSAxel Dörfler 			item->SetEnabled(true);
523a10cf76eSAxel Dörfler 	}
524a10cf76eSAxel Dörfler }
525a10cf76eSAxel Dörfler 
526a10cf76eSAxel Dörfler 
5275de171daSAxel Dörfler /*!	Update color and refresh options according to current mode
5285de171daSAxel Dörfler 	(a color space is made active if there is any mode with
5295de171daSAxel Dörfler 	given resolution and this colour space; same applies for
5305de171daSAxel Dörfler 	refresh rate, though "Other…" is always possible)
531a10cf76eSAxel Dörfler */
532a10cf76eSAxel Dörfler void
5335de171daSAxel Dörfler ScreenWindow::_CheckColorMenu()
534a10cf76eSAxel Dörfler {
535a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
536a10cf76eSAxel Dörfler 		bool supported = false;
537a10cf76eSAxel Dörfler 
538a10cf76eSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
539a10cf76eSAxel Dörfler 			screen_mode mode = fScreenMode.ModeAt(j);
540a10cf76eSAxel Dörfler 
541a10cf76eSAxel Dörfler 			if (fSelected.width == mode.width
542a10cf76eSAxel Dörfler 				&& fSelected.height == mode.height
5435de171daSAxel Dörfler 				&& (kColorSpaces[i].space == mode.space
5445de171daSAxel Dörfler 					// advertize 24 bit mode as 32 bit to avoid confusion
5455de171daSAxel Dörfler 					|| (kColorSpaces[i].space == B_RGB32
5465de171daSAxel Dörfler 						&& mode.space == B_RGB24))
547a10cf76eSAxel Dörfler 				&& fSelected.combine == mode.combine) {
548a10cf76eSAxel Dörfler 				supported = true;
549a10cf76eSAxel Dörfler 				break;
550a10cf76eSAxel Dörfler 			}
551a10cf76eSAxel Dörfler 		}
552a10cf76eSAxel Dörfler 
553a10cf76eSAxel Dörfler 		BMenuItem* item = fColorsMenu->ItemAt(i);
554a10cf76eSAxel Dörfler 		if (item)
555a10cf76eSAxel Dörfler 			item->SetEnabled(supported);
556a10cf76eSAxel Dörfler 	}
557a10cf76eSAxel Dörfler }
558a10cf76eSAxel Dörfler 
559a10cf76eSAxel Dörfler 
5605de171daSAxel Dörfler /*!	Enable/disable refresh options according to current mode. */
561a10cf76eSAxel Dörfler void
5625de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu()
563a10cf76eSAxel Dörfler {
56429e8a73aSAxel Dörfler 	float min, max;
56529e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max)
56629e8a73aSAxel Dörfler 		return;
567a10cf76eSAxel Dörfler 
56829e8a73aSAxel Dörfler 	for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) {
56929e8a73aSAxel Dörfler 		BMenuItem* item = fRefreshMenu->ItemAt(i);
57029e8a73aSAxel Dörfler 		BMessage* message = item->Message();
57129e8a73aSAxel Dörfler 		float refresh;
57229e8a73aSAxel Dörfler 		if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK)
57329e8a73aSAxel Dörfler 			item->SetEnabled(refresh >= min && refresh <= max);
574a10cf76eSAxel Dörfler 	}
575a10cf76eSAxel Dörfler }
576a10cf76eSAxel Dörfler 
577a10cf76eSAxel Dörfler 
5785de171daSAxel Dörfler /*!	Activate appropriate menu item according to selected refresh rate */
579a10cf76eSAxel Dörfler void
5805de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl()
581a10cf76eSAxel Dörfler {
582a10cf76eSAxel Dörfler 	BString string;
583a10cf76eSAxel Dörfler 	refresh_rate_to_string(fSelected.refresh, string);
584a10cf76eSAxel Dörfler 
585a10cf76eSAxel Dörfler 	BMenuItem* item = fRefreshMenu->FindItem(string.String());
586a10cf76eSAxel Dörfler 	if (item) {
587a10cf76eSAxel Dörfler 		if (!item->IsMarked())
588a10cf76eSAxel Dörfler 			item->SetMarked(true);
58929e8a73aSAxel Dörfler 
590a10cf76eSAxel Dörfler 		// "Other…" items only contains a refresh rate when active
591e6b421a9SJérôme Duval 		fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS);
592a10cf76eSAxel Dörfler 		return;
593a10cf76eSAxel Dörfler 	}
594a10cf76eSAxel Dörfler 
595a10cf76eSAxel Dörfler 	// this is a non-standard refresh rate
596a10cf76eSAxel Dörfler 
597a10cf76eSAxel Dörfler 	fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh);
598a10cf76eSAxel Dörfler 	fOtherRefresh->SetMarked(true);
599a10cf76eSAxel Dörfler 
600a10cf76eSAxel Dörfler 	fRefreshMenu->Superitem()->SetLabel(string.String());
601a10cf76eSAxel Dörfler 
602a10cf76eSAxel Dörfler 	string.Append("/Other" B_UTF8_ELLIPSIS);
603a10cf76eSAxel Dörfler 	fOtherRefresh->SetLabel(string.String());
604a10cf76eSAxel Dörfler }
605a10cf76eSAxel Dörfler 
606a10cf76eSAxel Dörfler 
607a10cf76eSAxel Dörfler void
6085de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView()
609a10cf76eSAxel Dörfler {
610a10cf76eSAxel Dörfler 	BMessage updateMessage(UPDATE_DESKTOP_MSG);
611a10cf76eSAxel Dörfler 	updateMessage.AddInt32("width", fSelected.width);
612a10cf76eSAxel Dörfler 	updateMessage.AddInt32("height", fSelected.height);
613a10cf76eSAxel Dörfler 
614a10cf76eSAxel Dörfler 	PostMessage(&updateMessage, fMonitorView);
615a10cf76eSAxel Dörfler }
616a10cf76eSAxel Dörfler 
617a10cf76eSAxel Dörfler 
618a10cf76eSAxel Dörfler void
6195de171daSAxel Dörfler ScreenWindow::_UpdateControls()
620a10cf76eSAxel Dörfler {
621b21d610eSAxel Dörfler 	_UpdateWorkspaceButtons();
622b21d610eSAxel Dörfler 
623a10cf76eSAxel Dörfler 	BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays);
624a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
625a10cf76eSAxel Dörfler 		item->SetMarked(true);
626a10cf76eSAxel Dörfler 
627a10cf76eSAxel Dörfler 	item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel);
628a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
629a10cf76eSAxel Dörfler 		item->SetMarked(true);
630a10cf76eSAxel Dörfler 
631a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) {
632a10cf76eSAxel Dörfler 		item = fTVStandardMenu->ItemAt(i);
633a10cf76eSAxel Dörfler 
634a10cf76eSAxel Dörfler 		uint32 tvStandard;
635a10cf76eSAxel Dörfler 		item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard);
636a10cf76eSAxel Dörfler 		if (tvStandard == fSelected.tv_standard) {
637a10cf76eSAxel Dörfler 			if (!item->IsMarked())
638a10cf76eSAxel Dörfler 				item->SetMarked(true);
639a10cf76eSAxel Dörfler 			break;
640a10cf76eSAxel Dörfler 		}
641a10cf76eSAxel Dörfler 	}
642a10cf76eSAxel Dörfler 
6435de171daSAxel Dörfler 	_CheckResolutionMenu();
6445de171daSAxel Dörfler 	_CheckColorMenu();
6455de171daSAxel Dörfler 	_CheckRefreshMenu();
646a10cf76eSAxel Dörfler 
647a10cf76eSAxel Dörfler 	BString string;
648a10cf76eSAxel Dörfler 	resolution_to_string(fSelected, string);
649a10cf76eSAxel Dörfler 	item = fResolutionMenu->FindItem(string.String());
650a10cf76eSAxel Dörfler 
651a10cf76eSAxel Dörfler 	if (item != NULL) {
652a10cf76eSAxel Dörfler 		if (!item->IsMarked())
653a10cf76eSAxel Dörfler 			item->SetMarked(true);
654a10cf76eSAxel Dörfler 	} else {
655a10cf76eSAxel Dörfler 		// this is bad luck - if mode has been set via screen references,
656a10cf76eSAxel Dörfler 		// this case cannot occur; there are three possible solutions:
657a10cf76eSAxel Dörfler 		// 1. add a new resolution to list
658a10cf76eSAxel Dörfler 		//    - we had to remove it as soon as a "valid" one is selected
659a10cf76eSAxel Dörfler 		//    - we don't know which frequencies/bit depths are supported
660a10cf76eSAxel Dörfler 		//    - as long as we haven't the GMT formula to create
661a10cf76eSAxel Dörfler 		//      parameters for any resolution given, we cannot
662a10cf76eSAxel Dörfler 		//      really set current mode - it's just not in the list
663a10cf76eSAxel Dörfler 		// 2. choose nearest resolution
664a10cf76eSAxel Dörfler 		//    - probably a good idea, but implies coding and testing
665a10cf76eSAxel Dörfler 		// 3. choose lowest resolution
666a10cf76eSAxel Dörfler 		//    - do you really think we are so lazy? yes, we are
667a10cf76eSAxel Dörfler 		item = fResolutionMenu->ItemAt(0);
668a10cf76eSAxel Dörfler 		if (item)
669a10cf76eSAxel Dörfler 			item->SetMarked(true);
670a10cf76eSAxel Dörfler 
671a10cf76eSAxel Dörfler 		// okay - at least we set menu label to active resolution
672a10cf76eSAxel Dörfler 		fResolutionMenu->Superitem()->SetLabel(string.String());
673a10cf76eSAxel Dörfler 	}
674a10cf76eSAxel Dörfler 
675a10cf76eSAxel Dörfler 	// mark active combine mode
676a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kCombineModeCount; i++) {
677a10cf76eSAxel Dörfler 		if (kCombineModes[i].mode == fSelected.combine) {
678a10cf76eSAxel Dörfler 			item = fCombineMenu->ItemAt(i);
679a10cf76eSAxel Dörfler 			if (item && !item->IsMarked())
680a10cf76eSAxel Dörfler 				item->SetMarked(true);
681a10cf76eSAxel Dörfler 			break;
682a10cf76eSAxel Dörfler 		}
683a10cf76eSAxel Dörfler 	}
684a10cf76eSAxel Dörfler 
685a10cf76eSAxel Dörfler 	item = fColorsMenu->ItemAt(0);
686a10cf76eSAxel Dörfler 
687a10cf76eSAxel Dörfler 	for (int32 i = kColorSpaceCount; i-- > 0;) {
6885de171daSAxel Dörfler 		if (kColorSpaces[i].space == fSelected.space
6895de171daSAxel Dörfler 			|| (kColorSpaces[i].space == B_RGB32
6905de171daSAxel Dörfler 				&& fSelected.space == B_RGB24)) {
691a10cf76eSAxel Dörfler 			item = fColorsMenu->ItemAt(i);
692a10cf76eSAxel Dörfler 			break;
693a10cf76eSAxel Dörfler 		}
694a10cf76eSAxel Dörfler 	}
695a10cf76eSAxel Dörfler 
696a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
697a10cf76eSAxel Dörfler 		item->SetMarked(true);
698a10cf76eSAxel Dörfler 
699a10cf76eSAxel Dörfler 	string.Truncate(0);
7005de171daSAxel Dörfler 	uint32 bitsPerPixel = fSelected.BitsPerPixel();
7015de171daSAxel Dörfler 	// advertize 24 bit mode as 32 bit to avoid confusion
7025de171daSAxel Dörfler 	if (bitsPerPixel == 24)
7035de171daSAxel Dörfler 		bitsPerPixel = 32;
7045de171daSAxel Dörfler 
7055de171daSAxel Dörfler 	string << bitsPerPixel << " Bits/Pixel";
706a10cf76eSAxel Dörfler 	if (string != fColorsMenu->Superitem()->Label())
707a10cf76eSAxel Dörfler 		fColorsMenu->Superitem()->SetLabel(string.String());
708a10cf76eSAxel Dörfler 
7095de171daSAxel Dörfler 	_UpdateMonitorView();
7105de171daSAxel Dörfler 	_UpdateRefreshControl();
711a10cf76eSAxel Dörfler 
7125de171daSAxel Dörfler 	_CheckApplyEnabled();
713a10cf76eSAxel Dörfler }
714a10cf76eSAxel Dörfler 
715a10cf76eSAxel Dörfler 
71612580984SAxel Dörfler /*! Reflect active mode in chosen settings */
717a10cf76eSAxel Dörfler void
7185de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode()
719a10cf76eSAxel Dörfler {
72012580984SAxel Dörfler 	// Usually, this function gets called after a mode
721a10cf76eSAxel Dörfler 	// has been set manually; still, as the graphics driver
722a10cf76eSAxel Dörfler 	// is free to fiddle with mode passed, we better ask
723a10cf76eSAxel Dörfler 	// what kind of mode we actually got
724a10cf76eSAxel Dörfler 	fScreenMode.Get(fActive);
725a10cf76eSAxel Dörfler 	fSelected = fActive;
726a10cf76eSAxel Dörfler 
72712966d04SAxel Dörfler 	_UpdateMonitor();
7285de171daSAxel Dörfler 	_UpdateControls();
729a10cf76eSAxel Dörfler }
730a10cf76eSAxel Dörfler 
731a10cf76eSAxel Dörfler 
732a10cf76eSAxel Dörfler void
733b21d610eSAxel Dörfler ScreenWindow::_UpdateWorkspaceButtons()
734b21d610eSAxel Dörfler {
735b21d610eSAxel Dörfler 	uint32 columns;
736b21d610eSAxel Dörfler 	uint32 rows;
737b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
738b21d610eSAxel Dörfler 
739b21d610eSAxel Dörfler 	char text[32];
740b21d610eSAxel Dörfler 	snprintf(text, sizeof(text), "%ld", columns);
741b21d610eSAxel Dörfler 	fColumnsControl->SetText(text);
742b21d610eSAxel Dörfler 
743b21d610eSAxel Dörfler 	snprintf(text, sizeof(text), "%ld", rows);
744b21d610eSAxel Dörfler 	fRowsControl->SetText(text);
745b21d610eSAxel Dörfler 
746b21d610eSAxel Dörfler 	_GetColumnRowButton(true, false)->SetEnabled(columns != 1 && rows != 32);
747b21d610eSAxel Dörfler 	_GetColumnRowButton(true, true)->SetEnabled((columns + 1) * rows < 32);
748b21d610eSAxel Dörfler 	_GetColumnRowButton(false, false)->SetEnabled(rows != 1 && columns != 32);
749b21d610eSAxel Dörfler 	_GetColumnRowButton(false, true)->SetEnabled(columns * (rows + 1) < 32);
750b21d610eSAxel Dörfler }
751b21d610eSAxel Dörfler 
752b21d610eSAxel Dörfler 
753b21d610eSAxel Dörfler void
754a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode)
755a10cf76eSAxel Dörfler {
756a10cf76eSAxel Dörfler 	// move window on screen, if necessary
757a10cf76eSAxel Dörfler 	if (frame.right <= Frame().right
758a10cf76eSAxel Dörfler 		&& frame.bottom <= Frame().bottom) {
759a10cf76eSAxel Dörfler 		MoveTo((frame.Width() - Frame().Width()) / 2,
760a10cf76eSAxel Dörfler 			(frame.Height() - Frame().Height()) / 2);
761a10cf76eSAxel Dörfler 	}
762a10cf76eSAxel Dörfler }
763a10cf76eSAxel Dörfler 
764a10cf76eSAxel Dörfler 
765a10cf76eSAxel Dörfler void
766a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state)
767a10cf76eSAxel Dörfler {
768abc649b8SWaldemar Kornewald 	fScreenMode.GetOriginalMode(fOriginal, workspace);
7695de171daSAxel Dörfler 	_UpdateActiveMode();
770a10cf76eSAxel Dörfler 
7716edaa0f6SStefano Ceccherini 	BMessage message(UPDATE_DESKTOP_COLOR_MSG);
7726edaa0f6SStefano Ceccherini 	PostMessage(&message, fMonitorView);
773a10cf76eSAxel Dörfler }
774a10cf76eSAxel Dörfler 
775a10cf76eSAxel Dörfler 
776a10cf76eSAxel Dörfler void
777a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message)
778a10cf76eSAxel Dörfler {
779a10cf76eSAxel Dörfler 	switch (message->what) {
780a10cf76eSAxel Dörfler 		case WORKSPACE_CHECK_MSG:
7815de171daSAxel Dörfler 			_CheckApplyEnabled();
782a10cf76eSAxel Dörfler 			break;
783a10cf76eSAxel Dörfler 
784b21d610eSAxel Dörfler 		case kMsgWorkspaceLayoutChanged:
785a10cf76eSAxel Dörfler 		{
786b21d610eSAxel Dörfler 			int32 deltaX = 0;
787b21d610eSAxel Dörfler 			int32 deltaY = 0;
788b21d610eSAxel Dörfler 			message->FindInt32("delta_x", &deltaX);
789b21d610eSAxel Dörfler 			message->FindInt32("delta_y", &deltaY);
790b21d610eSAxel Dörfler 
791b21d610eSAxel Dörfler 			if (deltaX == 0 && deltaY == 0)
792b21d610eSAxel Dörfler 				break;
793b21d610eSAxel Dörfler 
794b21d610eSAxel Dörfler 			uint32 newColumns;
795b21d610eSAxel Dörfler 			uint32 newRows;
796b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(&newColumns, &newRows);
797b21d610eSAxel Dörfler 
798b21d610eSAxel Dörfler 			newColumns += deltaX;
799b21d610eSAxel Dörfler 			newRows += deltaY;
800b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(newColumns, newRows);
801b21d610eSAxel Dörfler 
802b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
8035de171daSAxel Dörfler 			_CheckApplyEnabled();
804b21d610eSAxel Dörfler 			break;
805abc649b8SWaldemar Kornewald 		}
806b21d610eSAxel Dörfler 
807b21d610eSAxel Dörfler 		case kMsgWorkspaceColumnsChanged:
808b21d610eSAxel Dörfler 		{
809b21d610eSAxel Dörfler 			uint32 newColumns = strtoul(fColumnsControl->Text(), NULL, 10);
810b21d610eSAxel Dörfler 
811b21d610eSAxel Dörfler 			uint32 rows;
812b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(NULL, &rows);
813b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(newColumns, rows);
814b21d610eSAxel Dörfler 
815b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
816b21d610eSAxel Dörfler 			_CheckApplyEnabled();
817b21d610eSAxel Dörfler 			break;
818b21d610eSAxel Dörfler 		}
819b21d610eSAxel Dörfler 
820b21d610eSAxel Dörfler 		case kMsgWorkspaceRowsChanged:
821b21d610eSAxel Dörfler 		{
822b21d610eSAxel Dörfler 			uint32 newRows = strtoul(fRowsControl->Text(), NULL, 10);
823b21d610eSAxel Dörfler 
824b21d610eSAxel Dörfler 			uint32 columns;
825b21d610eSAxel Dörfler 			BPrivate::get_workspaces_layout(&columns, NULL);
826b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(columns, newRows);
827b21d610eSAxel Dörfler 
828b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
829b21d610eSAxel Dörfler 			_CheckApplyEnabled();
830a10cf76eSAxel Dörfler 			break;
831a10cf76eSAxel Dörfler 		}
832a10cf76eSAxel Dörfler 
833a10cf76eSAxel Dörfler 		case POP_RESOLUTION_MSG:
834a10cf76eSAxel Dörfler 		{
835a10cf76eSAxel Dörfler 			message->FindInt32("width", &fSelected.width);
836a10cf76eSAxel Dörfler 			message->FindInt32("height", &fSelected.height);
837a10cf76eSAxel Dörfler 
8385de171daSAxel Dörfler 			_CheckColorMenu();
8395de171daSAxel Dörfler 			_CheckRefreshMenu();
840a10cf76eSAxel Dörfler 
8415de171daSAxel Dörfler 			_UpdateMonitorView();
8425de171daSAxel Dörfler 			_UpdateRefreshControl();
843a10cf76eSAxel Dörfler 
8445de171daSAxel Dörfler 			_CheckApplyEnabled();
845a10cf76eSAxel Dörfler 			break;
846a10cf76eSAxel Dörfler 		}
847a10cf76eSAxel Dörfler 
848a10cf76eSAxel Dörfler 		case POP_COLORS_MSG:
849a10cf76eSAxel Dörfler 		{
850a10cf76eSAxel Dörfler 			message->FindInt32("space", (int32 *)&fSelected.space);
851a10cf76eSAxel Dörfler 
852a10cf76eSAxel Dörfler 			BString string;
853a10cf76eSAxel Dörfler 			string << fSelected.BitsPerPixel() << " Bits/Pixel";
854a10cf76eSAxel Dörfler 			fColorsMenu->Superitem()->SetLabel(string.String());
855a10cf76eSAxel Dörfler 
8565de171daSAxel Dörfler 			_CheckApplyEnabled();
857a10cf76eSAxel Dörfler 			break;
858a10cf76eSAxel Dörfler 		}
859a10cf76eSAxel Dörfler 
860a10cf76eSAxel Dörfler 		case POP_REFRESH_MSG:
861a40498e2SWaldemar Kornewald 		{
862a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
863a10cf76eSAxel Dörfler 			fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS);
864a10cf76eSAxel Dörfler 				// revert "Other…" label - it might have had a refresh rate prefix
865a10cf76eSAxel Dörfler 
8665de171daSAxel Dörfler 			_CheckApplyEnabled();
867a10cf76eSAxel Dörfler 			break;
868a40498e2SWaldemar Kornewald 		}
869a10cf76eSAxel Dörfler 
870a10cf76eSAxel Dörfler 		case POP_OTHER_REFRESH_MSG:
871a10cf76eSAxel Dörfler 		{
87229e8a73aSAxel Dörfler 			// make sure menu shows something useful
8735de171daSAxel Dörfler 			_UpdateRefreshControl();
874a10cf76eSAxel Dörfler 
87529e8a73aSAxel Dörfler 			float min = 0, max = 999;
87629e8a73aSAxel Dörfler 			fScreenMode.GetRefreshLimits(fSelected, min, max);
87729e8a73aSAxel Dörfler 			if (min < gMinRefresh)
87829e8a73aSAxel Dörfler 				min = gMinRefresh;
87929e8a73aSAxel Dörfler 			if (max > gMaxRefresh)
88029e8a73aSAxel Dörfler 				max = gMaxRefresh;
88129e8a73aSAxel Dörfler 
882c5d10f7aSAxel Dörfler 			RefreshWindow *fRefreshWindow = new RefreshWindow(
883c5d10f7aSAxel Dörfler 				fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, min, max);
884a10cf76eSAxel Dörfler 			fRefreshWindow->Show();
885a10cf76eSAxel Dörfler 			break;
886a10cf76eSAxel Dörfler 		}
887a10cf76eSAxel Dörfler 
888a10cf76eSAxel Dörfler 		case SET_CUSTOM_REFRESH_MSG:
889a10cf76eSAxel Dörfler 		{
890a10cf76eSAxel Dörfler 			// user pressed "done" in "Other…" refresh dialog;
891a10cf76eSAxel Dörfler 			// select the refresh rate chosen
892a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
893a10cf76eSAxel Dörfler 
8945de171daSAxel Dörfler 			_UpdateRefreshControl();
8955de171daSAxel Dörfler 			_CheckApplyEnabled();
896a10cf76eSAxel Dörfler 			break;
897a10cf76eSAxel Dörfler 		}
898a10cf76eSAxel Dörfler 
899a10cf76eSAxel Dörfler 		case POP_COMBINE_DISPLAYS_MSG:
900a10cf76eSAxel Dörfler 		{
901a10cf76eSAxel Dörfler 			// new combine mode has bee chosen
902a10cf76eSAxel Dörfler 			int32 mode;
903a10cf76eSAxel Dörfler 			if (message->FindInt32("mode", &mode) == B_OK)
904a10cf76eSAxel Dörfler 				fSelected.combine = (combine_mode)mode;
905a10cf76eSAxel Dörfler 
9065de171daSAxel Dörfler 			_CheckResolutionMenu();
9075de171daSAxel Dörfler 			_CheckApplyEnabled();
908a10cf76eSAxel Dörfler 			break;
909a10cf76eSAxel Dörfler 		}
910a10cf76eSAxel Dörfler 
911a10cf76eSAxel Dörfler 		case POP_SWAP_DISPLAYS_MSG:
912a10cf76eSAxel Dörfler 			message->FindBool("swap", &fSelected.swap_displays);
9135de171daSAxel Dörfler 			_CheckApplyEnabled();
914a10cf76eSAxel Dörfler 			break;
915a10cf76eSAxel Dörfler 
916a10cf76eSAxel Dörfler 		case POP_USE_LAPTOP_PANEL_MSG:
917a10cf76eSAxel Dörfler 			message->FindBool("use", &fSelected.use_laptop_panel);
9185de171daSAxel Dörfler 			_CheckApplyEnabled();
919a10cf76eSAxel Dörfler 			break;
920a10cf76eSAxel Dörfler 
921a10cf76eSAxel Dörfler 		case POP_TV_STANDARD_MSG:
922a10cf76eSAxel Dörfler 			message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard);
9235de171daSAxel Dörfler 			_CheckApplyEnabled();
924a10cf76eSAxel Dörfler 			break;
925a10cf76eSAxel Dörfler 
926df3f5bacSStephan Aßmus 		case BUTTON_LAUNCH_BACKGROUNDS_MSG:
9276f095d6aSRyan Leavengood 			if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) {
9286f095d6aSRyan Leavengood 				app_info info;
9296f095d6aSRyan Leavengood 				be_roster->GetAppInfo(kBackgroundsSignature, &info);
9306f095d6aSRyan Leavengood 				be_roster->ActivateApp(info.team);
9316f095d6aSRyan Leavengood 			}
932df3f5bacSStephan Aßmus 			break;
933df3f5bacSStephan Aßmus 
934a10cf76eSAxel Dörfler 		case BUTTON_DEFAULTS_MSG:
935a10cf76eSAxel Dörfler 		{
9364be51fe3SWaldemar Kornewald 			// TODO: get preferred settings of screen
937a10cf76eSAxel Dörfler 			fSelected.width = 640;
938a10cf76eSAxel Dörfler 			fSelected.height = 480;
939a10cf76eSAxel Dörfler 			fSelected.space = B_CMAP8;
940a10cf76eSAxel Dörfler 			fSelected.refresh = 60.0;
941a10cf76eSAxel Dörfler 			fSelected.combine = kCombineDisable;
942a10cf76eSAxel Dörfler 			fSelected.swap_displays = false;
943a10cf76eSAxel Dörfler 			fSelected.use_laptop_panel = false;
944a10cf76eSAxel Dörfler 			fSelected.tv_standard = 0;
945a10cf76eSAxel Dörfler 
946b21d610eSAxel Dörfler 			// TODO: workspace defaults
947abc649b8SWaldemar Kornewald 
9485de171daSAxel Dörfler 			_UpdateControls();
949a10cf76eSAxel Dörfler 			break;
950a10cf76eSAxel Dörfler 		}
951a10cf76eSAxel Dörfler 
95210e9b12fSWaldemar Kornewald 		case BUTTON_UNDO_MSG:
953abc649b8SWaldemar Kornewald 			fTempScreenMode.Revert();
9545de171daSAxel Dörfler 			_UpdateActiveMode();
955abc649b8SWaldemar Kornewald 			break;
956abc649b8SWaldemar Kornewald 
957abc649b8SWaldemar Kornewald 		case BUTTON_REVERT_MSG:
958abc649b8SWaldemar Kornewald 		{
959abc649b8SWaldemar Kornewald 			fModified = false;
960199893c3SAxel Dörfler 			fBootWorkspaceApplied = false;
961abc649b8SWaldemar Kornewald 
962b21d610eSAxel Dörfler 			// ScreenMode::Revert() assumes that we first set the correct
963b21d610eSAxel Dörfler 			// number of workspaces
964b21d610eSAxel Dörfler 
965b21d610eSAxel Dörfler 			BPrivate::set_workspaces_layout(fOriginalWorkspacesColumns,
966b21d610eSAxel Dörfler 				fOriginalWorkspacesRows);
967b21d610eSAxel Dörfler 			_UpdateWorkspaceButtons();
968b21d610eSAxel Dörfler 
969a10cf76eSAxel Dörfler 			fScreenMode.Revert();
9705de171daSAxel Dörfler 			_UpdateActiveMode();
971a10cf76eSAxel Dörfler 			break;
972abc649b8SWaldemar Kornewald 		}
973a10cf76eSAxel Dörfler 
974a10cf76eSAxel Dörfler 		case BUTTON_APPLY_MSG:
9755de171daSAxel Dörfler 			_Apply();
976a10cf76eSAxel Dörfler 			break;
977a10cf76eSAxel Dörfler 
978abc649b8SWaldemar Kornewald 		case MAKE_INITIAL_MSG:
979abc649b8SWaldemar Kornewald 			// user pressed "keep" in confirmation dialog
980abc649b8SWaldemar Kornewald 			fModified = true;
9815de171daSAxel Dörfler 			_UpdateActiveMode();
982a10cf76eSAxel Dörfler 			break;
983a10cf76eSAxel Dörfler 
984a10cf76eSAxel Dörfler 		default:
985a10cf76eSAxel Dörfler 			BWindow::MessageReceived(message);
986a10cf76eSAxel Dörfler 			break;
987a10cf76eSAxel Dörfler 	}
988a10cf76eSAxel Dörfler }
989a10cf76eSAxel Dörfler 
990a10cf76eSAxel Dörfler 
99112580984SAxel Dörfler status_t
99212580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const
99312580984SAxel Dörfler {
99412580984SAxel Dörfler 	BPath path;
99512580984SAxel Dörfler 	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
99612580984SAxel Dörfler 	if (status < B_OK)
99712580984SAxel Dörfler 		return status;
99812580984SAxel Dörfler 
99912580984SAxel Dörfler 	path.Append("kernel/drivers");
100012580984SAxel Dörfler 	status = create_directory(path.Path(), 0755);
100112580984SAxel Dörfler 	if (status < B_OK)
100212580984SAxel Dörfler 		return status;
100312580984SAxel Dörfler 
100412580984SAxel Dörfler 	path.Append("vesa");
100512580984SAxel Dörfler 	BFile file;
100612580984SAxel Dörfler 	status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
100712580984SAxel Dörfler 	if (status < B_OK)
100812580984SAxel Dörfler 		return status;
100912580984SAxel Dörfler 
101012580984SAxel Dörfler 	char buffer[256];
101112580984SAxel Dörfler 	snprintf(buffer, sizeof(buffer), "mode %ld %ld %ld\n",
101212580984SAxel Dörfler 		mode.width, mode.height, mode.BitsPerPixel());
101312580984SAxel Dörfler 
101412580984SAxel Dörfler 	ssize_t bytesWritten = file.Write(buffer, strlen(buffer));
101512580984SAxel Dörfler 	if (bytesWritten < B_OK)
101612580984SAxel Dörfler 		return bytesWritten;
101712580984SAxel Dörfler 
101812580984SAxel Dörfler 	return B_OK;
101912580984SAxel Dörfler }
102012580984SAxel Dörfler 
102112580984SAxel Dörfler 
1022b21d610eSAxel Dörfler BButton*
1023b21d610eSAxel Dörfler ScreenWindow::_CreateColumnRowButton(bool columns, bool plus)
1024b21d610eSAxel Dörfler {
1025b21d610eSAxel Dörfler 	BMessage* message = new BMessage(kMsgWorkspaceLayoutChanged);
1026b21d610eSAxel Dörfler 	message->AddInt32("delta_x", columns ? (plus ? 1 : -1) : 0);
1027b21d610eSAxel Dörfler 	message->AddInt32("delta_y", !columns ? (plus ? 1 : -1) : 0);
1028b21d610eSAxel Dörfler 
1029b21d610eSAxel Dörfler 	BButton* button = new BButton(plus ? "+" : "-", message);
1030b21d610eSAxel Dörfler 	button->SetFontSize(be_plain_font->Size() * 0.9);
1031b21d610eSAxel Dörfler 
1032b21d610eSAxel Dörfler 	BSize size = button->MinSize();
1033b21d610eSAxel Dörfler 	size.width = button->StringWidth("+") + 16;
1034b21d610eSAxel Dörfler 	button->SetExplicitMinSize(size);
1035b21d610eSAxel Dörfler 	button->SetExplicitMaxSize(size);
1036b21d610eSAxel Dörfler 
1037b21d610eSAxel Dörfler 	fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)] = button;
1038b21d610eSAxel Dörfler 	return button;
1039b21d610eSAxel Dörfler }
1040b21d610eSAxel Dörfler 
1041b21d610eSAxel Dörfler 
1042b21d610eSAxel Dörfler BButton*
1043b21d610eSAxel Dörfler ScreenWindow::_GetColumnRowButton(bool columns, bool plus)
1044b21d610eSAxel Dörfler {
1045b21d610eSAxel Dörfler 	return fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)];
1046b21d610eSAxel Dörfler }
1047b21d610eSAxel Dörfler 
1048b21d610eSAxel Dörfler 
1049a10cf76eSAxel Dörfler void
10505de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled()
1051a10cf76eSAxel Dörfler {
105227c43a2dSRene Gollent 	fApplyButton->SetEnabled(fSelected != fActive
105327c43a2dSRene Gollent 		|| fAllWorkspacesItem->IsMarked());
1054b21d610eSAxel Dörfler 
1055b21d610eSAxel Dörfler 	uint32 columns;
1056b21d610eSAxel Dörfler 	uint32 rows;
1057b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&columns, &rows);
1058b21d610eSAxel Dörfler 
1059b21d610eSAxel Dörfler 	fRevertButton->SetEnabled(columns != fOriginalWorkspacesColumns
1060b21d610eSAxel Dörfler 		|| rows != fOriginalWorkspacesRows
10615de171daSAxel Dörfler 		|| fSelected != fOriginal);
1062a10cf76eSAxel Dörfler }
1063a10cf76eSAxel Dörfler 
1064a10cf76eSAxel Dörfler 
1065a10cf76eSAxel Dörfler void
10665de171daSAxel Dörfler ScreenWindow::_UpdateOriginal()
1067abc649b8SWaldemar Kornewald {
1068b21d610eSAxel Dörfler 	BPrivate::get_workspaces_layout(&fOriginalWorkspacesColumns,
1069b21d610eSAxel Dörfler 		&fOriginalWorkspacesRows);
1070b21d610eSAxel Dörfler 
1071abc649b8SWaldemar Kornewald 	fScreenMode.Get(fOriginal);
1072abc649b8SWaldemar Kornewald 	fScreenMode.UpdateOriginalModes();
1073abc649b8SWaldemar Kornewald }
1074abc649b8SWaldemar Kornewald 
1075abc649b8SWaldemar Kornewald 
1076abc649b8SWaldemar Kornewald void
107712966d04SAxel Dörfler ScreenWindow::_UpdateMonitor()
107812966d04SAxel Dörfler {
107912966d04SAxel Dörfler 	monitor_info info;
108012966d04SAxel Dörfler 	float diagonalInches;
108112966d04SAxel Dörfler 	status_t status = fScreenMode.GetMonitorInfo(info, &diagonalInches);
108212966d04SAxel Dörfler 
108312966d04SAxel Dörfler 	if (status != B_OK) {
108412966d04SAxel Dörfler 		if (!fMonitorInfo->IsHidden())
108512966d04SAxel Dörfler 			fMonitorInfo->Hide();
108612966d04SAxel Dörfler 		return;
108712966d04SAxel Dörfler 	}
108812966d04SAxel Dörfler 
108912966d04SAxel Dörfler 	char text[256];
1090*66ab1666SAxel Dörfler 	snprintf(text, sizeof(text), "%s%s%s %g\"", info.vendor,
1091*66ab1666SAxel Dörfler 		info.name[0] ? " " : "", info.name, diagonalInches);
109212966d04SAxel Dörfler 
109312966d04SAxel Dörfler 	fMonitorInfo->SetText(text);
109412966d04SAxel Dörfler 
109512966d04SAxel Dörfler 	if (fMonitorInfo->IsHidden())
109612966d04SAxel Dörfler 		fMonitorInfo->Show();
109712966d04SAxel Dörfler }
109812966d04SAxel Dörfler 
109912966d04SAxel Dörfler 
110012966d04SAxel Dörfler void
11015de171daSAxel Dörfler ScreenWindow::_Apply()
1102a10cf76eSAxel Dörfler {
1103abc649b8SWaldemar Kornewald 	// make checkpoint, so we can undo these changes
1104abc649b8SWaldemar Kornewald 	fTempScreenMode.UpdateOriginalModes();
110507184a9eSAxel Dörfler 	status_t status = fScreenMode.Set(fSelected);
110607184a9eSAxel Dörfler 	if (status == B_OK) {
1107abc649b8SWaldemar Kornewald 		// use the mode that has eventually been set and
1108abc649b8SWaldemar Kornewald 		// thus we know to be working; it can differ from
1109abc649b8SWaldemar Kornewald 		// the mode selected by user due to hardware limitation
1110abc649b8SWaldemar Kornewald 		display_mode newMode;
1111abc649b8SWaldemar Kornewald 		BScreen screen(this);
1112abc649b8SWaldemar Kornewald 		screen.GetMode(&newMode);
1113abc649b8SWaldemar Kornewald 
1114abc649b8SWaldemar Kornewald 		if (fAllWorkspacesItem->IsMarked()) {
1115abc649b8SWaldemar Kornewald 			int32 originatingWorkspace = current_workspace();
1116abc649b8SWaldemar Kornewald 			for (int32 i = 0; i < count_workspaces(); i++) {
1117abc649b8SWaldemar Kornewald 				if (i != originatingWorkspace)
1118abc649b8SWaldemar Kornewald 					screen.SetMode(i, &newMode, true);
1119abc649b8SWaldemar Kornewald 			}
1120199893c3SAxel Dörfler 			fBootWorkspaceApplied = true;
1121199893c3SAxel Dörfler 		} else {
1122199893c3SAxel Dörfler 			if (current_workspace() == 0)
1123199893c3SAxel Dörfler 				fBootWorkspaceApplied = true;
1124abc649b8SWaldemar Kornewald 		}
1125abc649b8SWaldemar Kornewald 
1126a10cf76eSAxel Dörfler 		fActive = fSelected;
1127a10cf76eSAxel Dörfler 
1128abc649b8SWaldemar Kornewald 		// TODO: only show alert when this is an unknown mode
1129a10cf76eSAxel Dörfler 		BWindow* window = new AlertWindow(this);
1130a10cf76eSAxel Dörfler 		window->Show();
113107184a9eSAxel Dörfler 	} else {
113207184a9eSAxel Dörfler 		char message[256];
113307184a9eSAxel Dörfler 		snprintf(message, sizeof(message),
113407184a9eSAxel Dörfler 			"The screen mode could not be set:\n\t%s\n", screen_errors(status));
113507184a9eSAxel Dörfler 		BAlert* alert = new BAlert("Screen Alert", message, "Okay", NULL, NULL,
113607184a9eSAxel Dörfler 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
113707184a9eSAxel Dörfler 		alert->Go();
1138a10cf76eSAxel Dörfler 	}
113907184a9eSAxel Dörfler }
114007184a9eSAxel Dörfler 
1141