xref: /haiku/src/preferences/screen/ScreenWindow.cpp (revision 6bda235a592737fa04aefa756026f32892810715)
1a10cf76eSAxel Dörfler /*
2b72c4836SAlexandre Deckner  * Copyright 2001-2008, 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 
16a10cf76eSAxel Dörfler #include "AlertWindow.h"
17a10cf76eSAxel Dörfler #include "Constants.h"
18a10cf76eSAxel Dörfler #include "RefreshWindow.h"
19a10cf76eSAxel Dörfler #include "MonitorView.h"
20a10cf76eSAxel Dörfler #include "ScreenSettings.h"
21a10cf76eSAxel Dörfler #include "ScreenWindow.h"
22a10cf76eSAxel Dörfler #include "Utility.h"
23a10cf76eSAxel Dörfler 
24a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant.
25a10cf76eSAxel Dörfler  * It's a solution that works with the current BeOS interface that Haiku
26a10cf76eSAxel Dörfler  * adopted.
27a10cf76eSAxel Dörfler  * However, it's not a nice and clean solution. Don't use this header in any
28a10cf76eSAxel Dörfler  * application if you can avoid it. No other driver is using this, or should
29a10cf76eSAxel Dörfler  * be using this.
30a10cf76eSAxel Dörfler  * It will be replaced as soon as we introduce an updated accelerant interface
31a10cf76eSAxel Dörfler  * which may even happen before R1 hits the streets.
32a10cf76eSAxel Dörfler  */
33a10cf76eSAxel Dörfler #include "multimon.h"	// the usual: DANGER WILL, ROBINSON!
34a10cf76eSAxel Dörfler 
3512580984SAxel Dörfler #include <Alert.h>
3612580984SAxel Dörfler #include <Application.h>
3712580984SAxel Dörfler #include <Box.h>
3812580984SAxel Dörfler #include <Button.h>
3912580984SAxel Dörfler #include <Directory.h>
4012580984SAxel Dörfler #include <File.h>
4112580984SAxel Dörfler #include <FindDirectory.h>
4212580984SAxel Dörfler #include <InterfaceDefs.h>
4312580984SAxel Dörfler #include <MenuBar.h>
4412580984SAxel Dörfler #include <MenuItem.h>
4512580984SAxel Dörfler #include <MenuField.h>
4612580984SAxel Dörfler #include <Messenger.h>
4712580984SAxel Dörfler #include <Path.h>
4812580984SAxel Dörfler #include <PopUpMenu.h>
4912580984SAxel Dörfler #include <Screen.h>
5012580984SAxel Dörfler #include <String.h>
5112580984SAxel Dörfler #include <Roster.h>
5212580984SAxel Dörfler #include <Window.h>
5312580984SAxel Dörfler 
5412580984SAxel Dörfler #include <stdio.h>
5512580984SAxel Dörfler #include <stdlib.h>
5612580984SAxel Dörfler #include <string.h>
5712580984SAxel Dörfler 
58a10cf76eSAxel Dörfler 
59c5d80d47SAxel Dörfler const char* kBackgroundsSignature = "application/x-vnd.haiku-backgrounds";
60c5d80d47SAxel Dörfler 
61a10cf76eSAxel Dörfler // list of officially supported colour spaces
62a10cf76eSAxel Dörfler static const struct {
63a10cf76eSAxel Dörfler 	color_space	space;
64a10cf76eSAxel Dörfler 	int32		bits_per_pixel;
65a10cf76eSAxel Dörfler 	const char*	label;
66a10cf76eSAxel Dörfler } kColorSpaces[] = {
67a10cf76eSAxel Dörfler 	{ B_CMAP8, 8, "8 Bits/Pixel, 256 Colors" },
68a10cf76eSAxel Dörfler 	{ B_RGB15, 15, "15 Bits/Pixel, 32768 Colors" },
69a10cf76eSAxel Dörfler 	{ B_RGB16, 16, "16 Bits/Pixel, 65536 Colors" },
70a10cf76eSAxel Dörfler 	{ B_RGB32, 32, "32 Bits/Pixel, 16 Million Colors" }
71a10cf76eSAxel Dörfler };
72a10cf76eSAxel Dörfler static const int32 kColorSpaceCount = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]);
73a10cf76eSAxel Dörfler 
74a10cf76eSAxel Dörfler // list of standard refresh rates
75a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 };
76a10cf76eSAxel Dörfler static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]);
77a10cf76eSAxel Dörfler 
78a10cf76eSAxel Dörfler // list of combine modes
79a10cf76eSAxel Dörfler static const struct {
80a10cf76eSAxel Dörfler 	combine_mode	mode;
81a10cf76eSAxel Dörfler 	const char		*name;
82a10cf76eSAxel Dörfler } kCombineModes[] = {
83a10cf76eSAxel Dörfler 	{ kCombineDisable, "disable" },
84a10cf76eSAxel Dörfler 	{ kCombineHorizontally, "horizontally" },
85a10cf76eSAxel Dörfler 	{ kCombineVertically, "vertically" }
86a10cf76eSAxel Dörfler };
87a10cf76eSAxel Dörfler static const int32 kCombineModeCount = sizeof(kCombineModes) / sizeof(kCombineModes[0]);
88a10cf76eSAxel Dörfler 
8929e8a73aSAxel Dörfler enum {
9029e8a73aSAxel Dörfler 	SHOW_COMBINE_FIELD		= 0x01,
9129e8a73aSAxel Dörfler 	SHOW_SWAP_FIELD			= 0x02,
9229e8a73aSAxel Dörfler 	SHOW_LAPTOP_PANEL_FIELD	= 0x04,
9329e8a73aSAxel Dörfler 	SHOW_TV_STANDARD_FIELD	= 0x08,
9429e8a73aSAxel Dörfler };
9529e8a73aSAxel Dörfler 
96a10cf76eSAxel Dörfler 
97a10cf76eSAxel Dörfler static BString
98a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode)
99a10cf76eSAxel Dörfler {
100a10cf76eSAxel Dörfler 	switch (mode) {
101a10cf76eSAxel Dörfler 		case 0:		return "disabled";
102a10cf76eSAxel Dörfler 		case 1:		return "NTSC";
103a10cf76eSAxel Dörfler 		case 2:		return "NTSC Japan";
104a10cf76eSAxel Dörfler 		case 3:		return "PAL BDGHI";
105a10cf76eSAxel Dörfler 		case 4:		return "PAL M";
106a10cf76eSAxel Dörfler 		case 5:		return "PAL N";
107a10cf76eSAxel Dörfler 		case 6:		return "SECAM";
108a10cf76eSAxel Dörfler 		case 101:	return "NTSC 443";
109a10cf76eSAxel Dörfler 		case 102:	return "PAL 60";
110a10cf76eSAxel Dörfler 		case 103:	return "PAL NC";
111a10cf76eSAxel Dörfler 		default:
112a10cf76eSAxel Dörfler 		{
113a10cf76eSAxel Dörfler 			BString name;
114a10cf76eSAxel Dörfler 			name << "??? (" << mode << ")";
115a10cf76eSAxel Dörfler 
116a10cf76eSAxel Dörfler 			return name;
117a10cf76eSAxel Dörfler 		}
118a10cf76eSAxel Dörfler 	}
119a10cf76eSAxel Dörfler }
120a10cf76eSAxel Dörfler 
121a10cf76eSAxel Dörfler 
122a10cf76eSAxel Dörfler static void
123a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string)
124a10cf76eSAxel Dörfler {
125a10cf76eSAxel Dörfler 	string << mode.width << " x " << mode.height;
126a10cf76eSAxel Dörfler }
127a10cf76eSAxel Dörfler 
128a10cf76eSAxel Dörfler 
129a10cf76eSAxel Dörfler static void
130a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string,
131a10cf76eSAxel Dörfler 	bool appendUnit = true, bool alwaysWithFraction = false)
132a10cf76eSAxel Dörfler {
133a10cf76eSAxel Dörfler 	snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, refresh);
134a10cf76eSAxel Dörfler 	string.UnlockBuffer();
135a10cf76eSAxel Dörfler 
136a10cf76eSAxel Dörfler 	if (appendUnit)
137a10cf76eSAxel Dörfler 		string << " Hz";
138a10cf76eSAxel Dörfler }
139a10cf76eSAxel Dörfler 
140a10cf76eSAxel Dörfler 
14107184a9eSAxel Dörfler static const char*
14207184a9eSAxel Dörfler screen_errors(status_t status)
14307184a9eSAxel Dörfler {
14407184a9eSAxel Dörfler 	switch (status) {
14507184a9eSAxel Dörfler 		case B_ENTRY_NOT_FOUND:
14607184a9eSAxel Dörfler 			return "Unknown Mode";
14707184a9eSAxel Dörfler 		// TODO: add more?
14807184a9eSAxel Dörfler 
14907184a9eSAxel Dörfler 		default:
15007184a9eSAxel Dörfler 			return strerror(status);
15107184a9eSAxel Dörfler 	}
15207184a9eSAxel Dörfler }
15307184a9eSAxel Dörfler 
15429e8a73aSAxel Dörfler 
15529e8a73aSAxel Dörfler static float
15629e8a73aSAxel Dörfler max_label_width(BMenuField* control, float widestLabel)
15729e8a73aSAxel Dörfler {
15829e8a73aSAxel Dörfler 	float labelWidth = control->StringWidth(control->Label());
15929e8a73aSAxel Dörfler 	if (widestLabel < labelWidth)
16029e8a73aSAxel Dörfler 		return labelWidth;
16129e8a73aSAxel Dörfler 	return widestLabel;
16229e8a73aSAxel Dörfler }
16329e8a73aSAxel Dörfler 
16429e8a73aSAxel Dörfler 
16529e8a73aSAxel Dörfler static BRect
16629e8a73aSAxel Dörfler stack_and_align_menu_fields(const BList& menuFields)
16729e8a73aSAxel Dörfler {
16829e8a73aSAxel Dörfler 	float widestLabel = 0.0;
16929e8a73aSAxel Dörfler 	int32 count = menuFields.CountItems();
17029e8a73aSAxel Dörfler 	for (int32 i = 0; i < count; i++) {
17129e8a73aSAxel Dörfler 		BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i);
17229e8a73aSAxel Dörfler 		widestLabel = max_label_width(menuField, widestLabel);
17329e8a73aSAxel Dörfler 	}
17429e8a73aSAxel Dörfler 
17529e8a73aSAxel Dörfler 	// add some room (but only if there is text at all)
17629e8a73aSAxel Dörfler 	if (widestLabel > 0.0)
17729e8a73aSAxel Dörfler 		widestLabel += 5.0;
17829e8a73aSAxel Dörfler 
17929e8a73aSAxel Dörfler 	// make all controls the same width
180d1516993SAxel Dörfler 	float widestField = 0.0f;
18129e8a73aSAxel Dörfler 	for (int32 i = 0; i < count; i++) {
18229e8a73aSAxel Dörfler 		BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i);
183d1516993SAxel Dörfler 		if (widestField == 0.0f) {
184d1516993SAxel Dörfler 			widestField = menuField->StringWidth("9999 x 9999 WWW")
185d1516993SAxel Dörfler 				+ widestLabel;
186d1516993SAxel Dörfler 		}
18729e8a73aSAxel Dörfler 		menuField->SetAlignment(B_ALIGN_RIGHT);
18829e8a73aSAxel Dörfler 		menuField->SetDivider(widestLabel);
18929e8a73aSAxel Dörfler 		menuField->ResizeToPreferred();
19029e8a73aSAxel Dörfler 		widestField = max_c(menuField->Bounds().Width(), widestField);
19129e8a73aSAxel Dörfler 	}
19229e8a73aSAxel Dörfler 
19329e8a73aSAxel Dörfler 	// layout controls under each other, resize all to size
19429e8a73aSAxel Dörfler 	// of largest of them (they could still have different
19529e8a73aSAxel Dörfler 	// heights though)
19629e8a73aSAxel Dörfler 	BMenuField* topMenuField = (BMenuField*)menuFields.FirstItem();
19729e8a73aSAxel Dörfler 	BPoint leftTop = topMenuField->Frame().LeftTop();
19829e8a73aSAxel Dörfler 	BRect frame = topMenuField->Frame();
19929e8a73aSAxel Dörfler 
20029e8a73aSAxel Dörfler 	for (int32 i = 0; i < count; i++) {
20129e8a73aSAxel Dörfler 		BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i);
20229e8a73aSAxel Dörfler 		menuField->MoveTo(leftTop);
20329e8a73aSAxel Dörfler 		float height = menuField->Bounds().Height();
20429e8a73aSAxel Dörfler 		menuField->ResizeTo(widestField, height);
20529e8a73aSAxel Dörfler 		frame = frame | menuField->Frame();
20629e8a73aSAxel Dörfler 		leftTop.y += height + 5.0;
20729e8a73aSAxel Dörfler 	}
20829e8a73aSAxel Dörfler 
20929e8a73aSAxel Dörfler 	return frame;
21029e8a73aSAxel Dörfler }
211df3f5bacSStephan Aßmus 
212df3f5bacSStephan Aßmus 
2133dfd20c0SStephan Aßmus //	#pragma mark -
2143dfd20c0SStephan Aßmus 
2153dfd20c0SStephan Aßmus 
2165a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings *settings)
2175a78744bSAxel Dörfler 	: BWindow(settings->WindowFrame(), "Screen", B_TITLED_WINDOW,
218a10cf76eSAxel Dörfler 		B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES),
219199893c3SAxel Dörfler 	fBootWorkspaceApplied(false),
220a10cf76eSAxel Dörfler 	fScreenMode(this),
221abc649b8SWaldemar Kornewald 	fTempScreenMode(this),
222abc649b8SWaldemar Kornewald 	fModified(false)
223a10cf76eSAxel Dörfler {
224a10cf76eSAxel Dörfler 	BScreen screen(this);
225a10cf76eSAxel Dörfler 
22612580984SAxel Dörfler 	accelerant_device_info info;
227d1516993SAxel Dörfler 	if (screen.GetDeviceInfo(&info) == B_OK
228d1516993SAxel Dörfler 		&& !strcasecmp(info.chipset, "VESA"))
22912580984SAxel Dörfler 		fIsVesa = true;
23012580984SAxel Dörfler 
2315de171daSAxel Dörfler 	_UpdateOriginal();
232a10cf76eSAxel Dörfler 	fActive = fSelected = fOriginal;
233a10cf76eSAxel Dörfler 
234df3f5bacSStephan Aßmus 	BView *view = new BView(Bounds(), "ScreenView", B_FOLLOW_ALL, B_WILL_DRAW);
235a10cf76eSAxel Dörfler 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
236a10cf76eSAxel Dörfler 	AddChild(view);
237a10cf76eSAxel Dörfler 
2385a78744bSAxel Dörfler 	fSettings = settings;
2395a78744bSAxel Dörfler 
2405a78744bSAxel Dörfler 	// we need the "Current Workspace" first to get its height
2415a78744bSAxel Dörfler 
2425a78744bSAxel Dörfler 	BPopUpMenu *popUpMenu = new BPopUpMenu("Current Workspace", true, true);
243d1516993SAxel Dörfler 	fAllWorkspacesItem = new BMenuItem("All Workspaces",
244d1516993SAxel Dörfler 		new BMessage(WORKSPACE_CHECK_MSG));
2455a78744bSAxel Dörfler 	popUpMenu->AddItem(fAllWorkspacesItem);
246d1516993SAxel Dörfler 	BMenuItem *item = new BMenuItem("Current Workspace",
247d1516993SAxel Dörfler 		new BMessage(WORKSPACE_CHECK_MSG));
248b72c4836SAlexandre Deckner 
249b72c4836SAlexandre Deckner 	// TODO: since per workspace settings is unimplemented (Ticket #693)
250b72c4836SAlexandre Deckner 	// 		 we force the menu to "All Workspaces" for now
25112580984SAxel Dörfler 	fAllWorkspacesItem->SetMarked(true);
25212580984SAxel Dörfler 	item->SetEnabled(false);
253b72c4836SAlexandre Deckner 
2545a78744bSAxel Dörfler 	popUpMenu->AddItem(item);
2555a78744bSAxel Dörfler 
256df3f5bacSStephan Aßmus 	BMenuField* workspaceMenuField = new BMenuField(BRect(0, 0, 100, 15),
2575a78744bSAxel Dörfler 		"WorkspaceMenu", NULL, popUpMenu, true);
2585a78744bSAxel Dörfler 	workspaceMenuField->ResizeToPreferred();
259a10cf76eSAxel Dörfler 
260a10cf76eSAxel Dörfler 	// box on the left with workspace count and monitor view
261a10cf76eSAxel Dörfler 
2625a78744bSAxel Dörfler 	popUpMenu = new BPopUpMenu("", true, true);
263df3f5bacSStephan Aßmus 	fWorkspaceCountField = new BMenuField(BRect(0.0, 0.0, 50.0, 15.0),
264df3f5bacSStephan Aßmus 		"WorkspaceCountMenu", "Workspace count:", popUpMenu, true);
265d1516993SAxel Dörfler 	float labelWidth = fWorkspaceCountField->StringWidth(
266d1516993SAxel Dörfler 		fWorkspaceCountField->Label()) + 5.0;
267df3f5bacSStephan Aßmus 	fWorkspaceCountField->SetDivider(labelWidth);
268df3f5bacSStephan Aßmus 
269df3f5bacSStephan Aßmus 	fScreenBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0), "left box");
270df3f5bacSStephan Aßmus 	fScreenBox->AddChild(fWorkspaceCountField);
271a10cf76eSAxel Dörfler 
272a10cf76eSAxel Dörfler 	for (int32 count = 1; count <= 32; count++) {
273a10cf76eSAxel Dörfler 		BString workspaceCount;
274a10cf76eSAxel Dörfler 		workspaceCount << count;
275a10cf76eSAxel Dörfler 
276a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_WORKSPACE_CHANGED_MSG);
277a10cf76eSAxel Dörfler 		message->AddInt32("workspace count", count);
278a10cf76eSAxel Dörfler 
279a10cf76eSAxel Dörfler 		popUpMenu->AddItem(new BMenuItem(workspaceCount.String(),
280a10cf76eSAxel Dörfler 			message));
281a10cf76eSAxel Dörfler 	}
282a10cf76eSAxel Dörfler 
2835a78744bSAxel Dörfler 	item = popUpMenu->ItemAt(count_workspaces() - 1);
284a10cf76eSAxel Dörfler 	if (item != NULL)
285a10cf76eSAxel Dörfler 		item->SetMarked(true);
286a10cf76eSAxel Dörfler 
287df3f5bacSStephan Aßmus 	fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), "monitor",
288*6bda235aSStefano Ceccherini 		screen.Frame().IntegerWidth() + 1, screen.Frame().IntegerHeight() + 1);
289df3f5bacSStephan Aßmus 	fScreenBox->AddChild(fMonitorView);
2905a78744bSAxel Dörfler 
291df3f5bacSStephan Aßmus 	view->AddChild(fScreenBox);
292a10cf76eSAxel Dörfler 
293a10cf76eSAxel Dörfler 	// box on the right with screen resolution, etc.
294a10cf76eSAxel Dörfler 
295df3f5bacSStephan Aßmus 	fControlsBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0));
296df3f5bacSStephan Aßmus 	fControlsBox->SetLabel(workspaceMenuField);
297a10cf76eSAxel Dörfler 
298a10cf76eSAxel Dörfler 	fResolutionMenu = new BPopUpMenu("resolution", true, true);
299a10cf76eSAxel Dörfler 
300a10cf76eSAxel Dörfler 	uint16 previousWidth = 0, previousHeight = 0;
301a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
302a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
303a10cf76eSAxel Dörfler 
304a10cf76eSAxel Dörfler 		if (mode.width == previousWidth && mode.height == previousHeight)
305a10cf76eSAxel Dörfler 			continue;
306a10cf76eSAxel Dörfler 
307a10cf76eSAxel Dörfler 		previousWidth = mode.width;
308a10cf76eSAxel Dörfler 		previousHeight = mode.height;
309a10cf76eSAxel Dörfler 
310a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_RESOLUTION_MSG);
311a10cf76eSAxel Dörfler 		message->AddInt32("width", mode.width);
312a10cf76eSAxel Dörfler 		message->AddInt32("height", mode.height);
313a10cf76eSAxel Dörfler 
314a10cf76eSAxel Dörfler 		BString name;
315a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
316a10cf76eSAxel Dörfler 
317a10cf76eSAxel Dörfler 		fResolutionMenu->AddItem(new BMenuItem(name.String(), message));
318a10cf76eSAxel Dörfler 	}
319a10cf76eSAxel Dörfler 
32029e8a73aSAxel Dörfler 	BRect rect(0.0, 0.0, 200.0, 15.0);
321df3f5bacSStephan Aßmus 	// fResolutionField needs to be at the correct
322df3f5bacSStephan Aßmus 	// left-top offset, because all other menu fields
323df3f5bacSStephan Aßmus 	// will be layouted relative to it
324df3f5bacSStephan Aßmus 	fResolutionField = new BMenuField(rect.OffsetToCopy(10.0, 30.0),
325d1516993SAxel Dörfler 		"ResolutionMenu", "Resolution:", fResolutionMenu, false);
326df3f5bacSStephan Aßmus 	fControlsBox->AddChild(fResolutionField);
327a10cf76eSAxel Dörfler 
328a10cf76eSAxel Dörfler 	fColorsMenu = new BPopUpMenu("colors", true, true);
329a10cf76eSAxel Dörfler 
330a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
331a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_COLORS_MSG);
332a10cf76eSAxel Dörfler 		message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
333a10cf76eSAxel Dörfler 		message->AddInt32("space", kColorSpaces[i].space);
334a10cf76eSAxel Dörfler 
335a10cf76eSAxel Dörfler 		fColorsMenu->AddItem(new BMenuItem(kColorSpaces[i].label, message));
336a10cf76eSAxel Dörfler 	}
337a10cf76eSAxel Dörfler 
338df3f5bacSStephan Aßmus 	rect.OffsetTo(B_ORIGIN);
339df3f5bacSStephan Aßmus 
340d1516993SAxel Dörfler 	fColorsField = new BMenuField(rect, "ColorsMenu", "Colors:", fColorsMenu,
341d1516993SAxel Dörfler 		false);
342df3f5bacSStephan Aßmus 	fControlsBox->AddChild(fColorsField);
343a10cf76eSAxel Dörfler 
344a10cf76eSAxel Dörfler 	fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
345a10cf76eSAxel Dörfler 
34629e8a73aSAxel Dörfler 	BMessage *message;
34729e8a73aSAxel Dörfler 
34829e8a73aSAxel Dörfler 	float min, max;
34929e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fActive, min, max) && min == max) {
35029e8a73aSAxel Dörfler 		// This is a special case for drivers that only support a single
35129e8a73aSAxel Dörfler 		// frequency, like the VESA driver
35229e8a73aSAxel Dörfler 		BString name;
35329e8a73aSAxel Dörfler 		name << min << " Hz";
35429e8a73aSAxel Dörfler 
35529e8a73aSAxel Dörfler 		message = new BMessage(POP_REFRESH_MSG);
35629e8a73aSAxel Dörfler 		message->AddFloat("refresh", min);
35729e8a73aSAxel Dörfler 
35829e8a73aSAxel Dörfler 		fRefreshMenu->AddItem(item = new BMenuItem(name.String(), message));
35929e8a73aSAxel Dörfler 		item->SetEnabled(false);
36029e8a73aSAxel Dörfler 	} else {
361a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kRefreshRateCount; ++i) {
362a10cf76eSAxel Dörfler 			BString name;
363a10cf76eSAxel Dörfler 			name << kRefreshRates[i] << " Hz";
364a10cf76eSAxel Dörfler 
36529e8a73aSAxel Dörfler 			message = new BMessage(POP_REFRESH_MSG);
366a10cf76eSAxel Dörfler 			message->AddFloat("refresh", kRefreshRates[i]);
367a10cf76eSAxel Dörfler 
368a10cf76eSAxel Dörfler 			fRefreshMenu->AddItem(new BMenuItem(name.String(), message));
369a10cf76eSAxel Dörfler 		}
370a10cf76eSAxel Dörfler 
37129e8a73aSAxel Dörfler 		message = new BMessage(POP_OTHER_REFRESH_MSG);
372a10cf76eSAxel Dörfler 
373a10cf76eSAxel Dörfler 		fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message);
374a10cf76eSAxel Dörfler 		fRefreshMenu->AddItem(fOtherRefresh);
37529e8a73aSAxel Dörfler 	}
376a10cf76eSAxel Dörfler 
377d1516993SAxel Dörfler 	fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:",
378d1516993SAxel Dörfler 		fRefreshMenu, false);
37912580984SAxel Dörfler 	if (_IsVesa())
38012580984SAxel Dörfler 		fRefreshField->Hide();
381df3f5bacSStephan Aßmus 	fControlsBox->AddChild(fRefreshField);
382a10cf76eSAxel Dörfler 
383df3f5bacSStephan Aßmus 	view->AddChild(fControlsBox);
384df3f5bacSStephan Aßmus 
385df3f5bacSStephan Aßmus 	uint32 controlsFlags = 0;
386a10cf76eSAxel Dörfler 
387a10cf76eSAxel Dörfler 	// enlarged area for multi-monitor settings
388a10cf76eSAxel Dörfler 	{
389a10cf76eSAxel Dörfler 		bool dummy;
390a10cf76eSAxel Dörfler 		uint32 dummy32;
391a10cf76eSAxel Dörfler 		bool multiMonSupport;
392a10cf76eSAxel Dörfler 		bool useLaptopPanelSupport;
393a10cf76eSAxel Dörfler 		bool tvStandardSupport;
394a10cf76eSAxel Dörfler 
395a10cf76eSAxel Dörfler 		multiMonSupport = TestMultiMonSupport(&screen) == B_OK;
396a10cf76eSAxel Dörfler 		useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK;
397a10cf76eSAxel Dörfler 		tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK;
398df3f5bacSStephan Aßmus 		if (multiMonSupport) {
399df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_COMBINE_FIELD;
400df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_SWAP_FIELD;
401df3f5bacSStephan Aßmus 		}
402df3f5bacSStephan Aßmus 		if (useLaptopPanelSupport)
403df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_LAPTOP_PANEL_FIELD;
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 
408a10cf76eSAxel Dörfler 		fCombineMenu = new BPopUpMenu("CombineDisplays", true, true);
409a10cf76eSAxel Dörfler 
410a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kCombineModeCount; i++) {
411a10cf76eSAxel Dörfler 			message = new BMessage(POP_COMBINE_DISPLAYS_MSG);
412a10cf76eSAxel Dörfler 			message->AddInt32("mode", kCombineModes[i].mode);
413a10cf76eSAxel Dörfler 
414d1516993SAxel Dörfler 			fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name,
415d1516993SAxel Dörfler 				message));
416a10cf76eSAxel Dörfler 		}
417a10cf76eSAxel Dörfler 
418df3f5bacSStephan Aßmus 		fCombineField = new BMenuField(rect, "CombineMenu",
419d1516993SAxel Dörfler 			"Combine Displays:", fCombineMenu, false);
420df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fCombineField);
421a10cf76eSAxel Dörfler 
422a10cf76eSAxel Dörfler 		if (!multiMonSupport)
423df3f5bacSStephan Aßmus 			fCombineField->Hide();
424a10cf76eSAxel Dörfler 
425a10cf76eSAxel Dörfler 		fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true);
426a10cf76eSAxel Dörfler 
427a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
428a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
429a10cf76eSAxel Dörfler 		message->AddBool("swap", false);
430a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("no", message));
431a10cf76eSAxel Dörfler 
432a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
433a10cf76eSAxel Dörfler 		message->AddBool("swap", true);
434a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message));
435a10cf76eSAxel Dörfler 
436df3f5bacSStephan Aßmus 		fSwapDisplaysField = new BMenuField(rect, "SwapMenu", "Swap Displays:",
437d1516993SAxel Dörfler 			fSwapDisplaysMenu, false);
438a10cf76eSAxel Dörfler 
439df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fSwapDisplaysField);
440a10cf76eSAxel Dörfler 		if (!multiMonSupport)
441df3f5bacSStephan Aßmus 			fSwapDisplaysField->Hide();
442a10cf76eSAxel Dörfler 
443a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true);
444a10cf76eSAxel Dörfler 
445a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
446a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
447a10cf76eSAxel Dörfler 		message->AddBool("use", false);
448a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message));
449a10cf76eSAxel Dörfler 
450a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
451a10cf76eSAxel Dörfler 		message->AddBool("use", true);
452a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message));
453a10cf76eSAxel Dörfler 
454d1516993SAxel Dörfler 		fUseLaptopPanelField = new BMenuField(rect, "UseLaptopPanel",
455d1516993SAxel Dörfler 			"Use Laptop Panel:", fUseLaptopPanelMenu, false);
456a10cf76eSAxel Dörfler 
457df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fUseLaptopPanelField);
458a10cf76eSAxel Dörfler 		if (!useLaptopPanelSupport)
459df3f5bacSStephan Aßmus 			fUseLaptopPanelField->Hide();
460a10cf76eSAxel Dörfler 
461a10cf76eSAxel Dörfler 		fTVStandardMenu = new BPopUpMenu("TVStandard", true, true);
462a10cf76eSAxel Dörfler 
463a10cf76eSAxel Dörfler 		// arbitrary limit
464a10cf76eSAxel Dörfler 		uint32 i;
465a10cf76eSAxel Dörfler 		for (i = 0; i < 100; ++i) {
466a10cf76eSAxel Dörfler 			uint32 mode;
467a10cf76eSAxel Dörfler 			if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK)
468a10cf76eSAxel Dörfler 				break;
469a10cf76eSAxel Dörfler 
470a10cf76eSAxel Dörfler 			BString name = tv_standard_to_string(mode);
471a10cf76eSAxel Dörfler 
472a10cf76eSAxel Dörfler 			message = new BMessage(POP_TV_STANDARD_MSG);
473a10cf76eSAxel Dörfler 			message->AddInt32("tv_standard", mode);
474a10cf76eSAxel Dörfler 
475a10cf76eSAxel Dörfler 			fTVStandardMenu->AddItem(new BMenuItem(name.String(), message));
476a10cf76eSAxel Dörfler 		}
477a10cf76eSAxel Dörfler 
478df3f5bacSStephan Aßmus 		fTVStandardField = new BMenuField(rect, "tv standard", "Video Format:",
479d1516993SAxel Dörfler 			fTVStandardMenu, false);
480df3f5bacSStephan Aßmus 		fTVStandardField->SetAlignment(B_ALIGN_RIGHT);
481a10cf76eSAxel Dörfler 
482df3f5bacSStephan Aßmus 		if (!tvStandardSupport || i == 0) {
483df3f5bacSStephan Aßmus 			fTVStandardField->Hide();
484df3f5bacSStephan Aßmus 		} else {
485df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_TV_STANDARD_FIELD;
486a10cf76eSAxel Dörfler 		}
487a10cf76eSAxel Dörfler 
488df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fTVStandardField);
489df3f5bacSStephan Aßmus 	}
490df3f5bacSStephan Aßmus 
491df3f5bacSStephan Aßmus 	BRect buttonRect(0.0, 0.0, 30.0, 10.0);
492df3f5bacSStephan Aßmus 	fBackgroundsButton = new BButton(buttonRect, "BackgroundsButton",
493d1516993SAxel Dörfler 		"Set Background"B_UTF8_ELLIPSIS,
494d1516993SAxel Dörfler 		new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG));
4953dfd20c0SStephan Aßmus 	fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9);
496df3f5bacSStephan Aßmus 	fScreenBox->AddChild(fBackgroundsButton);
497df3f5bacSStephan Aßmus 
498abc649b8SWaldemar Kornewald 	// TODO: we don't support getting the screen's preferred settings
499abc649b8SWaldemar Kornewald 	/* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults",
500a10cf76eSAxel Dörfler 		new BMessage(BUTTON_DEFAULTS_MSG));
501abc649b8SWaldemar Kornewald 	view->AddChild(fDefaultsButton); */
502a10cf76eSAxel Dörfler 
503df3f5bacSStephan Aßmus 	fRevertButton = new BButton(buttonRect, "RevertButton", "Revert",
504a10cf76eSAxel Dörfler 		new BMessage(BUTTON_REVERT_MSG));
505a10cf76eSAxel Dörfler 	fRevertButton->SetEnabled(false);
506a10cf76eSAxel Dörfler 	view->AddChild(fRevertButton);
507a10cf76eSAxel Dörfler 
508df3f5bacSStephan Aßmus 	fApplyButton = new BButton(buttonRect, "ApplyButton", "Apply",
509df3f5bacSStephan Aßmus 		new BMessage(BUTTON_APPLY_MSG));
510df3f5bacSStephan Aßmus 	fApplyButton->SetEnabled(false);
511abc649b8SWaldemar Kornewald 	fControlsBox->AddChild(fApplyButton);
5125a78744bSAxel Dörfler 
5135de171daSAxel Dörfler 	_UpdateControls();
514df3f5bacSStephan Aßmus 
5155de171daSAxel Dörfler 	_LayoutControls(controlsFlags);
516a10cf76eSAxel Dörfler }
517a10cf76eSAxel Dörfler 
518a10cf76eSAxel Dörfler 
519a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow()
520a10cf76eSAxel Dörfler {
521a10cf76eSAxel Dörfler 	delete fSettings;
522a10cf76eSAxel Dörfler }
523a10cf76eSAxel Dörfler 
524a10cf76eSAxel Dörfler 
525a10cf76eSAxel Dörfler bool
526a10cf76eSAxel Dörfler ScreenWindow::QuitRequested()
527a10cf76eSAxel Dörfler {
528a10cf76eSAxel Dörfler 	fSettings->SetWindowFrame(Frame());
529199893c3SAxel Dörfler 
530199893c3SAxel Dörfler 	// Write mode of workspace 0 (the boot workspace) to the vesa settings file
531199893c3SAxel Dörfler 	screen_mode vesaMode;
532199893c3SAxel Dörfler 	if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) {
533199893c3SAxel Dörfler 		status_t status = _WriteVesaModeFile(vesaMode);
53412580984SAxel Dörfler 		if (status < B_OK) {
53512580984SAxel Dörfler 			BString warning = "Could not write VESA mode settings file:\n\t";
53612580984SAxel Dörfler 			warning << strerror(status);
53712580984SAxel Dörfler 			(new BAlert("VesaAlert", warning.String(), "Okay", NULL, NULL,
53812580984SAxel Dörfler 				B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
53912580984SAxel Dörfler 		}
54012580984SAxel Dörfler 	}
54112580984SAxel Dörfler 
542a10cf76eSAxel Dörfler 	be_app->PostMessage(B_QUIT_REQUESTED);
543a10cf76eSAxel Dörfler 
544a10cf76eSAxel Dörfler 	return BWindow::QuitRequested();
545a10cf76eSAxel Dörfler }
546a10cf76eSAxel Dörfler 
547a10cf76eSAxel Dörfler 
5485de171daSAxel Dörfler /*!	Update resolution list according to combine mode
5495de171daSAxel Dörfler 	(some resolution may not be combinable due to memory restrictions)
550a10cf76eSAxel Dörfler */
551a10cf76eSAxel Dörfler void
5525de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu()
553a10cf76eSAxel Dörfler {
554a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fResolutionMenu->CountItems(); i++)
555a10cf76eSAxel Dörfler 		fResolutionMenu->ItemAt(i)->SetEnabled(false);
556a10cf76eSAxel Dörfler 
557a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
558a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
559a10cf76eSAxel Dörfler 		if (mode.combine != fSelected.combine)
560a10cf76eSAxel Dörfler 			continue;
561a10cf76eSAxel Dörfler 
562a10cf76eSAxel Dörfler 		BString name;
563a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
564a10cf76eSAxel Dörfler 
565a10cf76eSAxel Dörfler 		BMenuItem *item = fResolutionMenu->FindItem(name.String());
566a10cf76eSAxel Dörfler 		if (item != NULL)
567a10cf76eSAxel Dörfler 			item->SetEnabled(true);
568a10cf76eSAxel Dörfler 	}
569a10cf76eSAxel Dörfler }
570a10cf76eSAxel Dörfler 
571a10cf76eSAxel Dörfler 
5725de171daSAxel Dörfler /*!	Update color and refresh options according to current mode
5735de171daSAxel Dörfler 	(a color space is made active if there is any mode with
5745de171daSAxel Dörfler 	given resolution and this colour space; same applies for
5755de171daSAxel Dörfler 	refresh rate, though "Other…" is always possible)
576a10cf76eSAxel Dörfler */
577a10cf76eSAxel Dörfler void
5785de171daSAxel Dörfler ScreenWindow::_CheckColorMenu()
579a10cf76eSAxel Dörfler {
580a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
581a10cf76eSAxel Dörfler 		bool supported = false;
582a10cf76eSAxel Dörfler 
583a10cf76eSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
584a10cf76eSAxel Dörfler 			screen_mode mode = fScreenMode.ModeAt(j);
585a10cf76eSAxel Dörfler 
586a10cf76eSAxel Dörfler 			if (fSelected.width == mode.width
587a10cf76eSAxel Dörfler 				&& fSelected.height == mode.height
5885de171daSAxel Dörfler 				&& (kColorSpaces[i].space == mode.space
5895de171daSAxel Dörfler 					// advertize 24 bit mode as 32 bit to avoid confusion
5905de171daSAxel Dörfler 					|| (kColorSpaces[i].space == B_RGB32
5915de171daSAxel Dörfler 						&& mode.space == B_RGB24))
592a10cf76eSAxel Dörfler 				&& fSelected.combine == mode.combine) {
593a10cf76eSAxel Dörfler 				supported = true;
594a10cf76eSAxel Dörfler 				break;
595a10cf76eSAxel Dörfler 			}
596a10cf76eSAxel Dörfler 		}
597a10cf76eSAxel Dörfler 
598a10cf76eSAxel Dörfler 		BMenuItem* item = fColorsMenu->ItemAt(i);
599a10cf76eSAxel Dörfler 		if (item)
600a10cf76eSAxel Dörfler 			item->SetEnabled(supported);
601a10cf76eSAxel Dörfler 	}
602a10cf76eSAxel Dörfler }
603a10cf76eSAxel Dörfler 
604a10cf76eSAxel Dörfler 
6055de171daSAxel Dörfler /*!	Enable/disable refresh options according to current mode. */
606a10cf76eSAxel Dörfler void
6075de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu()
608a10cf76eSAxel Dörfler {
60929e8a73aSAxel Dörfler 	float min, max;
61029e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max)
61129e8a73aSAxel Dörfler 		return;
612a10cf76eSAxel Dörfler 
61329e8a73aSAxel Dörfler 	for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) {
61429e8a73aSAxel Dörfler 		BMenuItem* item = fRefreshMenu->ItemAt(i);
61529e8a73aSAxel Dörfler 		BMessage* message = item->Message();
61629e8a73aSAxel Dörfler 		float refresh;
61729e8a73aSAxel Dörfler 		if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK)
61829e8a73aSAxel Dörfler 			item->SetEnabled(refresh >= min && refresh <= max);
619a10cf76eSAxel Dörfler 	}
620a10cf76eSAxel Dörfler }
621a10cf76eSAxel Dörfler 
622a10cf76eSAxel Dörfler 
6235de171daSAxel Dörfler /*!	Activate appropriate menu item according to selected refresh rate */
624a10cf76eSAxel Dörfler void
6255de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl()
626a10cf76eSAxel Dörfler {
627a10cf76eSAxel Dörfler 	BString string;
628a10cf76eSAxel Dörfler 	refresh_rate_to_string(fSelected.refresh, string);
629a10cf76eSAxel Dörfler 
630a10cf76eSAxel Dörfler 	BMenuItem* item = fRefreshMenu->FindItem(string.String());
631a10cf76eSAxel Dörfler 	if (item) {
632a10cf76eSAxel Dörfler 		if (!item->IsMarked())
633a10cf76eSAxel Dörfler 			item->SetMarked(true);
63429e8a73aSAxel Dörfler 
635a10cf76eSAxel Dörfler 		// "Other…" items only contains a refresh rate when active
636e6b421a9SJérôme Duval 		fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS);
637a10cf76eSAxel Dörfler 		return;
638a10cf76eSAxel Dörfler 	}
639a10cf76eSAxel Dörfler 
640a10cf76eSAxel Dörfler 	// this is a non-standard refresh rate
641a10cf76eSAxel Dörfler 
642a10cf76eSAxel Dörfler 	fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh);
643a10cf76eSAxel Dörfler 	fOtherRefresh->SetMarked(true);
644a10cf76eSAxel Dörfler 
645a10cf76eSAxel Dörfler 	fRefreshMenu->Superitem()->SetLabel(string.String());
646a10cf76eSAxel Dörfler 
647a10cf76eSAxel Dörfler 	string.Append("/Other" B_UTF8_ELLIPSIS);
648a10cf76eSAxel Dörfler 	fOtherRefresh->SetLabel(string.String());
649a10cf76eSAxel Dörfler }
650a10cf76eSAxel Dörfler 
651a10cf76eSAxel Dörfler 
652a10cf76eSAxel Dörfler void
6535de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView()
654a10cf76eSAxel Dörfler {
655a10cf76eSAxel Dörfler 	BMessage updateMessage(UPDATE_DESKTOP_MSG);
656a10cf76eSAxel Dörfler 	updateMessage.AddInt32("width", fSelected.width);
657a10cf76eSAxel Dörfler 	updateMessage.AddInt32("height", fSelected.height);
658a10cf76eSAxel Dörfler 
659a10cf76eSAxel Dörfler 	PostMessage(&updateMessage, fMonitorView);
660a10cf76eSAxel Dörfler }
661a10cf76eSAxel Dörfler 
662a10cf76eSAxel Dörfler 
663a10cf76eSAxel Dörfler void
6645de171daSAxel Dörfler ScreenWindow::_UpdateControls()
665a10cf76eSAxel Dörfler {
666a10cf76eSAxel Dörfler 	BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays);
667a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
668a10cf76eSAxel Dörfler 		item->SetMarked(true);
669a10cf76eSAxel Dörfler 
670a10cf76eSAxel Dörfler 	item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel);
671a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
672a10cf76eSAxel Dörfler 		item->SetMarked(true);
673a10cf76eSAxel Dörfler 
674a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) {
675a10cf76eSAxel Dörfler 		item = fTVStandardMenu->ItemAt(i);
676a10cf76eSAxel Dörfler 
677a10cf76eSAxel Dörfler 		uint32 tvStandard;
678a10cf76eSAxel Dörfler 		item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard);
679a10cf76eSAxel Dörfler 		if (tvStandard == fSelected.tv_standard) {
680a10cf76eSAxel Dörfler 			if (!item->IsMarked())
681a10cf76eSAxel Dörfler 				item->SetMarked(true);
682a10cf76eSAxel Dörfler 			break;
683a10cf76eSAxel Dörfler 		}
684a10cf76eSAxel Dörfler 	}
685a10cf76eSAxel Dörfler 
6865de171daSAxel Dörfler 	_CheckResolutionMenu();
6875de171daSAxel Dörfler 	_CheckColorMenu();
6885de171daSAxel Dörfler 	_CheckRefreshMenu();
689a10cf76eSAxel Dörfler 
690a10cf76eSAxel Dörfler 	BString string;
691a10cf76eSAxel Dörfler 	resolution_to_string(fSelected, string);
692a10cf76eSAxel Dörfler 	item = fResolutionMenu->FindItem(string.String());
693a10cf76eSAxel Dörfler 
694a10cf76eSAxel Dörfler 	if (item != NULL) {
695a10cf76eSAxel Dörfler 		if (!item->IsMarked())
696a10cf76eSAxel Dörfler 			item->SetMarked(true);
697a10cf76eSAxel Dörfler 	} else {
698a10cf76eSAxel Dörfler 		// this is bad luck - if mode has been set via screen references,
699a10cf76eSAxel Dörfler 		// this case cannot occur; there are three possible solutions:
700a10cf76eSAxel Dörfler 		// 1. add a new resolution to list
701a10cf76eSAxel Dörfler 		//    - we had to remove it as soon as a "valid" one is selected
702a10cf76eSAxel Dörfler 		//    - we don't know which frequencies/bit depths are supported
703a10cf76eSAxel Dörfler 		//    - as long as we haven't the GMT formula to create
704a10cf76eSAxel Dörfler 		//      parameters for any resolution given, we cannot
705a10cf76eSAxel Dörfler 		//      really set current mode - it's just not in the list
706a10cf76eSAxel Dörfler 		// 2. choose nearest resolution
707a10cf76eSAxel Dörfler 		//    - probably a good idea, but implies coding and testing
708a10cf76eSAxel Dörfler 		// 3. choose lowest resolution
709a10cf76eSAxel Dörfler 		//    - do you really think we are so lazy? yes, we are
710a10cf76eSAxel Dörfler 		item = fResolutionMenu->ItemAt(0);
711a10cf76eSAxel Dörfler 		if (item)
712a10cf76eSAxel Dörfler 			item->SetMarked(true);
713a10cf76eSAxel Dörfler 
714a10cf76eSAxel Dörfler 		// okay - at least we set menu label to active resolution
715a10cf76eSAxel Dörfler 		fResolutionMenu->Superitem()->SetLabel(string.String());
716a10cf76eSAxel Dörfler 	}
717a10cf76eSAxel Dörfler 
718a10cf76eSAxel Dörfler 	// mark active combine mode
719a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kCombineModeCount; i++) {
720a10cf76eSAxel Dörfler 		if (kCombineModes[i].mode == fSelected.combine) {
721a10cf76eSAxel Dörfler 			item = fCombineMenu->ItemAt(i);
722a10cf76eSAxel Dörfler 			if (item && !item->IsMarked())
723a10cf76eSAxel Dörfler 				item->SetMarked(true);
724a10cf76eSAxel Dörfler 			break;
725a10cf76eSAxel Dörfler 		}
726a10cf76eSAxel Dörfler 	}
727a10cf76eSAxel Dörfler 
728a10cf76eSAxel Dörfler 	item = fColorsMenu->ItemAt(0);
729a10cf76eSAxel Dörfler 
730a10cf76eSAxel Dörfler 	for (int32 i = kColorSpaceCount; i-- > 0;) {
7315de171daSAxel Dörfler 		if (kColorSpaces[i].space == fSelected.space
7325de171daSAxel Dörfler 			|| (kColorSpaces[i].space == B_RGB32
7335de171daSAxel Dörfler 				&& fSelected.space == B_RGB24)) {
734a10cf76eSAxel Dörfler 			item = fColorsMenu->ItemAt(i);
735a10cf76eSAxel Dörfler 			break;
736a10cf76eSAxel Dörfler 		}
737a10cf76eSAxel Dörfler 	}
738a10cf76eSAxel Dörfler 
739a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
740a10cf76eSAxel Dörfler 		item->SetMarked(true);
741a10cf76eSAxel Dörfler 
742a10cf76eSAxel Dörfler 	string.Truncate(0);
7435de171daSAxel Dörfler 	uint32 bitsPerPixel = fSelected.BitsPerPixel();
7445de171daSAxel Dörfler 	// advertize 24 bit mode as 32 bit to avoid confusion
7455de171daSAxel Dörfler 	if (bitsPerPixel == 24)
7465de171daSAxel Dörfler 		bitsPerPixel = 32;
7475de171daSAxel Dörfler 
7485de171daSAxel Dörfler 	string << bitsPerPixel << " Bits/Pixel";
749a10cf76eSAxel Dörfler 	if (string != fColorsMenu->Superitem()->Label())
750a10cf76eSAxel Dörfler 		fColorsMenu->Superitem()->SetLabel(string.String());
751a10cf76eSAxel Dörfler 
7525de171daSAxel Dörfler 	_UpdateMonitorView();
7535de171daSAxel Dörfler 	_UpdateRefreshControl();
754a10cf76eSAxel Dörfler 
7555de171daSAxel Dörfler 	_CheckApplyEnabled();
756a10cf76eSAxel Dörfler }
757a10cf76eSAxel Dörfler 
758a10cf76eSAxel Dörfler 
75912580984SAxel Dörfler /*! Reflect active mode in chosen settings */
760a10cf76eSAxel Dörfler void
7615de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode()
762a10cf76eSAxel Dörfler {
76312580984SAxel Dörfler 	// Usually, this function gets called after a mode
764a10cf76eSAxel Dörfler 	// has been set manually; still, as the graphics driver
765a10cf76eSAxel Dörfler 	// is free to fiddle with mode passed, we better ask
766a10cf76eSAxel Dörfler 	// what kind of mode we actually got
767a10cf76eSAxel Dörfler 	fScreenMode.Get(fActive);
768a10cf76eSAxel Dörfler 	fSelected = fActive;
769a10cf76eSAxel Dörfler 
7705de171daSAxel Dörfler 	_UpdateControls();
771a10cf76eSAxel Dörfler }
772a10cf76eSAxel Dörfler 
773a10cf76eSAxel Dörfler 
774a10cf76eSAxel Dörfler void
775a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode)
776a10cf76eSAxel Dörfler {
777a10cf76eSAxel Dörfler 	// move window on screen, if necessary
778a10cf76eSAxel Dörfler 	if (frame.right <= Frame().right
779a10cf76eSAxel Dörfler 		&& frame.bottom <= Frame().bottom) {
780a10cf76eSAxel Dörfler 		MoveTo((frame.Width() - Frame().Width()) / 2,
781a10cf76eSAxel Dörfler 			(frame.Height() - Frame().Height()) / 2);
782a10cf76eSAxel Dörfler 	}
783a10cf76eSAxel Dörfler }
784a10cf76eSAxel Dörfler 
785a10cf76eSAxel Dörfler 
786a10cf76eSAxel Dörfler void
787a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state)
788a10cf76eSAxel Dörfler {
789abc649b8SWaldemar Kornewald 	fScreenMode.GetOriginalMode(fOriginal, workspace);
7905de171daSAxel Dörfler 	_UpdateActiveMode();
791a10cf76eSAxel Dörfler 
7926edaa0f6SStefano Ceccherini 	BMessage message(UPDATE_DESKTOP_COLOR_MSG);
7936edaa0f6SStefano Ceccherini 	PostMessage(&message, fMonitorView);
794a10cf76eSAxel Dörfler }
795a10cf76eSAxel Dörfler 
796a10cf76eSAxel Dörfler 
797a10cf76eSAxel Dörfler void
798a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message)
799a10cf76eSAxel Dörfler {
800a10cf76eSAxel Dörfler 	switch (message->what) {
801a10cf76eSAxel Dörfler 		case WORKSPACE_CHECK_MSG:
8025de171daSAxel Dörfler 			_CheckApplyEnabled();
803a10cf76eSAxel Dörfler 			break;
804a10cf76eSAxel Dörfler 
805a10cf76eSAxel Dörfler 		case POP_WORKSPACE_CHANGED_MSG:
806a10cf76eSAxel Dörfler 		{
807abc649b8SWaldemar Kornewald 			// update checkpoint state
808a10cf76eSAxel Dörfler 			int32 index;
809abc649b8SWaldemar Kornewald 			if (message->FindInt32("index", &index) == B_OK) {
810a10cf76eSAxel Dörfler 				set_workspace_count(index + 1);
8115de171daSAxel Dörfler 				_CheckApplyEnabled();
812abc649b8SWaldemar Kornewald 			}
813a10cf76eSAxel Dörfler 			break;
814a10cf76eSAxel Dörfler 		}
815a10cf76eSAxel Dörfler 
816a10cf76eSAxel Dörfler 		case POP_RESOLUTION_MSG:
817a10cf76eSAxel Dörfler 		{
818a10cf76eSAxel Dörfler 			message->FindInt32("width", &fSelected.width);
819a10cf76eSAxel Dörfler 			message->FindInt32("height", &fSelected.height);
820a10cf76eSAxel Dörfler 
8215de171daSAxel Dörfler 			_CheckColorMenu();
8225de171daSAxel Dörfler 			_CheckRefreshMenu();
823a10cf76eSAxel Dörfler 
8245de171daSAxel Dörfler 			_UpdateMonitorView();
8255de171daSAxel Dörfler 			_UpdateRefreshControl();
826a10cf76eSAxel Dörfler 
8275de171daSAxel Dörfler 			_CheckApplyEnabled();
828a10cf76eSAxel Dörfler 			break;
829a10cf76eSAxel Dörfler 		}
830a10cf76eSAxel Dörfler 
831a10cf76eSAxel Dörfler 		case POP_COLORS_MSG:
832a10cf76eSAxel Dörfler 		{
833a10cf76eSAxel Dörfler 			message->FindInt32("space", (int32 *)&fSelected.space);
834a10cf76eSAxel Dörfler 
835a10cf76eSAxel Dörfler 			BString string;
836a10cf76eSAxel Dörfler 			string << fSelected.BitsPerPixel() << " Bits/Pixel";
837a10cf76eSAxel Dörfler 			fColorsMenu->Superitem()->SetLabel(string.String());
838a10cf76eSAxel Dörfler 
8395de171daSAxel Dörfler 			_CheckApplyEnabled();
840a10cf76eSAxel Dörfler 			break;
841a10cf76eSAxel Dörfler 		}
842a10cf76eSAxel Dörfler 
843a10cf76eSAxel Dörfler 		case POP_REFRESH_MSG:
844a40498e2SWaldemar Kornewald 		{
845a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
846a10cf76eSAxel Dörfler 			fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS);
847a10cf76eSAxel Dörfler 				// revert "Other…" label - it might have had a refresh rate prefix
848a10cf76eSAxel Dörfler 
8495de171daSAxel Dörfler 			_CheckApplyEnabled();
850a10cf76eSAxel Dörfler 			break;
851a40498e2SWaldemar Kornewald 		}
852a10cf76eSAxel Dörfler 
853a10cf76eSAxel Dörfler 		case POP_OTHER_REFRESH_MSG:
854a10cf76eSAxel Dörfler 		{
85529e8a73aSAxel Dörfler 			// make sure menu shows something useful
8565de171daSAxel Dörfler 			_UpdateRefreshControl();
857a10cf76eSAxel Dörfler 
85829e8a73aSAxel Dörfler 			float min = 0, max = 999;
85929e8a73aSAxel Dörfler 			fScreenMode.GetRefreshLimits(fSelected, min, max);
86029e8a73aSAxel Dörfler 			if (min < gMinRefresh)
86129e8a73aSAxel Dörfler 				min = gMinRefresh;
86229e8a73aSAxel Dörfler 			if (max > gMaxRefresh)
86329e8a73aSAxel Dörfler 				max = gMaxRefresh;
86429e8a73aSAxel Dörfler 
865c5d10f7aSAxel Dörfler 			RefreshWindow *fRefreshWindow = new RefreshWindow(
866c5d10f7aSAxel Dörfler 				fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, min, max);
867a10cf76eSAxel Dörfler 			fRefreshWindow->Show();
868a10cf76eSAxel Dörfler 			break;
869a10cf76eSAxel Dörfler 		}
870a10cf76eSAxel Dörfler 
871a10cf76eSAxel Dörfler 		case SET_CUSTOM_REFRESH_MSG:
872a10cf76eSAxel Dörfler 		{
873a10cf76eSAxel Dörfler 			// user pressed "done" in "Other…" refresh dialog;
874a10cf76eSAxel Dörfler 			// select the refresh rate chosen
875a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
876a10cf76eSAxel Dörfler 
8775de171daSAxel Dörfler 			_UpdateRefreshControl();
8785de171daSAxel Dörfler 			_CheckApplyEnabled();
879a10cf76eSAxel Dörfler 			break;
880a10cf76eSAxel Dörfler 		}
881a10cf76eSAxel Dörfler 
882a10cf76eSAxel Dörfler 		case POP_COMBINE_DISPLAYS_MSG:
883a10cf76eSAxel Dörfler 		{
884a10cf76eSAxel Dörfler 			// new combine mode has bee chosen
885a10cf76eSAxel Dörfler 			int32 mode;
886a10cf76eSAxel Dörfler 			if (message->FindInt32("mode", &mode) == B_OK)
887a10cf76eSAxel Dörfler 				fSelected.combine = (combine_mode)mode;
888a10cf76eSAxel Dörfler 
8895de171daSAxel Dörfler 			_CheckResolutionMenu();
8905de171daSAxel Dörfler 			_CheckApplyEnabled();
891a10cf76eSAxel Dörfler 			break;
892a10cf76eSAxel Dörfler 		}
893a10cf76eSAxel Dörfler 
894a10cf76eSAxel Dörfler 		case POP_SWAP_DISPLAYS_MSG:
895a10cf76eSAxel Dörfler 			message->FindBool("swap", &fSelected.swap_displays);
8965de171daSAxel Dörfler 			_CheckApplyEnabled();
897a10cf76eSAxel Dörfler 			break;
898a10cf76eSAxel Dörfler 
899a10cf76eSAxel Dörfler 		case POP_USE_LAPTOP_PANEL_MSG:
900a10cf76eSAxel Dörfler 			message->FindBool("use", &fSelected.use_laptop_panel);
9015de171daSAxel Dörfler 			_CheckApplyEnabled();
902a10cf76eSAxel Dörfler 			break;
903a10cf76eSAxel Dörfler 
904a10cf76eSAxel Dörfler 		case POP_TV_STANDARD_MSG:
905a10cf76eSAxel Dörfler 			message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard);
9065de171daSAxel Dörfler 			_CheckApplyEnabled();
907a10cf76eSAxel Dörfler 			break;
908a10cf76eSAxel Dörfler 
909df3f5bacSStephan Aßmus 		case BUTTON_LAUNCH_BACKGROUNDS_MSG:
9106f095d6aSRyan Leavengood 			if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) {
9116f095d6aSRyan Leavengood 				app_info info;
9126f095d6aSRyan Leavengood 				be_roster->GetAppInfo(kBackgroundsSignature, &info);
9136f095d6aSRyan Leavengood 				be_roster->ActivateApp(info.team);
9146f095d6aSRyan Leavengood 			}
915df3f5bacSStephan Aßmus 			break;
916df3f5bacSStephan Aßmus 
917a10cf76eSAxel Dörfler 		case BUTTON_DEFAULTS_MSG:
918a10cf76eSAxel Dörfler 		{
9194be51fe3SWaldemar Kornewald 			// TODO: get preferred settings of screen
920a10cf76eSAxel Dörfler 			fSelected.width = 640;
921a10cf76eSAxel Dörfler 			fSelected.height = 480;
922a10cf76eSAxel Dörfler 			fSelected.space = B_CMAP8;
923a10cf76eSAxel Dörfler 			fSelected.refresh = 60.0;
924a10cf76eSAxel Dörfler 			fSelected.combine = kCombineDisable;
925a10cf76eSAxel Dörfler 			fSelected.swap_displays = false;
926a10cf76eSAxel Dörfler 			fSelected.use_laptop_panel = false;
927a10cf76eSAxel Dörfler 			fSelected.tv_standard = 0;
928a10cf76eSAxel Dörfler 
929abc649b8SWaldemar Kornewald 			BMenuItem *item;
930abc649b8SWaldemar Kornewald 			item = fWorkspaceCountField->Menu()->ItemAt(3);
931abc649b8SWaldemar Kornewald 			if (item != NULL)
932abc649b8SWaldemar Kornewald 				item->SetMarked(true);
933abc649b8SWaldemar Kornewald 
9345de171daSAxel Dörfler 			_UpdateControls();
935a10cf76eSAxel Dörfler 			break;
936a10cf76eSAxel Dörfler 		}
937a10cf76eSAxel Dörfler 
93810e9b12fSWaldemar Kornewald 		case BUTTON_UNDO_MSG:
939abc649b8SWaldemar Kornewald 			fTempScreenMode.Revert();
9405de171daSAxel Dörfler 			_UpdateActiveMode();
941abc649b8SWaldemar Kornewald 			break;
942abc649b8SWaldemar Kornewald 
943abc649b8SWaldemar Kornewald 		case BUTTON_REVERT_MSG:
944abc649b8SWaldemar Kornewald 		{
945abc649b8SWaldemar Kornewald 			fModified = false;
946199893c3SAxel Dörfler 			fBootWorkspaceApplied = false;
947abc649b8SWaldemar Kornewald 			BMenuItem *item;
948abc649b8SWaldemar Kornewald 			item = fWorkspaceCountField->Menu()->ItemAt(fOriginalWorkspaceCount - 1);
949abc649b8SWaldemar Kornewald 			if (item != NULL)
950abc649b8SWaldemar Kornewald 				item->SetMarked(true);
951abc649b8SWaldemar Kornewald 
952abc649b8SWaldemar Kornewald 			// ScreenMode::Revert() assumes that we first set the correct number
953abc649b8SWaldemar Kornewald 			// of workspaces
954abc649b8SWaldemar Kornewald 			set_workspace_count(fOriginalWorkspaceCount);
955a10cf76eSAxel Dörfler 			fScreenMode.Revert();
9565de171daSAxel Dörfler 			_UpdateActiveMode();
957a10cf76eSAxel Dörfler 			break;
958abc649b8SWaldemar Kornewald 		}
959a10cf76eSAxel Dörfler 
960a10cf76eSAxel Dörfler 		case BUTTON_APPLY_MSG:
9615de171daSAxel Dörfler 			_Apply();
962a10cf76eSAxel Dörfler 			break;
963a10cf76eSAxel Dörfler 
964abc649b8SWaldemar Kornewald 		case MAKE_INITIAL_MSG:
965abc649b8SWaldemar Kornewald 			// user pressed "keep" in confirmation dialog
966abc649b8SWaldemar Kornewald 			fModified = true;
9675de171daSAxel Dörfler 			_UpdateActiveMode();
968a10cf76eSAxel Dörfler 			break;
969a10cf76eSAxel Dörfler 
970a10cf76eSAxel Dörfler 		default:
971a10cf76eSAxel Dörfler 			BWindow::MessageReceived(message);
972a10cf76eSAxel Dörfler 			break;
973a10cf76eSAxel Dörfler 	}
974a10cf76eSAxel Dörfler }
975a10cf76eSAxel Dörfler 
976a10cf76eSAxel Dörfler 
97712580984SAxel Dörfler status_t
97812580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const
97912580984SAxel Dörfler {
98012580984SAxel Dörfler 	BPath path;
98112580984SAxel Dörfler 	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
98212580984SAxel Dörfler 	if (status < B_OK)
98312580984SAxel Dörfler 		return status;
98412580984SAxel Dörfler 
98512580984SAxel Dörfler 	path.Append("kernel/drivers");
98612580984SAxel Dörfler 	status = create_directory(path.Path(), 0755);
98712580984SAxel Dörfler 	if (status < B_OK)
98812580984SAxel Dörfler 		return status;
98912580984SAxel Dörfler 
99012580984SAxel Dörfler 	path.Append("vesa");
99112580984SAxel Dörfler 	BFile file;
99212580984SAxel Dörfler 	status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
99312580984SAxel Dörfler 	if (status < B_OK)
99412580984SAxel Dörfler 		return status;
99512580984SAxel Dörfler 
99612580984SAxel Dörfler 	char buffer[256];
99712580984SAxel Dörfler 	snprintf(buffer, sizeof(buffer), "mode %ld %ld %ld\n",
99812580984SAxel Dörfler 		mode.width, mode.height, mode.BitsPerPixel());
99912580984SAxel Dörfler 
100012580984SAxel Dörfler 	ssize_t bytesWritten = file.Write(buffer, strlen(buffer));
100112580984SAxel Dörfler 	if (bytesWritten < B_OK)
100212580984SAxel Dörfler 		return bytesWritten;
100312580984SAxel Dörfler 
100412580984SAxel Dörfler 	return B_OK;
100512580984SAxel Dörfler }
100612580984SAxel Dörfler 
100712580984SAxel Dörfler 
1008a10cf76eSAxel Dörfler void
10095de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled()
1010a10cf76eSAxel Dörfler {
1011b72c4836SAlexandre Deckner 	fApplyButton->SetEnabled(fSelected != fActive);
10125de171daSAxel Dörfler 	fRevertButton->SetEnabled(count_workspaces() != fOriginalWorkspaceCount
10135de171daSAxel Dörfler 		|| fSelected != fOriginal);
1014a10cf76eSAxel Dörfler }
1015a10cf76eSAxel Dörfler 
1016a10cf76eSAxel Dörfler 
1017a10cf76eSAxel Dörfler void
10185de171daSAxel Dörfler ScreenWindow::_UpdateOriginal()
1019abc649b8SWaldemar Kornewald {
1020abc649b8SWaldemar Kornewald 	fOriginalWorkspaceCount = count_workspaces();
1021abc649b8SWaldemar Kornewald 	fScreenMode.Get(fOriginal);
1022abc649b8SWaldemar Kornewald 	fScreenMode.UpdateOriginalModes();
1023abc649b8SWaldemar Kornewald }
1024abc649b8SWaldemar Kornewald 
1025abc649b8SWaldemar Kornewald 
1026abc649b8SWaldemar Kornewald void
10275de171daSAxel Dörfler ScreenWindow::_Apply()
1028a10cf76eSAxel Dörfler {
1029abc649b8SWaldemar Kornewald 	// make checkpoint, so we can undo these changes
1030abc649b8SWaldemar Kornewald 	fTempScreenMode.UpdateOriginalModes();
103107184a9eSAxel Dörfler 	status_t status = fScreenMode.Set(fSelected);
103207184a9eSAxel Dörfler 	if (status == B_OK) {
1033abc649b8SWaldemar Kornewald 		// use the mode that has eventually been set and
1034abc649b8SWaldemar Kornewald 		// thus we know to be working; it can differ from
1035abc649b8SWaldemar Kornewald 		// the mode selected by user due to hardware limitation
1036abc649b8SWaldemar Kornewald 		display_mode newMode;
1037abc649b8SWaldemar Kornewald 		BScreen screen(this);
1038abc649b8SWaldemar Kornewald 		screen.GetMode(&newMode);
1039abc649b8SWaldemar Kornewald 
1040abc649b8SWaldemar Kornewald 		if (fAllWorkspacesItem->IsMarked()) {
1041abc649b8SWaldemar Kornewald 			int32 originatingWorkspace = current_workspace();
1042abc649b8SWaldemar Kornewald 			for (int32 i = 0; i < count_workspaces(); i++) {
1043abc649b8SWaldemar Kornewald 				if (i != originatingWorkspace)
1044abc649b8SWaldemar Kornewald 					screen.SetMode(i, &newMode, true);
1045abc649b8SWaldemar Kornewald 			}
1046199893c3SAxel Dörfler 			fBootWorkspaceApplied = true;
1047199893c3SAxel Dörfler 		} else {
1048199893c3SAxel Dörfler 			if (current_workspace() == 0)
1049199893c3SAxel Dörfler 				fBootWorkspaceApplied = true;
1050abc649b8SWaldemar Kornewald 		}
1051abc649b8SWaldemar Kornewald 
1052a10cf76eSAxel Dörfler 		fActive = fSelected;
1053a10cf76eSAxel Dörfler 
1054abc649b8SWaldemar Kornewald 		// TODO: only show alert when this is an unknown mode
1055a10cf76eSAxel Dörfler 		BWindow* window = new AlertWindow(this);
1056a10cf76eSAxel Dörfler 		window->Show();
105707184a9eSAxel Dörfler 	} else {
105807184a9eSAxel Dörfler 		char message[256];
105907184a9eSAxel Dörfler 		snprintf(message, sizeof(message),
106007184a9eSAxel Dörfler 			"The screen mode could not be set:\n\t%s\n", screen_errors(status));
106107184a9eSAxel Dörfler 		BAlert* alert = new BAlert("Screen Alert", message, "Okay", NULL, NULL,
106207184a9eSAxel Dörfler 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
106307184a9eSAxel Dörfler 		alert->Go();
1064a10cf76eSAxel Dörfler 	}
106507184a9eSAxel Dörfler }
106607184a9eSAxel Dörfler 
1067df3f5bacSStephan Aßmus 
1068df3f5bacSStephan Aßmus void
10695de171daSAxel Dörfler ScreenWindow::_LayoutControls(uint32 flags)
1070df3f5bacSStephan Aßmus {
1071df3f5bacSStephan Aßmus 	// layout the screen box and its controls
1072df3f5bacSStephan Aßmus 	fWorkspaceCountField->ResizeToPreferred();
1073df3f5bacSStephan Aßmus 
1074df3f5bacSStephan Aßmus 	float monitorViewHeight = fMonitorView->Bounds().Height();
1075df3f5bacSStephan Aßmus 	float workspaceFieldHeight = fWorkspaceCountField->Bounds().Height();
1076df3f5bacSStephan Aßmus 	float backgroundsButtonHeight = fBackgroundsButton->Bounds().Height();
1077df3f5bacSStephan Aßmus 
1078df3f5bacSStephan Aßmus 	float screenBoxWidth = fWorkspaceCountField->Bounds().Width() + 20.0;
10795de171daSAxel Dörfler 	float screenBoxHeight = monitorViewHeight + 5.0 + workspaceFieldHeight + 5.0
10805de171daSAxel Dörfler 		+ backgroundsButtonHeight + 20.0;
1081df3f5bacSStephan Aßmus 
108229e8a73aSAxel Dörfler #ifdef __HAIKU__
1083df3f5bacSStephan Aßmus 	fScreenBox->MoveTo(10.0, 10.0 + fControlsBox->TopBorderOffset());
108429e8a73aSAxel Dörfler #else
108529e8a73aSAxel Dörfler 	fScreenBox->MoveTo(10.0, 10.0 + 3);
108629e8a73aSAxel Dörfler #endif
1087df3f5bacSStephan Aßmus 	fScreenBox->ResizeTo(screenBoxWidth, screenBoxHeight);
1088df3f5bacSStephan Aßmus 
1089df3f5bacSStephan Aßmus 	float leftOffset = 10.0;
1090df3f5bacSStephan Aßmus 	float topOffset = 10.0;
1091df3f5bacSStephan Aßmus 	fMonitorView->MoveTo(leftOffset, topOffset);
1092df3f5bacSStephan Aßmus 	fMonitorView->ResizeTo(screenBoxWidth - 20.0, monitorViewHeight);
1093df3f5bacSStephan Aßmus 	fMonitorView->SetResizingMode(B_FOLLOW_ALL);
1094df3f5bacSStephan Aßmus 	topOffset += monitorViewHeight + 5.0;
1095df3f5bacSStephan Aßmus 
1096df3f5bacSStephan Aßmus 	fWorkspaceCountField->MoveTo(leftOffset, topOffset);
1097df3f5bacSStephan Aßmus 	fWorkspaceCountField->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
1098df3f5bacSStephan Aßmus 	topOffset += workspaceFieldHeight + 5.0;
1099df3f5bacSStephan Aßmus 
1100df3f5bacSStephan Aßmus 	fBackgroundsButton->MoveTo(leftOffset, topOffset);
1101df3f5bacSStephan Aßmus 	fBackgroundsButton->ResizeTo(screenBoxWidth - 20.0, backgroundsButtonHeight);
1102df3f5bacSStephan Aßmus 	fBackgroundsButton->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
1103df3f5bacSStephan Aßmus 
1104df3f5bacSStephan Aßmus 	fControlsBox->MoveTo(fScreenBox->Frame().right + 10.0, 10.0);
1105df3f5bacSStephan Aßmus 
1106df3f5bacSStephan Aßmus 	// layout the right side
11074008594dSWaldemar Kornewald 	fApplyButton->ResizeToPreferred();
11085de171daSAxel Dörfler 	BRect controlsRect = _LayoutMenuFields(flags);
1109df3f5bacSStephan Aßmus 	controlsRect.InsetBy(-10.0, -10.0);
11104008594dSWaldemar Kornewald 	controlsRect.bottom += 8 + fApplyButton->Bounds().Height();
1111df3f5bacSStephan Aßmus 	// adjust size of controls box and move aligned buttons along
1112df3f5bacSStephan Aßmus 	float xDiff = controlsRect.right - fControlsBox->Bounds().right;
1113df3f5bacSStephan Aßmus 	float yDiff = controlsRect.bottom - fControlsBox->Bounds().bottom;
1114df3f5bacSStephan Aßmus 	if (yDiff < 0.0) {
1115df3f5bacSStephan Aßmus 		// don't shrink vertically
1116df3f5bacSStephan Aßmus 		yDiff = 0.0;
1117df3f5bacSStephan Aßmus 	}
1118df3f5bacSStephan Aßmus 
1119df3f5bacSStephan Aßmus 	fControlsBox->ResizeBy(xDiff, yDiff);
1120df3f5bacSStephan Aßmus 
1121df3f5bacSStephan Aßmus 	// align bottom of boxen
1122df3f5bacSStephan Aßmus 	float boxBottomDiff = fControlsBox->Frame().bottom - fScreenBox->Frame().bottom;
1123df3f5bacSStephan Aßmus 	if (boxBottomDiff > 0)
1124df3f5bacSStephan Aßmus 		fScreenBox->ResizeBy(0.0, boxBottomDiff);
1125df3f5bacSStephan Aßmus 	else
1126df3f5bacSStephan Aßmus 		fControlsBox->ResizeBy(0.0, -boxBottomDiff);
1127df3f5bacSStephan Aßmus 
1128df3f5bacSStephan Aßmus 	BRect boxFrame = fScreenBox->Frame() | fControlsBox->Frame();
1129df3f5bacSStephan Aßmus 
1130df3f5bacSStephan Aßmus 	// layout rest of buttons
1131abc649b8SWaldemar Kornewald 	// TODO: we don't support getting the screen's preferred settings
1132abc649b8SWaldemar Kornewald //	fDefaultsButton->ResizeToPreferred();
1133abc649b8SWaldemar Kornewald //	fDefaultsButton->MoveTo(boxFrame.left, boxFrame.bottom + 8);
1134df3f5bacSStephan Aßmus 
1135df3f5bacSStephan Aßmus 	fRevertButton->ResizeToPreferred();
1136abc649b8SWaldemar Kornewald 	fRevertButton->MoveTo(boxFrame.left, boxFrame.bottom + 8);
1137abc649b8SWaldemar Kornewald //	fRevertButton->MoveTo(fDefaultsButton->Frame().right + 10,
1138abc649b8SWaldemar Kornewald //						  fDefaultsButton->Frame().top);
1139df3f5bacSStephan Aßmus 
11404008594dSWaldemar Kornewald 	// Apply button was already resized above
1141abc649b8SWaldemar Kornewald 	float resolutionFieldRight = fResolutionField->Frame().right;
1142abc649b8SWaldemar Kornewald 	fApplyButton->MoveTo(resolutionFieldRight - fApplyButton->Bounds().Width(),
11434008594dSWaldemar Kornewald 		fControlsBox->Bounds().bottom - fApplyButton->Bounds().Height() - 10);
1144df3f5bacSStephan Aßmus 
1145abc649b8SWaldemar Kornewald 	ResizeTo(boxFrame.right + 10, fRevertButton->Frame().bottom + 10);
1146df3f5bacSStephan Aßmus }
1147df3f5bacSStephan Aßmus 
1148df3f5bacSStephan Aßmus 
1149df3f5bacSStephan Aßmus BRect
11505de171daSAxel Dörfler ScreenWindow::_LayoutMenuFields(uint32 flags, bool sideBySide)
1151df3f5bacSStephan Aßmus {
1152df3f5bacSStephan Aßmus 	BList menuFields;
1153df3f5bacSStephan Aßmus 	menuFields.AddItem((void*)fResolutionField);
1154df3f5bacSStephan Aßmus 	menuFields.AddItem((void*)fColorsField);
1155df3f5bacSStephan Aßmus 	menuFields.AddItem((void*)fRefreshField);
1156df3f5bacSStephan Aßmus 
1157df3f5bacSStephan Aßmus 	BRect frame;
1158df3f5bacSStephan Aßmus 
1159df3f5bacSStephan Aßmus 	if (sideBySide)
1160df3f5bacSStephan Aßmus 		frame = stack_and_align_menu_fields(menuFields);
1161df3f5bacSStephan Aßmus 
1162df3f5bacSStephan Aßmus 	if (sideBySide)
1163df3f5bacSStephan Aßmus 		menuFields.MakeEmpty();
1164df3f5bacSStephan Aßmus 
1165df3f5bacSStephan Aßmus 	if (flags & SHOW_COMBINE_FIELD)
1166df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fCombineField);
1167df3f5bacSStephan Aßmus 	if (flags & SHOW_SWAP_FIELD)
1168df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fSwapDisplaysField);
1169df3f5bacSStephan Aßmus 	if (flags & SHOW_LAPTOP_PANEL_FIELD)
1170df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fUseLaptopPanelField);
1171df3f5bacSStephan Aßmus 	if (flags & SHOW_TV_STANDARD_FIELD)
1172df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fTVStandardField);
1173df3f5bacSStephan Aßmus 
1174df3f5bacSStephan Aßmus 	if (sideBySide) {
1175df3f5bacSStephan Aßmus 		if (menuFields.CountItems() > 0) {
1176df3f5bacSStephan Aßmus 			((BMenuField*)menuFields.FirstItem())->MoveTo(frame.right + 8.0, frame.top);
1177df3f5bacSStephan Aßmus 			frame = frame | stack_and_align_menu_fields(menuFields);
1178df3f5bacSStephan Aßmus 		}
1179df3f5bacSStephan Aßmus 	} else {
1180df3f5bacSStephan Aßmus 		frame = stack_and_align_menu_fields(menuFields);
1181df3f5bacSStephan Aßmus 	}
1182df3f5bacSStephan Aßmus 
1183df3f5bacSStephan Aßmus 	return frame;
1184df3f5bacSStephan Aßmus }
1185df3f5bacSStephan Aßmus 
1186