xref: /haiku/src/preferences/screen/ScreenWindow.cpp (revision 4be51fe314df1645aa937335ad861fc739071259)
1a10cf76eSAxel Dörfler /*
212580984SAxel Dörfler  * Copyright 2001-2007, 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>
12a10cf76eSAxel Dörfler  */
13a10cf76eSAxel Dörfler 
14a10cf76eSAxel Dörfler 
15a10cf76eSAxel Dörfler #include "AlertWindow.h"
16a10cf76eSAxel Dörfler #include "Constants.h"
17a10cf76eSAxel Dörfler #include "RefreshWindow.h"
18a10cf76eSAxel Dörfler #include "MonitorView.h"
19a10cf76eSAxel Dörfler #include "ScreenSettings.h"
20a10cf76eSAxel Dörfler #include "ScreenWindow.h"
21a10cf76eSAxel Dörfler #include "Utility.h"
22a10cf76eSAxel Dörfler 
23a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant.
24a10cf76eSAxel Dörfler  * It's a solution that works with the current BeOS interface that Haiku
25a10cf76eSAxel Dörfler  * adopted.
26a10cf76eSAxel Dörfler  * However, it's not a nice and clean solution. Don't use this header in any
27a10cf76eSAxel Dörfler  * application if you can avoid it. No other driver is using this, or should
28a10cf76eSAxel Dörfler  * be using this.
29a10cf76eSAxel Dörfler  * It will be replaced as soon as we introduce an updated accelerant interface
30a10cf76eSAxel Dörfler  * which may even happen before R1 hits the streets.
31a10cf76eSAxel Dörfler  */
32a10cf76eSAxel Dörfler #include "multimon.h"	// the usual: DANGER WILL, ROBINSON!
33a10cf76eSAxel Dörfler 
3412580984SAxel Dörfler #include <Alert.h>
3512580984SAxel Dörfler #include <Application.h>
3612580984SAxel Dörfler #include <Box.h>
3712580984SAxel Dörfler #include <Button.h>
3812580984SAxel Dörfler #include <Directory.h>
3912580984SAxel Dörfler #include <File.h>
4012580984SAxel Dörfler #include <FindDirectory.h>
4112580984SAxel Dörfler #include <InterfaceDefs.h>
4212580984SAxel Dörfler #include <MenuBar.h>
4312580984SAxel Dörfler #include <MenuItem.h>
4412580984SAxel Dörfler #include <MenuField.h>
4512580984SAxel Dörfler #include <Messenger.h>
4612580984SAxel Dörfler #include <Path.h>
4712580984SAxel Dörfler #include <PopUpMenu.h>
4812580984SAxel Dörfler #include <Screen.h>
4912580984SAxel Dörfler #include <String.h>
5012580984SAxel Dörfler #include <Roster.h>
5112580984SAxel Dörfler #include <Window.h>
5212580984SAxel Dörfler 
5312580984SAxel Dörfler #include <stdio.h>
5412580984SAxel Dörfler #include <stdlib.h>
5512580984SAxel Dörfler #include <string.h>
5612580984SAxel Dörfler 
57a10cf76eSAxel Dörfler 
58c5d80d47SAxel Dörfler const char* kBackgroundsSignature = "application/x-vnd.haiku-backgrounds";
59c5d80d47SAxel Dörfler 
60a10cf76eSAxel Dörfler // list of officially supported colour spaces
61a10cf76eSAxel Dörfler static const struct {
62a10cf76eSAxel Dörfler 	color_space	space;
63a10cf76eSAxel Dörfler 	int32		bits_per_pixel;
64a10cf76eSAxel Dörfler 	const char*	label;
65a10cf76eSAxel Dörfler } kColorSpaces[] = {
66a10cf76eSAxel Dörfler 	{ B_CMAP8, 8, "8 Bits/Pixel, 256 Colors" },
67a10cf76eSAxel Dörfler 	{ B_RGB15, 15, "15 Bits/Pixel, 32768 Colors" },
68a10cf76eSAxel Dörfler 	{ B_RGB16, 16, "16 Bits/Pixel, 65536 Colors" },
69a10cf76eSAxel Dörfler 	{ B_RGB32, 32, "32 Bits/Pixel, 16 Million Colors" }
70a10cf76eSAxel Dörfler };
71a10cf76eSAxel Dörfler static const int32 kColorSpaceCount = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]);
72a10cf76eSAxel Dörfler 
73a10cf76eSAxel Dörfler // list of standard refresh rates
74a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 };
75a10cf76eSAxel Dörfler static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]);
76a10cf76eSAxel Dörfler 
77a10cf76eSAxel Dörfler // list of combine modes
78a10cf76eSAxel Dörfler static const struct {
79a10cf76eSAxel Dörfler 	combine_mode	mode;
80a10cf76eSAxel Dörfler 	const char		*name;
81a10cf76eSAxel Dörfler } kCombineModes[] = {
82a10cf76eSAxel Dörfler 	{ kCombineDisable, "disable" },
83a10cf76eSAxel Dörfler 	{ kCombineHorizontally, "horizontally" },
84a10cf76eSAxel Dörfler 	{ kCombineVertically, "vertically" }
85a10cf76eSAxel Dörfler };
86a10cf76eSAxel Dörfler static const int32 kCombineModeCount = sizeof(kCombineModes) / sizeof(kCombineModes[0]);
87a10cf76eSAxel Dörfler 
8829e8a73aSAxel Dörfler enum {
8929e8a73aSAxel Dörfler 	SHOW_COMBINE_FIELD		= 0x01,
9029e8a73aSAxel Dörfler 	SHOW_SWAP_FIELD			= 0x02,
9129e8a73aSAxel Dörfler 	SHOW_LAPTOP_PANEL_FIELD	= 0x04,
9229e8a73aSAxel Dörfler 	SHOW_TV_STANDARD_FIELD	= 0x08,
9329e8a73aSAxel Dörfler };
9429e8a73aSAxel Dörfler 
95a10cf76eSAxel Dörfler 
96a10cf76eSAxel Dörfler static BString
97a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode)
98a10cf76eSAxel Dörfler {
99a10cf76eSAxel Dörfler 	switch (mode) {
100a10cf76eSAxel Dörfler 		case 0:		return "disabled";
101a10cf76eSAxel Dörfler 		case 1:		return "NTSC";
102a10cf76eSAxel Dörfler 		case 2:		return "NTSC Japan";
103a10cf76eSAxel Dörfler 		case 3:		return "PAL BDGHI";
104a10cf76eSAxel Dörfler 		case 4:		return "PAL M";
105a10cf76eSAxel Dörfler 		case 5:		return "PAL N";
106a10cf76eSAxel Dörfler 		case 6:		return "SECAM";
107a10cf76eSAxel Dörfler 		case 101:	return "NTSC 443";
108a10cf76eSAxel Dörfler 		case 102:	return "PAL 60";
109a10cf76eSAxel Dörfler 		case 103:	return "PAL NC";
110a10cf76eSAxel Dörfler 		default:
111a10cf76eSAxel Dörfler 		{
112a10cf76eSAxel Dörfler 			BString name;
113a10cf76eSAxel Dörfler 			name << "??? (" << mode << ")";
114a10cf76eSAxel Dörfler 
115a10cf76eSAxel Dörfler 			return name;
116a10cf76eSAxel Dörfler 		}
117a10cf76eSAxel Dörfler 	}
118a10cf76eSAxel Dörfler }
119a10cf76eSAxel Dörfler 
120a10cf76eSAxel Dörfler 
121a10cf76eSAxel Dörfler static void
122a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string)
123a10cf76eSAxel Dörfler {
124a10cf76eSAxel Dörfler 	string << mode.width << " x " << mode.height;
125a10cf76eSAxel Dörfler }
126a10cf76eSAxel Dörfler 
127a10cf76eSAxel Dörfler 
128a10cf76eSAxel Dörfler static void
129a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string,
130a10cf76eSAxel Dörfler 	bool appendUnit = true, bool alwaysWithFraction = false)
131a10cf76eSAxel Dörfler {
132a10cf76eSAxel Dörfler 	snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, refresh);
133a10cf76eSAxel Dörfler 	string.UnlockBuffer();
134a10cf76eSAxel Dörfler 
135a10cf76eSAxel Dörfler 	if (appendUnit)
136a10cf76eSAxel Dörfler 		string << " Hz";
137a10cf76eSAxel Dörfler }
138a10cf76eSAxel Dörfler 
139a10cf76eSAxel Dörfler 
14007184a9eSAxel Dörfler static const char*
14107184a9eSAxel Dörfler screen_errors(status_t status)
14207184a9eSAxel Dörfler {
14307184a9eSAxel Dörfler 	switch (status) {
14407184a9eSAxel Dörfler 		case B_ENTRY_NOT_FOUND:
14507184a9eSAxel Dörfler 			return "Unknown Mode";
14607184a9eSAxel Dörfler 		// TODO: add more?
14707184a9eSAxel Dörfler 
14807184a9eSAxel Dörfler 		default:
14907184a9eSAxel Dörfler 			return strerror(status);
15007184a9eSAxel Dörfler 	}
15107184a9eSAxel Dörfler }
15207184a9eSAxel Dörfler 
15329e8a73aSAxel Dörfler 
15429e8a73aSAxel Dörfler static float
15529e8a73aSAxel Dörfler max_label_width(BMenuField* control, float widestLabel)
15629e8a73aSAxel Dörfler {
15729e8a73aSAxel Dörfler 	float labelWidth = control->StringWidth(control->Label());
15829e8a73aSAxel Dörfler 	if (widestLabel < labelWidth)
15929e8a73aSAxel Dörfler 		return labelWidth;
16029e8a73aSAxel Dörfler 	return widestLabel;
16129e8a73aSAxel Dörfler }
16229e8a73aSAxel Dörfler 
16329e8a73aSAxel Dörfler 
16429e8a73aSAxel Dörfler static BRect
16529e8a73aSAxel Dörfler stack_and_align_menu_fields(const BList& menuFields)
16629e8a73aSAxel Dörfler {
16729e8a73aSAxel Dörfler 	float widestLabel = 0.0;
16829e8a73aSAxel Dörfler 	int32 count = menuFields.CountItems();
16929e8a73aSAxel Dörfler 	for (int32 i = 0; i < count; i++) {
17029e8a73aSAxel Dörfler 		BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i);
17129e8a73aSAxel Dörfler 		widestLabel = max_label_width(menuField, widestLabel);
17229e8a73aSAxel Dörfler 	}
17329e8a73aSAxel Dörfler 
17429e8a73aSAxel Dörfler 	// add some room (but only if there is text at all)
17529e8a73aSAxel Dörfler 	if (widestLabel > 0.0)
17629e8a73aSAxel Dörfler 		widestLabel += 5.0;
17729e8a73aSAxel Dörfler 
17829e8a73aSAxel Dörfler 	// make all controls the same width
17929e8a73aSAxel Dörfler 	float widestField = 0.0;
18029e8a73aSAxel Dörfler 	for (int32 i = 0; i < count; i++) {
18129e8a73aSAxel Dörfler 		BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i);
18229e8a73aSAxel Dörfler 		menuField->SetAlignment(B_ALIGN_RIGHT);
18329e8a73aSAxel Dörfler 		menuField->SetDivider(widestLabel);
18429e8a73aSAxel Dörfler 		menuField->ResizeToPreferred();
18529e8a73aSAxel Dörfler 		widestField = max_c(menuField->Bounds().Width(), widestField);
18629e8a73aSAxel Dörfler 	}
18729e8a73aSAxel Dörfler 
18829e8a73aSAxel Dörfler 	// layout controls under each other, resize all to size
18929e8a73aSAxel Dörfler 	// of largest of them (they could still have different
19029e8a73aSAxel Dörfler 	// heights though)
19129e8a73aSAxel Dörfler 	BMenuField* topMenuField = (BMenuField*)menuFields.FirstItem();
19229e8a73aSAxel Dörfler 	BPoint leftTop = topMenuField->Frame().LeftTop();
19329e8a73aSAxel Dörfler 	BRect frame = topMenuField->Frame();
19429e8a73aSAxel Dörfler 
19529e8a73aSAxel Dörfler 	for (int32 i = 0; i < count; i++) {
19629e8a73aSAxel Dörfler 		BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i);
19729e8a73aSAxel Dörfler 		menuField->MoveTo(leftTop);
19829e8a73aSAxel Dörfler 		float height = menuField->Bounds().Height();
19929e8a73aSAxel Dörfler 		menuField->ResizeTo(widestField, height);
20029e8a73aSAxel Dörfler 		frame = frame | menuField->Frame();
20129e8a73aSAxel Dörfler 		leftTop.y += height + 5.0;
20229e8a73aSAxel Dörfler 	}
20329e8a73aSAxel Dörfler 
20429e8a73aSAxel Dörfler 	return frame;
20529e8a73aSAxel Dörfler }
206df3f5bacSStephan Aßmus 
207df3f5bacSStephan Aßmus 
2083dfd20c0SStephan Aßmus //	#pragma mark -
2093dfd20c0SStephan Aßmus 
2103dfd20c0SStephan Aßmus 
2115a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings *settings)
2125a78744bSAxel Dörfler 	: BWindow(settings->WindowFrame(), "Screen", B_TITLED_WINDOW,
213a10cf76eSAxel Dörfler 		B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES),
21412580984SAxel Dörfler 	fIsVesa(false),
21512580984SAxel Dörfler 	fVesaApplied(false),
216a10cf76eSAxel Dörfler 	fScreenMode(this),
217a10cf76eSAxel Dörfler 	fChangingAllWorkspaces(false)
218a10cf76eSAxel Dörfler {
219a10cf76eSAxel Dörfler 	BScreen screen(this);
220a10cf76eSAxel Dörfler 
22112580984SAxel Dörfler 	accelerant_device_info info;
22212580984SAxel Dörfler 	if (screen.GetDeviceInfo(&info) == B_OK && !strcasecmp(info.chipset, "VESA"))
22312580984SAxel Dörfler 		fIsVesa = true;
22412580984SAxel Dörfler 
225a10cf76eSAxel Dörfler 	fScreenMode.Get(fOriginal);
226a10cf76eSAxel Dörfler 	fActive = fSelected = fOriginal;
227a10cf76eSAxel Dörfler 
228df3f5bacSStephan Aßmus 	BView *view = new BView(Bounds(), "ScreenView", B_FOLLOW_ALL, B_WILL_DRAW);
229a10cf76eSAxel Dörfler 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
230a10cf76eSAxel Dörfler 	AddChild(view);
231a10cf76eSAxel Dörfler 
2325a78744bSAxel Dörfler 	fSettings = settings;
2335a78744bSAxel Dörfler 
2345a78744bSAxel Dörfler 	// we need the "Current Workspace" first to get its height
2355a78744bSAxel Dörfler 
2365a78744bSAxel Dörfler 	BPopUpMenu *popUpMenu = new BPopUpMenu("Current Workspace", true, true);
2375a78744bSAxel Dörfler 	fAllWorkspacesItem = new BMenuItem("All Workspaces", new BMessage(WORKSPACE_CHECK_MSG));
2385a78744bSAxel Dörfler 	popUpMenu->AddItem(fAllWorkspacesItem);
2395a78744bSAxel Dörfler 	BMenuItem *item = new BMenuItem("Current Workspace", new BMessage(WORKSPACE_CHECK_MSG));
24012580984SAxel Dörfler 	if (_IsVesa()) {
24112580984SAxel Dörfler 		fAllWorkspacesItem->SetMarked(true);
24212580984SAxel Dörfler 		item->SetEnabled(false);
24312580984SAxel Dörfler 	} else
2445a78744bSAxel Dörfler 		item->SetMarked(true);
2455a78744bSAxel Dörfler 	popUpMenu->AddItem(item);
2465a78744bSAxel Dörfler 
247df3f5bacSStephan Aßmus 	BMenuField* workspaceMenuField = new BMenuField(BRect(0, 0, 100, 15),
2485a78744bSAxel Dörfler 		"WorkspaceMenu", NULL, popUpMenu, true);
2495a78744bSAxel Dörfler 	workspaceMenuField->ResizeToPreferred();
250a10cf76eSAxel Dörfler 
251a10cf76eSAxel Dörfler 	// box on the left with workspace count and monitor view
252a10cf76eSAxel Dörfler 
2535a78744bSAxel Dörfler 	popUpMenu = new BPopUpMenu("", true, true);
254df3f5bacSStephan Aßmus 	fWorkspaceCountField = new BMenuField(BRect(0.0, 0.0, 50.0, 15.0),
255df3f5bacSStephan Aßmus 		"WorkspaceCountMenu", "Workspace count:", popUpMenu, true);
256df3f5bacSStephan Aßmus 	float labelWidth = fWorkspaceCountField->StringWidth(fWorkspaceCountField->Label()) + 5.0;
257df3f5bacSStephan Aßmus 	fWorkspaceCountField->SetDivider(labelWidth);
258df3f5bacSStephan Aßmus 
259df3f5bacSStephan Aßmus 	fScreenBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0), "left box");
260df3f5bacSStephan Aßmus 	fScreenBox->AddChild(fWorkspaceCountField);
261a10cf76eSAxel Dörfler 
262a10cf76eSAxel Dörfler 	for (int32 count = 1; count <= 32; count++) {
263a10cf76eSAxel Dörfler 		BString workspaceCount;
264a10cf76eSAxel Dörfler 		workspaceCount << count;
265a10cf76eSAxel Dörfler 
266a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_WORKSPACE_CHANGED_MSG);
267a10cf76eSAxel Dörfler 		message->AddInt32("workspace count", count);
268a10cf76eSAxel Dörfler 
269a10cf76eSAxel Dörfler 		popUpMenu->AddItem(new BMenuItem(workspaceCount.String(),
270a10cf76eSAxel Dörfler 			message));
271a10cf76eSAxel Dörfler 	}
272a10cf76eSAxel Dörfler 
2735a78744bSAxel Dörfler 	item = popUpMenu->ItemAt(count_workspaces() - 1);
274a10cf76eSAxel Dörfler 	if (item != NULL)
275a10cf76eSAxel Dörfler 		item->SetMarked(true);
276a10cf76eSAxel Dörfler 
277df3f5bacSStephan Aßmus 	fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), "monitor",
2785a78744bSAxel Dörfler 		screen.Frame().Width() + 1, screen.Frame().Height() + 1);
279df3f5bacSStephan Aßmus 	fScreenBox->AddChild(fMonitorView);
2805a78744bSAxel Dörfler 
281df3f5bacSStephan Aßmus 	view->AddChild(fScreenBox);
282a10cf76eSAxel Dörfler 
283a10cf76eSAxel Dörfler 	// box on the right with screen resolution, etc.
284a10cf76eSAxel Dörfler 
285df3f5bacSStephan Aßmus 	fControlsBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0));
286df3f5bacSStephan Aßmus 	fControlsBox->SetLabel(workspaceMenuField);
287a10cf76eSAxel Dörfler 
288a10cf76eSAxel Dörfler 	fResolutionMenu = new BPopUpMenu("resolution", true, true);
289a10cf76eSAxel Dörfler 
290a10cf76eSAxel Dörfler 	uint16 previousWidth = 0, previousHeight = 0;
291a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
292a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
293a10cf76eSAxel Dörfler 
294a10cf76eSAxel Dörfler 		if (mode.width == previousWidth && mode.height == previousHeight)
295a10cf76eSAxel Dörfler 			continue;
296a10cf76eSAxel Dörfler 
297a10cf76eSAxel Dörfler 		previousWidth = mode.width;
298a10cf76eSAxel Dörfler 		previousHeight = mode.height;
299a10cf76eSAxel Dörfler 
300a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_RESOLUTION_MSG);
301a10cf76eSAxel Dörfler 		message->AddInt32("width", mode.width);
302a10cf76eSAxel Dörfler 		message->AddInt32("height", mode.height);
303a10cf76eSAxel Dörfler 
304a10cf76eSAxel Dörfler 		BString name;
305a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
306a10cf76eSAxel Dörfler 
307a10cf76eSAxel Dörfler 		fResolutionMenu->AddItem(new BMenuItem(name.String(), message));
308a10cf76eSAxel Dörfler 	}
309a10cf76eSAxel Dörfler 
31029e8a73aSAxel Dörfler 	BRect rect(0.0, 0.0, 200.0, 15.0);
311df3f5bacSStephan Aßmus 	// fResolutionField needs to be at the correct
312df3f5bacSStephan Aßmus 	// left-top offset, because all other menu fields
313df3f5bacSStephan Aßmus 	// will be layouted relative to it
314df3f5bacSStephan Aßmus 	fResolutionField = new BMenuField(rect.OffsetToCopy(10.0, 30.0),
315df3f5bacSStephan Aßmus 		"ResolutionMenu", "Resolution:", fResolutionMenu, true);
316df3f5bacSStephan Aßmus 	fControlsBox->AddChild(fResolutionField);
317a10cf76eSAxel Dörfler 
318a10cf76eSAxel Dörfler 	fColorsMenu = new BPopUpMenu("colors", true, true);
319a10cf76eSAxel Dörfler 
320a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
321a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_COLORS_MSG);
322a10cf76eSAxel Dörfler 		message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
323a10cf76eSAxel Dörfler 		message->AddInt32("space", kColorSpaces[i].space);
324a10cf76eSAxel Dörfler 
325a10cf76eSAxel Dörfler 		fColorsMenu->AddItem(new BMenuItem(kColorSpaces[i].label, message));
326a10cf76eSAxel Dörfler 	}
327a10cf76eSAxel Dörfler 
328df3f5bacSStephan Aßmus 	rect.OffsetTo(B_ORIGIN);
329df3f5bacSStephan Aßmus 
330a10cf76eSAxel Dörfler 	fColorsField = new BMenuField(rect, "ColorsMenu", "Colors:", fColorsMenu, true);
331df3f5bacSStephan Aßmus 	fControlsBox->AddChild(fColorsField);
332a10cf76eSAxel Dörfler 
333a10cf76eSAxel Dörfler 	fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
334a10cf76eSAxel Dörfler 
33529e8a73aSAxel Dörfler 	BMessage *message;
33629e8a73aSAxel Dörfler 
33729e8a73aSAxel Dörfler 	float min, max;
33829e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fActive, min, max) && min == max) {
33929e8a73aSAxel Dörfler 		// This is a special case for drivers that only support a single
34029e8a73aSAxel Dörfler 		// frequency, like the VESA driver
34129e8a73aSAxel Dörfler 		BString name;
34229e8a73aSAxel Dörfler 		name << min << " Hz";
34329e8a73aSAxel Dörfler 
34429e8a73aSAxel Dörfler 		message = new BMessage(POP_REFRESH_MSG);
34529e8a73aSAxel Dörfler 		message->AddFloat("refresh", min);
34629e8a73aSAxel Dörfler 
34729e8a73aSAxel Dörfler 		fRefreshMenu->AddItem(item = new BMenuItem(name.String(), message));
34829e8a73aSAxel Dörfler 		item->SetEnabled(false);
34929e8a73aSAxel Dörfler 	} else {
350a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kRefreshRateCount; ++i) {
351a10cf76eSAxel Dörfler 			BString name;
352a10cf76eSAxel Dörfler 			name << kRefreshRates[i] << " Hz";
353a10cf76eSAxel Dörfler 
35429e8a73aSAxel Dörfler 			message = new BMessage(POP_REFRESH_MSG);
355a10cf76eSAxel Dörfler 			message->AddFloat("refresh", kRefreshRates[i]);
356a10cf76eSAxel Dörfler 
357a10cf76eSAxel Dörfler 			fRefreshMenu->AddItem(new BMenuItem(name.String(), message));
358a10cf76eSAxel Dörfler 		}
359a10cf76eSAxel Dörfler 
36029e8a73aSAxel Dörfler 		message = new BMessage(POP_OTHER_REFRESH_MSG);
361a10cf76eSAxel Dörfler 
362a10cf76eSAxel Dörfler 		fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message);
363a10cf76eSAxel Dörfler 		fRefreshMenu->AddItem(fOtherRefresh);
36429e8a73aSAxel Dörfler 	}
365a10cf76eSAxel Dörfler 
366a10cf76eSAxel Dörfler 	fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:", fRefreshMenu, true);
36712580984SAxel Dörfler 	if (_IsVesa())
36812580984SAxel Dörfler 		fRefreshField->Hide();
369df3f5bacSStephan Aßmus 	fControlsBox->AddChild(fRefreshField);
370a10cf76eSAxel Dörfler 
371df3f5bacSStephan Aßmus 	view->AddChild(fControlsBox);
372df3f5bacSStephan Aßmus 
373df3f5bacSStephan Aßmus 	uint32 controlsFlags = 0;
374a10cf76eSAxel Dörfler 
375a10cf76eSAxel Dörfler 	// enlarged area for multi-monitor settings
376a10cf76eSAxel Dörfler 	{
377a10cf76eSAxel Dörfler 		bool dummy;
378a10cf76eSAxel Dörfler 		uint32 dummy32;
379a10cf76eSAxel Dörfler 		bool multiMonSupport;
380a10cf76eSAxel Dörfler 		bool useLaptopPanelSupport;
381a10cf76eSAxel Dörfler 		bool tvStandardSupport;
382a10cf76eSAxel Dörfler 
383a10cf76eSAxel Dörfler 		multiMonSupport = TestMultiMonSupport(&screen) == B_OK;
384a10cf76eSAxel Dörfler 		useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK;
385a10cf76eSAxel Dörfler 		tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK;
386df3f5bacSStephan Aßmus 		if (multiMonSupport) {
387df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_COMBINE_FIELD;
388df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_SWAP_FIELD;
389df3f5bacSStephan Aßmus 		}
390df3f5bacSStephan Aßmus 		if (useLaptopPanelSupport)
391df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_LAPTOP_PANEL_FIELD;
392a10cf76eSAxel Dörfler 
393a10cf76eSAxel Dörfler 		// even if there is no support, we still create all controls
394a10cf76eSAxel Dörfler 		// to make sure we don't access NULL pointers later on
395a10cf76eSAxel Dörfler 
396a10cf76eSAxel Dörfler 		fCombineMenu = new BPopUpMenu("CombineDisplays", true, true);
397a10cf76eSAxel Dörfler 
398a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kCombineModeCount; i++) {
399a10cf76eSAxel Dörfler 			message = new BMessage(POP_COMBINE_DISPLAYS_MSG);
400a10cf76eSAxel Dörfler 			message->AddInt32("mode", kCombineModes[i].mode);
401a10cf76eSAxel Dörfler 
402a10cf76eSAxel Dörfler 			fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, message));
403a10cf76eSAxel Dörfler 		}
404a10cf76eSAxel Dörfler 
405df3f5bacSStephan Aßmus 		fCombineField = new BMenuField(rect, "CombineMenu",
406a10cf76eSAxel Dörfler 			"Combine Displays:", fCombineMenu, true);
407df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fCombineField);
408a10cf76eSAxel Dörfler 
409a10cf76eSAxel Dörfler 		if (!multiMonSupport)
410df3f5bacSStephan Aßmus 			fCombineField->Hide();
411a10cf76eSAxel Dörfler 
412a10cf76eSAxel Dörfler 		fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true);
413a10cf76eSAxel Dörfler 
414a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
415a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
416a10cf76eSAxel Dörfler 		message->AddBool("swap", false);
417a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("no", message));
418a10cf76eSAxel Dörfler 
419a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
420a10cf76eSAxel Dörfler 		message->AddBool("swap", true);
421a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message));
422a10cf76eSAxel Dörfler 
423df3f5bacSStephan Aßmus 		fSwapDisplaysField = new BMenuField(rect, "SwapMenu", "Swap Displays:",
424a10cf76eSAxel Dörfler 			fSwapDisplaysMenu, true);
425a10cf76eSAxel Dörfler 
426df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fSwapDisplaysField);
427a10cf76eSAxel Dörfler 		if (!multiMonSupport)
428df3f5bacSStephan Aßmus 			fSwapDisplaysField->Hide();
429a10cf76eSAxel Dörfler 
430a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true);
431a10cf76eSAxel Dörfler 
432a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
433a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
434a10cf76eSAxel Dörfler 		message->AddBool("use", false);
435a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message));
436a10cf76eSAxel Dörfler 
437a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
438a10cf76eSAxel Dörfler 		message->AddBool("use", true);
439a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message));
440a10cf76eSAxel Dörfler 
441df3f5bacSStephan Aßmus 		fUseLaptopPanelField = new BMenuField(rect, "UseLaptopPanel", "Use Laptop Panel:",
442a10cf76eSAxel Dörfler 			fUseLaptopPanelMenu, true);
443a10cf76eSAxel Dörfler 
444df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fUseLaptopPanelField);
445a10cf76eSAxel Dörfler 		if (!useLaptopPanelSupport)
446df3f5bacSStephan Aßmus 			fUseLaptopPanelField->Hide();
447a10cf76eSAxel Dörfler 
448a10cf76eSAxel Dörfler 		fTVStandardMenu = new BPopUpMenu("TVStandard", true, true);
449a10cf76eSAxel Dörfler 
450a10cf76eSAxel Dörfler 		// arbitrary limit
451a10cf76eSAxel Dörfler 		uint32 i;
452a10cf76eSAxel Dörfler 		for (i = 0; i < 100; ++i) {
453a10cf76eSAxel Dörfler 			uint32 mode;
454a10cf76eSAxel Dörfler 
455a10cf76eSAxel Dörfler 			if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK)
456a10cf76eSAxel Dörfler 				break;
457a10cf76eSAxel Dörfler 
458a10cf76eSAxel Dörfler 			BString name = tv_standard_to_string(mode);
459a10cf76eSAxel Dörfler 
460a10cf76eSAxel Dörfler 			message = new BMessage(POP_TV_STANDARD_MSG);
461a10cf76eSAxel Dörfler 			message->AddInt32("tv_standard", mode);
462a10cf76eSAxel Dörfler 
463a10cf76eSAxel Dörfler 			fTVStandardMenu->AddItem(new BMenuItem(name.String(), message));
464a10cf76eSAxel Dörfler 		}
465a10cf76eSAxel Dörfler 
466df3f5bacSStephan Aßmus 		fTVStandardField = new BMenuField(rect, "tv standard", "Video Format:",
467a10cf76eSAxel Dörfler 			fTVStandardMenu, true);
468df3f5bacSStephan Aßmus 		fTVStandardField->SetAlignment(B_ALIGN_RIGHT);
469a10cf76eSAxel Dörfler 
470df3f5bacSStephan Aßmus 		if (!tvStandardSupport || i == 0) {
471df3f5bacSStephan Aßmus 			fTVStandardField->Hide();
472df3f5bacSStephan Aßmus 		} else {
473df3f5bacSStephan Aßmus 			controlsFlags |= SHOW_TV_STANDARD_FIELD;
474a10cf76eSAxel Dörfler 		}
475a10cf76eSAxel Dörfler 
476df3f5bacSStephan Aßmus 		fControlsBox->AddChild(fTVStandardField);
477df3f5bacSStephan Aßmus 	}
478df3f5bacSStephan Aßmus 
479df3f5bacSStephan Aßmus 	BRect buttonRect(0.0, 0.0, 30.0, 10.0);
480df3f5bacSStephan Aßmus 	fBackgroundsButton = new BButton(buttonRect, "BackgroundsButton",
481df3f5bacSStephan Aßmus 		"Set Background"B_UTF8_ELLIPSIS, new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG));
4823dfd20c0SStephan Aßmus 	fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9);
483df3f5bacSStephan Aßmus 	fScreenBox->AddChild(fBackgroundsButton);
484df3f5bacSStephan Aßmus 
485df3f5bacSStephan Aßmus 	fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults",
486a10cf76eSAxel Dörfler 		new BMessage(BUTTON_DEFAULTS_MSG));
487a10cf76eSAxel Dörfler 	view->AddChild(fDefaultsButton);
488a10cf76eSAxel Dörfler 
489df3f5bacSStephan Aßmus 	fRevertButton = new BButton(buttonRect, "RevertButton", "Revert",
490a10cf76eSAxel Dörfler 		new BMessage(BUTTON_REVERT_MSG));
491a10cf76eSAxel Dörfler 	fRevertButton->SetEnabled(false);
492a10cf76eSAxel Dörfler 	view->AddChild(fRevertButton);
493a10cf76eSAxel Dörfler 
494df3f5bacSStephan Aßmus 	fApplyButton = new BButton(buttonRect, "ApplyButton", "Apply",
495df3f5bacSStephan Aßmus 		new BMessage(BUTTON_APPLY_MSG));
496df3f5bacSStephan Aßmus 	fApplyButton->SetEnabled(false);
497df3f5bacSStephan Aßmus 	view->AddChild(fApplyButton);
4985a78744bSAxel Dörfler 
499a10cf76eSAxel Dörfler 	UpdateControls();
500df3f5bacSStephan Aßmus 
501df3f5bacSStephan Aßmus 	LayoutControls(controlsFlags);
502a10cf76eSAxel Dörfler }
503a10cf76eSAxel Dörfler 
504a10cf76eSAxel Dörfler 
505a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow()
506a10cf76eSAxel Dörfler {
507a10cf76eSAxel Dörfler 	delete fSettings;
508a10cf76eSAxel Dörfler }
509a10cf76eSAxel Dörfler 
510a10cf76eSAxel Dörfler 
511a10cf76eSAxel Dörfler bool
512a10cf76eSAxel Dörfler ScreenWindow::QuitRequested()
513a10cf76eSAxel Dörfler {
514a10cf76eSAxel Dörfler 	fSettings->SetWindowFrame(Frame());
51512580984SAxel Dörfler 	if (fVesaApplied) {
51612580984SAxel Dörfler 		status_t status = _WriteVesaModeFile(fSelected);
51712580984SAxel Dörfler 		if (status < B_OK) {
51812580984SAxel Dörfler 			BString warning = "Could not write VESA mode settings file:\n\t";
51912580984SAxel Dörfler 			warning << strerror(status);
52012580984SAxel Dörfler 			(new BAlert("VesaAlert", warning.String(), "Okay", NULL, NULL,
52112580984SAxel Dörfler 				B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
52212580984SAxel Dörfler 
52312580984SAxel Dörfler 		}
52412580984SAxel Dörfler 	}
52512580984SAxel Dörfler 
526a10cf76eSAxel Dörfler 	be_app->PostMessage(B_QUIT_REQUESTED);
527a10cf76eSAxel Dörfler 
528a10cf76eSAxel Dörfler 	return BWindow::QuitRequested();
529a10cf76eSAxel Dörfler }
530a10cf76eSAxel Dörfler 
531a10cf76eSAxel Dörfler 
532a10cf76eSAxel Dörfler /**	update resolution list according to combine mode
533a10cf76eSAxel Dörfler  *	(some resolution may not be combinable due to memory restrictions)
534a10cf76eSAxel Dörfler  */
535a10cf76eSAxel Dörfler 
536a10cf76eSAxel Dörfler void
537a10cf76eSAxel Dörfler ScreenWindow::CheckResolutionMenu()
538a10cf76eSAxel Dörfler {
539a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fResolutionMenu->CountItems(); i++)
540a10cf76eSAxel Dörfler 		fResolutionMenu->ItemAt(i)->SetEnabled(false);
541a10cf76eSAxel Dörfler 
542a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
543a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
544a10cf76eSAxel Dörfler 		if (mode.combine != fSelected.combine)
545a10cf76eSAxel Dörfler 			continue;
546a10cf76eSAxel Dörfler 
547a10cf76eSAxel Dörfler 		BString name;
548a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
549a10cf76eSAxel Dörfler 
550a10cf76eSAxel Dörfler 		BMenuItem *item = fResolutionMenu->FindItem(name.String());
551a10cf76eSAxel Dörfler 		if (item != NULL)
552a10cf76eSAxel Dörfler 			item->SetEnabled(true);
553a10cf76eSAxel Dörfler 	}
554a10cf76eSAxel Dörfler }
555a10cf76eSAxel Dörfler 
556a10cf76eSAxel Dörfler 
557a10cf76eSAxel Dörfler /**	update color and refresh options according to current mode
558a10cf76eSAxel Dörfler  *	(a color space is made active if there is any mode with
559a10cf76eSAxel Dörfler  *	given resolution and this colour space; same applies for
560a10cf76eSAxel Dörfler  *	refresh rate, though "Other…" is always possible)
561a10cf76eSAxel Dörfler  */
562a10cf76eSAxel Dörfler 
563a10cf76eSAxel Dörfler void
564a10cf76eSAxel Dörfler ScreenWindow::CheckColorMenu()
565a10cf76eSAxel Dörfler {
566a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
567a10cf76eSAxel Dörfler 		bool supported = false;
568a10cf76eSAxel Dörfler 
569a10cf76eSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
570a10cf76eSAxel Dörfler 			screen_mode mode = fScreenMode.ModeAt(j);
571a10cf76eSAxel Dörfler 
572a10cf76eSAxel Dörfler 			if (fSelected.width == mode.width
573a10cf76eSAxel Dörfler 				&& fSelected.height == mode.height
574a10cf76eSAxel Dörfler 				&& kColorSpaces[i].space == mode.space
575a10cf76eSAxel Dörfler 				&& fSelected.combine == mode.combine) {
576a10cf76eSAxel Dörfler 				supported = true;
577a10cf76eSAxel Dörfler 				break;
578a10cf76eSAxel Dörfler 			}
579a10cf76eSAxel Dörfler 		}
580a10cf76eSAxel Dörfler 
581a10cf76eSAxel Dörfler 		BMenuItem* item = fColorsMenu->ItemAt(i);
582a10cf76eSAxel Dörfler 		if (item)
583a10cf76eSAxel Dörfler 			item->SetEnabled(supported);
584a10cf76eSAxel Dörfler 	}
585a10cf76eSAxel Dörfler }
586a10cf76eSAxel Dörfler 
587a10cf76eSAxel Dörfler 
58829e8a73aSAxel Dörfler /**	Enable/disable refresh options according to current mode. */
589a10cf76eSAxel Dörfler 
590a10cf76eSAxel Dörfler void
591a10cf76eSAxel Dörfler ScreenWindow::CheckRefreshMenu()
592a10cf76eSAxel Dörfler {
59329e8a73aSAxel Dörfler 	float min, max;
59429e8a73aSAxel Dörfler 	if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max)
59529e8a73aSAxel Dörfler 		return;
596a10cf76eSAxel Dörfler 
59729e8a73aSAxel Dörfler 	for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) {
59829e8a73aSAxel Dörfler 		BMenuItem* item = fRefreshMenu->ItemAt(i);
59929e8a73aSAxel Dörfler 		BMessage* message = item->Message();
60029e8a73aSAxel Dörfler 		float refresh;
60129e8a73aSAxel Dörfler 		if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK)
60229e8a73aSAxel Dörfler 			item->SetEnabled(refresh >= min && refresh <= max);
603a10cf76eSAxel Dörfler 	}
604a10cf76eSAxel Dörfler }
605a10cf76eSAxel Dörfler 
606a10cf76eSAxel Dörfler 
60729e8a73aSAxel Dörfler /** Activate appropriate menu item according to selected refresh rate */
608a10cf76eSAxel Dörfler 
609a10cf76eSAxel Dörfler void
610a10cf76eSAxel Dörfler ScreenWindow::UpdateRefreshControl()
611a10cf76eSAxel Dörfler {
612a10cf76eSAxel Dörfler 	BString string;
613a10cf76eSAxel Dörfler 	refresh_rate_to_string(fSelected.refresh, string);
614a10cf76eSAxel Dörfler 
615a10cf76eSAxel Dörfler 	BMenuItem* item = fRefreshMenu->FindItem(string.String());
616a10cf76eSAxel Dörfler 	if (item) {
617a10cf76eSAxel Dörfler 		if (!item->IsMarked())
618a10cf76eSAxel Dörfler 			item->SetMarked(true);
61929e8a73aSAxel Dörfler 
620a10cf76eSAxel Dörfler 		// "Other…" items only contains a refresh rate when active
621a10cf76eSAxel Dörfler 		fOtherRefresh->SetLabel("Other…");
622a10cf76eSAxel Dörfler 		return;
623a10cf76eSAxel Dörfler 	}
624a10cf76eSAxel Dörfler 
625a10cf76eSAxel Dörfler 	// this is a non-standard refresh rate
626a10cf76eSAxel Dörfler 
627a10cf76eSAxel Dörfler 	fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh);
628a10cf76eSAxel Dörfler 	fOtherRefresh->SetMarked(true);
629a10cf76eSAxel Dörfler 
630a10cf76eSAxel Dörfler 	fRefreshMenu->Superitem()->SetLabel(string.String());
631a10cf76eSAxel Dörfler 
632a10cf76eSAxel Dörfler 	string.Append("/Other" B_UTF8_ELLIPSIS);
633a10cf76eSAxel Dörfler 	fOtherRefresh->SetLabel(string.String());
634a10cf76eSAxel Dörfler }
635a10cf76eSAxel Dörfler 
636a10cf76eSAxel Dörfler 
637a10cf76eSAxel Dörfler void
638a10cf76eSAxel Dörfler ScreenWindow::UpdateMonitorView()
639a10cf76eSAxel Dörfler {
640a10cf76eSAxel Dörfler 	BMessage updateMessage(UPDATE_DESKTOP_MSG);
641a10cf76eSAxel Dörfler 	updateMessage.AddInt32("width", fSelected.width);
642a10cf76eSAxel Dörfler 	updateMessage.AddInt32("height", fSelected.height);
643a10cf76eSAxel Dörfler 
644a10cf76eSAxel Dörfler 	PostMessage(&updateMessage, fMonitorView);
645a10cf76eSAxel Dörfler }
646a10cf76eSAxel Dörfler 
647a10cf76eSAxel Dörfler 
648a10cf76eSAxel Dörfler void
649a10cf76eSAxel Dörfler ScreenWindow::UpdateControls()
650a10cf76eSAxel Dörfler {
651a10cf76eSAxel Dörfler 	BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays);
652a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
653a10cf76eSAxel Dörfler 		item->SetMarked(true);
654a10cf76eSAxel Dörfler 
655a10cf76eSAxel Dörfler 	item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel);
656a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
657a10cf76eSAxel Dörfler 		item->SetMarked(true);
658a10cf76eSAxel Dörfler 
659a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) {
660a10cf76eSAxel Dörfler 		item = fTVStandardMenu->ItemAt(i);
661a10cf76eSAxel Dörfler 
662a10cf76eSAxel Dörfler 		uint32 tvStandard;
663a10cf76eSAxel Dörfler 		item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard);
664a10cf76eSAxel Dörfler 		if (tvStandard == fSelected.tv_standard) {
665a10cf76eSAxel Dörfler 			if (!item->IsMarked())
666a10cf76eSAxel Dörfler 				item->SetMarked(true);
667a10cf76eSAxel Dörfler 			break;
668a10cf76eSAxel Dörfler 		}
669a10cf76eSAxel Dörfler 	}
670a10cf76eSAxel Dörfler 
671a10cf76eSAxel Dörfler 	CheckResolutionMenu();
672a10cf76eSAxel Dörfler 	CheckColorMenu();
673a10cf76eSAxel Dörfler 	CheckRefreshMenu();
674a10cf76eSAxel Dörfler 
675a10cf76eSAxel Dörfler 	BString string;
676a10cf76eSAxel Dörfler 	resolution_to_string(fSelected, string);
677a10cf76eSAxel Dörfler 	item = fResolutionMenu->FindItem(string.String());
678a10cf76eSAxel Dörfler 
679a10cf76eSAxel Dörfler 	if (item != NULL) {
680a10cf76eSAxel Dörfler 		if (!item->IsMarked())
681a10cf76eSAxel Dörfler 			item->SetMarked(true);
682a10cf76eSAxel Dörfler 	} else {
683a10cf76eSAxel Dörfler 		// this is bad luck - if mode has been set via screen references,
684a10cf76eSAxel Dörfler 		// this case cannot occur; there are three possible solutions:
685a10cf76eSAxel Dörfler 		// 1. add a new resolution to list
686a10cf76eSAxel Dörfler 		//    - we had to remove it as soon as a "valid" one is selected
687a10cf76eSAxel Dörfler 		//    - we don't know which frequencies/bit depths are supported
688a10cf76eSAxel Dörfler 		//    - as long as we haven't the GMT formula to create
689a10cf76eSAxel Dörfler 		//      parameters for any resolution given, we cannot
690a10cf76eSAxel Dörfler 		//      really set current mode - it's just not in the list
691a10cf76eSAxel Dörfler 		// 2. choose nearest resolution
692a10cf76eSAxel Dörfler 		//    - probably a good idea, but implies coding and testing
693a10cf76eSAxel Dörfler 		// 3. choose lowest resolution
694a10cf76eSAxel Dörfler 		//    - do you really think we are so lazy? yes, we are
695a10cf76eSAxel Dörfler 		item = fResolutionMenu->ItemAt(0);
696a10cf76eSAxel Dörfler 		if (item)
697a10cf76eSAxel Dörfler 			item->SetMarked(true);
698a10cf76eSAxel Dörfler 
699a10cf76eSAxel Dörfler 		// okay - at least we set menu label to active resolution
700a10cf76eSAxel Dörfler 		fResolutionMenu->Superitem()->SetLabel(string.String());
701a10cf76eSAxel Dörfler 	}
702a10cf76eSAxel Dörfler 
703a10cf76eSAxel Dörfler 	// mark active combine mode
704a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kCombineModeCount; i++) {
705a10cf76eSAxel Dörfler 		if (kCombineModes[i].mode == fSelected.combine) {
706a10cf76eSAxel Dörfler 			item = fCombineMenu->ItemAt(i);
707a10cf76eSAxel Dörfler 			if (item && !item->IsMarked())
708a10cf76eSAxel Dörfler 				item->SetMarked(true);
709a10cf76eSAxel Dörfler 			break;
710a10cf76eSAxel Dörfler 		}
711a10cf76eSAxel Dörfler 	}
712a10cf76eSAxel Dörfler 
713a10cf76eSAxel Dörfler 	item = fColorsMenu->ItemAt(0);
714a10cf76eSAxel Dörfler 
715a10cf76eSAxel Dörfler 	for (int32 i = kColorSpaceCount; i-- > 0;) {
716a10cf76eSAxel Dörfler 		if (kColorSpaces[i].space == fSelected.space) {
717a10cf76eSAxel Dörfler 			item = fColorsMenu->ItemAt(i);
718a10cf76eSAxel Dörfler 			break;
719a10cf76eSAxel Dörfler 		}
720a10cf76eSAxel Dörfler 	}
721a10cf76eSAxel Dörfler 
722a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
723a10cf76eSAxel Dörfler 		item->SetMarked(true);
724a10cf76eSAxel Dörfler 
725a10cf76eSAxel Dörfler 	string.Truncate(0);
726a10cf76eSAxel Dörfler 	string << fSelected.BitsPerPixel() << " Bits/Pixel";
727a10cf76eSAxel Dörfler 	if (string != fColorsMenu->Superitem()->Label())
728a10cf76eSAxel Dörfler 		fColorsMenu->Superitem()->SetLabel(string.String());
729a10cf76eSAxel Dörfler 
730a10cf76eSAxel Dörfler 	UpdateMonitorView();
731a10cf76eSAxel Dörfler 	UpdateRefreshControl();
732a10cf76eSAxel Dörfler 
733a10cf76eSAxel Dörfler 	CheckApplyEnabled();
734a10cf76eSAxel Dörfler }
735a10cf76eSAxel Dörfler 
736a10cf76eSAxel Dörfler 
73712580984SAxel Dörfler /*! Reflect active mode in chosen settings */
738a10cf76eSAxel Dörfler void
739a10cf76eSAxel Dörfler ScreenWindow::UpdateActiveMode()
740a10cf76eSAxel Dörfler {
74112580984SAxel Dörfler 	// Usually, this function gets called after a mode
742a10cf76eSAxel Dörfler 	// has been set manually; still, as the graphics driver
743a10cf76eSAxel Dörfler 	// is free to fiddle with mode passed, we better ask
744a10cf76eSAxel Dörfler 	// what kind of mode we actually got
74512580984SAxel Dörfler 	if (!fVesaApplied)
746a10cf76eSAxel Dörfler 		fScreenMode.Get(fActive);
747a10cf76eSAxel Dörfler 	fSelected = fActive;
748a10cf76eSAxel Dörfler 
749a10cf76eSAxel Dörfler 	UpdateControls();
750a10cf76eSAxel Dörfler }
751a10cf76eSAxel Dörfler 
752a10cf76eSAxel Dörfler 
753a10cf76eSAxel 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 {
768a10cf76eSAxel Dörfler 	if (fChangingAllWorkspaces) {
769a10cf76eSAxel Dörfler 		// we're currently changing all workspaces, so there is no need
770a10cf76eSAxel Dörfler 		// to update the interface
771a10cf76eSAxel Dörfler 		return;
772a10cf76eSAxel Dörfler 	}
773a10cf76eSAxel Dörfler 
774a10cf76eSAxel Dörfler 	fScreenMode.Get(fOriginal);
775a10cf76eSAxel Dörfler 	fScreenMode.UpdateOriginalMode();
776a10cf76eSAxel Dörfler 
777a10cf76eSAxel Dörfler 	// only override current settings if they have not been changed yet
778a10cf76eSAxel Dörfler 	if (fSelected == fActive)
779a10cf76eSAxel Dörfler 		UpdateActiveMode();
780a10cf76eSAxel Dörfler 
7816edaa0f6SStefano Ceccherini 	BMessage message(UPDATE_DESKTOP_COLOR_MSG);
7826edaa0f6SStefano Ceccherini 	PostMessage(&message, fMonitorView);
783a10cf76eSAxel Dörfler }
784a10cf76eSAxel Dörfler 
785a10cf76eSAxel Dörfler 
786a10cf76eSAxel Dörfler void
787a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message)
788a10cf76eSAxel Dörfler {
789a10cf76eSAxel Dörfler 	switch (message->what) {
790a10cf76eSAxel Dörfler 		case WORKSPACE_CHECK_MSG:
791a10cf76eSAxel Dörfler 			CheckApplyEnabled();
792a10cf76eSAxel Dörfler 			break;
793a10cf76eSAxel Dörfler 
794a10cf76eSAxel Dörfler 		case POP_WORKSPACE_CHANGED_MSG:
795a10cf76eSAxel Dörfler 		{
796a10cf76eSAxel Dörfler 			int32 index;
797a10cf76eSAxel Dörfler 			if (message->FindInt32("index", &index) == B_OK)
798a10cf76eSAxel Dörfler 				set_workspace_count(index + 1);
799a10cf76eSAxel Dörfler 			break;
800a10cf76eSAxel Dörfler 		}
801a10cf76eSAxel Dörfler 
802a10cf76eSAxel Dörfler 		case POP_RESOLUTION_MSG:
803a10cf76eSAxel Dörfler 		{
804a40498e2SWaldemar Kornewald 			int32 oldWidth = fSelected.width, oldHeight = fSelected.height;
805a10cf76eSAxel Dörfler 			message->FindInt32("width", &fSelected.width);
806a10cf76eSAxel Dörfler 			message->FindInt32("height", &fSelected.height);
807a40498e2SWaldemar Kornewald 			if (fSelected.width == oldWidth && fSelected.height == oldHeight)
808a40498e2SWaldemar Kornewald 				break;
809a10cf76eSAxel Dörfler 
810a10cf76eSAxel Dörfler 			CheckColorMenu();
811a10cf76eSAxel Dörfler 			CheckRefreshMenu();
812a10cf76eSAxel Dörfler 
813a10cf76eSAxel Dörfler 			UpdateMonitorView();
814a10cf76eSAxel Dörfler 			UpdateRefreshControl();
815a10cf76eSAxel Dörfler 
816a40498e2SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
817a40498e2SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
818a10cf76eSAxel Dörfler 			CheckApplyEnabled();
819a10cf76eSAxel Dörfler 			break;
820a10cf76eSAxel Dörfler 		}
821a10cf76eSAxel Dörfler 
822a10cf76eSAxel Dörfler 		case POP_COLORS_MSG:
823a10cf76eSAxel Dörfler 		{
824a40498e2SWaldemar Kornewald 			color_space old = fSelected.space;
825a10cf76eSAxel Dörfler 			message->FindInt32("space", (int32 *)&fSelected.space);
826a40498e2SWaldemar Kornewald 			if (fSelected.space == old)
827a40498e2SWaldemar Kornewald 				break;
828a10cf76eSAxel Dörfler 
829a10cf76eSAxel Dörfler 			BString string;
830a10cf76eSAxel Dörfler 			string << fSelected.BitsPerPixel() << " Bits/Pixel";
831a10cf76eSAxel Dörfler 			fColorsMenu->Superitem()->SetLabel(string.String());
832a10cf76eSAxel Dörfler 
833a40498e2SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
834a40498e2SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
835a10cf76eSAxel Dörfler 			CheckApplyEnabled();
836a10cf76eSAxel Dörfler 			break;
837a10cf76eSAxel Dörfler 		}
838a10cf76eSAxel Dörfler 
839a10cf76eSAxel Dörfler 		case POP_REFRESH_MSG:
840a40498e2SWaldemar Kornewald 		{
841a40498e2SWaldemar Kornewald 			float old = fSelected.refresh;
842a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
843a10cf76eSAxel Dörfler 			fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS);
844a10cf76eSAxel Dörfler 				// revert "Other…" label - it might have had a refresh rate prefix
845a10cf76eSAxel Dörfler 
846a40498e2SWaldemar Kornewald 			if (fSelected.refresh == old)
847a40498e2SWaldemar Kornewald 				break;
848a40498e2SWaldemar Kornewald 
849a40498e2SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
850a40498e2SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
851a10cf76eSAxel Dörfler 			CheckApplyEnabled();
852a10cf76eSAxel Dörfler 			break;
853a40498e2SWaldemar Kornewald 		}
854a10cf76eSAxel Dörfler 
855a10cf76eSAxel Dörfler 		case POP_OTHER_REFRESH_MSG:
856a10cf76eSAxel Dörfler 		{
85729e8a73aSAxel Dörfler 			// make sure menu shows something useful
858a10cf76eSAxel Dörfler 			UpdateRefreshControl();
859a10cf76eSAxel Dörfler 
86029e8a73aSAxel Dörfler 			float min = 0, max = 999;
86129e8a73aSAxel Dörfler 			fScreenMode.GetRefreshLimits(fSelected, min, max);
86229e8a73aSAxel Dörfler 			if (min < gMinRefresh)
86329e8a73aSAxel Dörfler 				min = gMinRefresh;
86429e8a73aSAxel Dörfler 			if (max > gMaxRefresh)
86529e8a73aSAxel Dörfler 				max = gMaxRefresh;
86629e8a73aSAxel Dörfler 
867c5d10f7aSAxel Dörfler 			RefreshWindow *fRefreshWindow = new RefreshWindow(
868c5d10f7aSAxel Dörfler 				fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, min, max);
869a10cf76eSAxel Dörfler 			fRefreshWindow->Show();
870a10cf76eSAxel Dörfler 			break;
871a10cf76eSAxel Dörfler 		}
872a10cf76eSAxel Dörfler 
873a10cf76eSAxel Dörfler 		case SET_CUSTOM_REFRESH_MSG:
874a10cf76eSAxel Dörfler 		{
875a10cf76eSAxel Dörfler 			// user pressed "done" in "Other…" refresh dialog;
876a10cf76eSAxel Dörfler 			// select the refresh rate chosen
877a40498e2SWaldemar Kornewald 			float old = fSelected.refresh;
878a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
879a40498e2SWaldemar Kornewald 			if (fSelected.refresh != old)
880a40498e2SWaldemar Kornewald 				break;
881a10cf76eSAxel Dörfler 
882a40498e2SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
883a40498e2SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
884a10cf76eSAxel Dörfler 			UpdateRefreshControl();
885a10cf76eSAxel Dörfler 			CheckApplyEnabled();
886a10cf76eSAxel Dörfler 			break;
887a10cf76eSAxel Dörfler 		}
888a10cf76eSAxel Dörfler 
889a10cf76eSAxel Dörfler 		case POP_COMBINE_DISPLAYS_MSG:
890a10cf76eSAxel Dörfler 		{
891a10cf76eSAxel Dörfler 			// new combine mode has bee chosen
892a10cf76eSAxel Dörfler 			int32 mode;
893a10cf76eSAxel Dörfler 			if (message->FindInt32("mode", &mode) == B_OK)
894a10cf76eSAxel Dörfler 				fSelected.combine = (combine_mode)mode;
895a10cf76eSAxel Dörfler 
896*4be51fe3SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
897*4be51fe3SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
898a10cf76eSAxel Dörfler 			CheckResolutionMenu();
899a10cf76eSAxel Dörfler 			CheckApplyEnabled();
900a10cf76eSAxel Dörfler 			break;
901a10cf76eSAxel Dörfler 		}
902a10cf76eSAxel Dörfler 
903a10cf76eSAxel Dörfler 		case POP_SWAP_DISPLAYS_MSG:
904a10cf76eSAxel Dörfler 			message->FindBool("swap", &fSelected.swap_displays);
905*4be51fe3SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
906*4be51fe3SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
907a10cf76eSAxel Dörfler 			CheckApplyEnabled();
908a10cf76eSAxel Dörfler 			break;
909a10cf76eSAxel Dörfler 
910a10cf76eSAxel Dörfler 		case POP_USE_LAPTOP_PANEL_MSG:
911a10cf76eSAxel Dörfler 			message->FindBool("use", &fSelected.use_laptop_panel);
912*4be51fe3SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
913*4be51fe3SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
914a10cf76eSAxel Dörfler 			CheckApplyEnabled();
915a10cf76eSAxel Dörfler 			break;
916a10cf76eSAxel Dörfler 
917a10cf76eSAxel Dörfler 		case POP_TV_STANDARD_MSG:
918a10cf76eSAxel Dörfler 			message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard);
919*4be51fe3SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
920*4be51fe3SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
921a10cf76eSAxel Dörfler 			CheckApplyEnabled();
922a10cf76eSAxel Dörfler 			break;
923a10cf76eSAxel Dörfler 
924df3f5bacSStephan Aßmus 		case BUTTON_LAUNCH_BACKGROUNDS_MSG:
9256f095d6aSRyan Leavengood 			if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) {
9266f095d6aSRyan Leavengood 				app_info info;
9276f095d6aSRyan Leavengood 				be_roster->GetAppInfo(kBackgroundsSignature, &info);
9286f095d6aSRyan Leavengood 				be_roster->ActivateApp(info.team);
9296f095d6aSRyan Leavengood 			}
930df3f5bacSStephan Aßmus 			break;
931df3f5bacSStephan Aßmus 
932a10cf76eSAxel Dörfler 		case BUTTON_DEFAULTS_MSG:
933a10cf76eSAxel Dörfler 		{
934*4be51fe3SWaldemar Kornewald 			// TODO: get preferred settings of screen
935a10cf76eSAxel Dörfler 			fSelected.width = 640;
936a10cf76eSAxel Dörfler 			fSelected.height = 480;
937a10cf76eSAxel Dörfler 			fSelected.space = B_CMAP8;
938a10cf76eSAxel Dörfler 			fSelected.refresh = 60.0;
939a10cf76eSAxel Dörfler 			fSelected.combine = kCombineDisable;
940a10cf76eSAxel Dörfler 			fSelected.swap_displays = false;
941a10cf76eSAxel Dörfler 			fSelected.use_laptop_panel = false;
942a10cf76eSAxel Dörfler 			fSelected.tv_standard = 0;
943a10cf76eSAxel Dörfler 
944a40498e2SWaldemar Kornewald 			fScreenMode.Get(fOriginal);
945a40498e2SWaldemar Kornewald 			fScreenMode.UpdateOriginalMode();
946a10cf76eSAxel Dörfler 			UpdateControls();
947a10cf76eSAxel Dörfler 			break;
948a10cf76eSAxel Dörfler 		}
949a10cf76eSAxel Dörfler 
950a10cf76eSAxel Dörfler 		case BUTTON_REVERT_MSG:
951a10cf76eSAxel Dörfler 		case SET_INITIAL_MODE_MSG:
952a10cf76eSAxel Dörfler 			fScreenMode.Revert();
953a10cf76eSAxel Dörfler 			UpdateActiveMode();
954a10cf76eSAxel Dörfler 			break;
955a10cf76eSAxel Dörfler 
956a10cf76eSAxel Dörfler 		case BUTTON_APPLY_MSG:
957a10cf76eSAxel Dörfler 			Apply();
958a10cf76eSAxel Dörfler 			break;
959a10cf76eSAxel Dörfler 
960a10cf76eSAxel Dörfler 		case MAKE_INITIAL_MSG: {
961a10cf76eSAxel Dörfler 			// user pressed "keep" in confirmation box;
962a10cf76eSAxel Dörfler 			// select this mode in dialog and mark it as
963a10cf76eSAxel Dörfler 			// previous mode; if "all workspaces" is selected,
964a10cf76eSAxel Dörfler 			// distribute mode to all workspaces
965a10cf76eSAxel Dörfler 
966a10cf76eSAxel Dörfler 			// use the mode that has eventually been set and
967a10cf76eSAxel Dörfler 			// thus we know to be working; it can differ from
968a10cf76eSAxel Dörfler 			// the mode selected by user due to hardware limitation
969a10cf76eSAxel Dörfler 			display_mode newMode;
970a10cf76eSAxel Dörfler 			BScreen screen(this);
971a10cf76eSAxel Dörfler 			screen.GetMode(&newMode);
972a10cf76eSAxel Dörfler 
973a10cf76eSAxel Dörfler 			if (fAllWorkspacesItem->IsMarked()) {
974a10cf76eSAxel Dörfler 				int32 originatingWorkspace;
975a10cf76eSAxel Dörfler 
976a10cf76eSAxel Dörfler 				// the original panel activates each workspace in turn;
977a10cf76eSAxel Dörfler 				// this is disguisting and there is a SetMode
978a10cf76eSAxel Dörfler 				// variant that accepts a workspace id, so let's take
979a10cf76eSAxel Dörfler 				// this one
980a10cf76eSAxel Dörfler 				originatingWorkspace = current_workspace();
981a10cf76eSAxel Dörfler 
982a10cf76eSAxel Dörfler 				// well, this "cannot be reverted" message is not
983a10cf76eSAxel Dörfler 				// entirely true - at least, you can revert it
984a10cf76eSAxel Dörfler 				// for current workspace; to not overwrite original
985a10cf76eSAxel Dörfler 				// mode during workspace switch, we use this flag
986a10cf76eSAxel Dörfler 				fChangingAllWorkspaces = true;
987a10cf76eSAxel Dörfler 
988a10cf76eSAxel Dörfler 				for (int32 i = 0; i < count_workspaces(); i++) {
989a10cf76eSAxel Dörfler 					if (i != originatingWorkspace)
990a10cf76eSAxel Dörfler 						screen.SetMode(i, &newMode, true);
991a10cf76eSAxel Dörfler 				}
992a10cf76eSAxel Dörfler 
993a10cf76eSAxel Dörfler 				fChangingAllWorkspaces = false;
994a10cf76eSAxel Dörfler 			}
995a10cf76eSAxel Dörfler 
996a10cf76eSAxel Dörfler 			UpdateActiveMode();
997a10cf76eSAxel Dörfler 			break;
998a10cf76eSAxel Dörfler 		}
999a10cf76eSAxel Dörfler 
1000a10cf76eSAxel Dörfler 		default:
1001a10cf76eSAxel Dörfler 			BWindow::MessageReceived(message);
1002a10cf76eSAxel Dörfler 			break;
1003a10cf76eSAxel Dörfler 	}
1004a10cf76eSAxel Dörfler }
1005a10cf76eSAxel Dörfler 
1006a10cf76eSAxel Dörfler 
100712580984SAxel Dörfler status_t
100812580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const
100912580984SAxel Dörfler {
101012580984SAxel Dörfler 	BPath path;
101112580984SAxel Dörfler 	status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
101212580984SAxel Dörfler 	if (status < B_OK)
101312580984SAxel Dörfler 		return status;
101412580984SAxel Dörfler 
101512580984SAxel Dörfler 	path.Append("kernel/drivers");
101612580984SAxel Dörfler 	status = create_directory(path.Path(), 0755);
101712580984SAxel Dörfler 	if (status < B_OK)
101812580984SAxel Dörfler 		return status;
101912580984SAxel Dörfler 
102012580984SAxel Dörfler 	path.Append("vesa");
102112580984SAxel Dörfler 	BFile file;
102212580984SAxel Dörfler 	status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
102312580984SAxel Dörfler 	if (status < B_OK)
102412580984SAxel Dörfler 		return status;
102512580984SAxel Dörfler 
102612580984SAxel Dörfler 	char buffer[256];
102712580984SAxel Dörfler 	snprintf(buffer, sizeof(buffer), "mode %ld %ld %ld\n",
102812580984SAxel Dörfler 		mode.width, mode.height, mode.BitsPerPixel());
102912580984SAxel Dörfler 
103012580984SAxel Dörfler 	ssize_t bytesWritten = file.Write(buffer, strlen(buffer));
103112580984SAxel Dörfler 	if (bytesWritten < B_OK)
103212580984SAxel Dörfler 		return bytesWritten;
103312580984SAxel Dörfler 
103412580984SAxel Dörfler 	return B_OK;
103512580984SAxel Dörfler }
103612580984SAxel Dörfler 
103712580984SAxel Dörfler 
1038a10cf76eSAxel Dörfler bool
1039a10cf76eSAxel Dörfler ScreenWindow::CanApply() const
1040a10cf76eSAxel Dörfler {
1041894deb54SWaldemar Kornewald 	return fAllWorkspacesItem->IsMarked() || fSelected != fActive;
1042a10cf76eSAxel Dörfler }
1043a10cf76eSAxel Dörfler 
1044a10cf76eSAxel Dörfler 
1045a10cf76eSAxel Dörfler bool
1046a10cf76eSAxel Dörfler ScreenWindow::CanRevert() const
1047a10cf76eSAxel Dörfler {
1048a40498e2SWaldemar Kornewald 	return (fActive != fOriginal && !fAllWorkspacesItem->IsMarked())
1049a40498e2SWaldemar Kornewald 			|| fSelected != fActive;
1050a10cf76eSAxel Dörfler }
1051a10cf76eSAxel Dörfler 
1052a10cf76eSAxel Dörfler 
1053a10cf76eSAxel Dörfler void
1054a10cf76eSAxel Dörfler ScreenWindow::CheckApplyEnabled()
1055a10cf76eSAxel Dörfler {
1056a10cf76eSAxel Dörfler 	fApplyButton->SetEnabled(CanApply());
1057a10cf76eSAxel Dörfler 	fRevertButton->SetEnabled(CanRevert());
1058a10cf76eSAxel Dörfler }
1059a10cf76eSAxel Dörfler 
1060a10cf76eSAxel Dörfler 
1061a10cf76eSAxel Dörfler void
1062a10cf76eSAxel Dörfler ScreenWindow::Apply()
1063a10cf76eSAxel Dörfler {
106412580984SAxel Dörfler 	if (_IsVesa()) {
106512580984SAxel Dörfler 		(new BAlert("VesaAlert",
106612580984SAxel Dörfler 			"Your graphics card is not supported. Resolution changes will be "
106712580984SAxel Dörfler 			"adopted on next system startup.\n", "Okay", NULL, NULL, B_WIDTH_AS_USUAL,
106812580984SAxel Dörfler 			B_INFO_ALERT))->Go(NULL);
106912580984SAxel Dörfler 
107012580984SAxel Dörfler 		fVesaApplied = true;
107112580984SAxel Dörfler 		fActive = fSelected;
107212580984SAxel Dörfler 		return;
107312580984SAxel Dörfler 	}
107412580984SAxel Dörfler 
1075a10cf76eSAxel Dörfler 	if (fAllWorkspacesItem->IsMarked()) {
1076a10cf76eSAxel Dörfler 		BAlert *workspacesAlert = new BAlert("WorkspacesAlert",
1077a10cf76eSAxel Dörfler 			"Change all workspaces? This action cannot be reverted.", "Okay", "Cancel",
1078a10cf76eSAxel Dörfler 			NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
1079a10cf76eSAxel Dörfler 
1080a10cf76eSAxel Dörfler 		if (workspacesAlert->Go() == 1)
1081a10cf76eSAxel Dörfler 			return;
1082a10cf76eSAxel Dörfler 	}
1083a10cf76eSAxel Dörfler 
108407184a9eSAxel Dörfler 	status_t status = fScreenMode.Set(fSelected);
108507184a9eSAxel Dörfler 	if (status == B_OK) {
1086a10cf76eSAxel Dörfler 		fActive = fSelected;
1087a10cf76eSAxel Dörfler 
1088a10cf76eSAxel Dörfler 		// ToDo: only show alert when this is an unknown mode
1089a10cf76eSAxel Dörfler 		BWindow* window = new AlertWindow(this);
1090a10cf76eSAxel Dörfler 		window->Show();
109107184a9eSAxel Dörfler 	} else {
109207184a9eSAxel Dörfler 		char message[256];
109307184a9eSAxel Dörfler 		snprintf(message, sizeof(message),
109407184a9eSAxel Dörfler 			"The screen mode could not be set:\n\t%s\n", screen_errors(status));
109507184a9eSAxel Dörfler 		BAlert* alert = new BAlert("Screen Alert", message, "Okay", NULL, NULL,
109607184a9eSAxel Dörfler 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
109707184a9eSAxel Dörfler 		alert->Go();
1098a10cf76eSAxel Dörfler 	}
109907184a9eSAxel Dörfler }
110007184a9eSAxel Dörfler 
1101df3f5bacSStephan Aßmus 
1102df3f5bacSStephan Aßmus void
1103df3f5bacSStephan Aßmus ScreenWindow::LayoutControls(uint32 flags)
1104df3f5bacSStephan Aßmus {
1105df3f5bacSStephan Aßmus 	// layout the screen box and its controls
1106df3f5bacSStephan Aßmus 	fWorkspaceCountField->ResizeToPreferred();
1107df3f5bacSStephan Aßmus 
1108df3f5bacSStephan Aßmus 	float monitorViewHeight = fMonitorView->Bounds().Height();
1109df3f5bacSStephan Aßmus 	float workspaceFieldHeight = fWorkspaceCountField->Bounds().Height();
1110df3f5bacSStephan Aßmus 	float backgroundsButtonHeight = fBackgroundsButton->Bounds().Height();
1111df3f5bacSStephan Aßmus 
1112df3f5bacSStephan Aßmus 	float screenBoxWidth = fWorkspaceCountField->Bounds().Width() + 20.0;
1113df3f5bacSStephan Aßmus 	float screenBoxHeight = monitorViewHeight + 5.0
1114df3f5bacSStephan Aßmus 							+ workspaceFieldHeight + 5.0
1115df3f5bacSStephan Aßmus 							+ backgroundsButtonHeight
1116df3f5bacSStephan Aßmus 							+ 20.0;
1117df3f5bacSStephan Aßmus 
111829e8a73aSAxel Dörfler #ifdef __HAIKU__
1119df3f5bacSStephan Aßmus 	fScreenBox->MoveTo(10.0, 10.0 + fControlsBox->TopBorderOffset());
112029e8a73aSAxel Dörfler #else
112129e8a73aSAxel Dörfler 	fScreenBox->MoveTo(10.0, 10.0 + 3);
112229e8a73aSAxel Dörfler #endif
1123df3f5bacSStephan Aßmus 	fScreenBox->ResizeTo(screenBoxWidth, screenBoxHeight);
1124df3f5bacSStephan Aßmus 
1125df3f5bacSStephan Aßmus 	float leftOffset = 10.0;
1126df3f5bacSStephan Aßmus 	float topOffset = 10.0;
1127df3f5bacSStephan Aßmus 	fMonitorView->MoveTo(leftOffset, topOffset);
1128df3f5bacSStephan Aßmus 	fMonitorView->ResizeTo(screenBoxWidth - 20.0, monitorViewHeight);
1129df3f5bacSStephan Aßmus 	fMonitorView->SetResizingMode(B_FOLLOW_ALL);
1130df3f5bacSStephan Aßmus 	topOffset += monitorViewHeight + 5.0;
1131df3f5bacSStephan Aßmus 
1132df3f5bacSStephan Aßmus 	fWorkspaceCountField->MoveTo(leftOffset, topOffset);
1133df3f5bacSStephan Aßmus 	fWorkspaceCountField->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
1134df3f5bacSStephan Aßmus 	topOffset += workspaceFieldHeight + 5.0;
1135df3f5bacSStephan Aßmus 
1136df3f5bacSStephan Aßmus 	fBackgroundsButton->MoveTo(leftOffset, topOffset);
1137df3f5bacSStephan Aßmus 	fBackgroundsButton->ResizeTo(screenBoxWidth - 20.0, backgroundsButtonHeight);
1138df3f5bacSStephan Aßmus 	fBackgroundsButton->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
1139df3f5bacSStephan Aßmus 
1140df3f5bacSStephan Aßmus 	fControlsBox->MoveTo(fScreenBox->Frame().right + 10.0, 10.0);
1141df3f5bacSStephan Aßmus 
1142df3f5bacSStephan Aßmus 	// layout the right side
1143df3f5bacSStephan Aßmus 	BRect controlsRect = LayoutMenuFields(flags);
1144df3f5bacSStephan Aßmus 	controlsRect.InsetBy(-10.0, -10.0);
1145df3f5bacSStephan Aßmus 	// adjust size of controls box and move aligned buttons along
1146df3f5bacSStephan Aßmus 	float xDiff = controlsRect.right - fControlsBox->Bounds().right;
1147df3f5bacSStephan Aßmus 	float yDiff = controlsRect.bottom - fControlsBox->Bounds().bottom;
1148df3f5bacSStephan Aßmus 	if (yDiff < 0.0) {
1149df3f5bacSStephan Aßmus 		// don't shrink vertically
1150df3f5bacSStephan Aßmus 		yDiff = 0.0;
1151df3f5bacSStephan Aßmus 	}
1152df3f5bacSStephan Aßmus 
1153df3f5bacSStephan Aßmus 	fControlsBox->ResizeBy(xDiff, yDiff);
1154df3f5bacSStephan Aßmus 
1155df3f5bacSStephan Aßmus 	// align bottom of boxen
1156df3f5bacSStephan Aßmus 	float boxBottomDiff = fControlsBox->Frame().bottom - fScreenBox->Frame().bottom;
1157df3f5bacSStephan Aßmus 	if (boxBottomDiff > 0)
1158df3f5bacSStephan Aßmus 		fScreenBox->ResizeBy(0.0, boxBottomDiff);
1159df3f5bacSStephan Aßmus 	else
1160df3f5bacSStephan Aßmus 		fControlsBox->ResizeBy(0.0, -boxBottomDiff);
1161df3f5bacSStephan Aßmus 
1162df3f5bacSStephan Aßmus 	BRect boxFrame = fScreenBox->Frame() | fControlsBox->Frame();
1163df3f5bacSStephan Aßmus 
1164df3f5bacSStephan Aßmus 	// layout rest of buttons
1165df3f5bacSStephan Aßmus 	fDefaultsButton->ResizeToPreferred();
1166df3f5bacSStephan Aßmus 	fDefaultsButton->MoveTo(boxFrame.left, boxFrame.bottom + 8);
1167df3f5bacSStephan Aßmus 
1168df3f5bacSStephan Aßmus 	fRevertButton->ResizeToPreferred();
1169df3f5bacSStephan Aßmus 	fRevertButton->MoveTo(fDefaultsButton->Frame().right + 10,
1170df3f5bacSStephan Aßmus 						  fDefaultsButton->Frame().top);
1171df3f5bacSStephan Aßmus 
1172df3f5bacSStephan Aßmus 	fApplyButton->ResizeToPreferred();
1173df3f5bacSStephan Aßmus 	fApplyButton->MoveTo(boxFrame.right - fApplyButton->Bounds().Width(),
1174df3f5bacSStephan Aßmus 						 fDefaultsButton->Frame().top);
1175df3f5bacSStephan Aßmus 
1176df3f5bacSStephan Aßmus 	ResizeTo(boxFrame.right + 10, fDefaultsButton->Frame().bottom + 10);
1177df3f5bacSStephan Aßmus }
1178df3f5bacSStephan Aßmus 
1179df3f5bacSStephan Aßmus 
1180df3f5bacSStephan Aßmus BRect
1181df3f5bacSStephan Aßmus ScreenWindow::LayoutMenuFields(uint32 flags, bool sideBySide)
1182df3f5bacSStephan Aßmus {
1183df3f5bacSStephan Aßmus 	BList menuFields;
1184df3f5bacSStephan Aßmus 	menuFields.AddItem((void*)fResolutionField);
1185df3f5bacSStephan Aßmus 	menuFields.AddItem((void*)fColorsField);
1186df3f5bacSStephan Aßmus 	menuFields.AddItem((void*)fRefreshField);
1187df3f5bacSStephan Aßmus 
1188df3f5bacSStephan Aßmus 	BRect frame;
1189df3f5bacSStephan Aßmus 
1190df3f5bacSStephan Aßmus 	if (sideBySide)
1191df3f5bacSStephan Aßmus 		frame = stack_and_align_menu_fields(menuFields);
1192df3f5bacSStephan Aßmus 
1193df3f5bacSStephan Aßmus 	if (sideBySide)
1194df3f5bacSStephan Aßmus 		menuFields.MakeEmpty();
1195df3f5bacSStephan Aßmus 
1196df3f5bacSStephan Aßmus 	if (flags & SHOW_COMBINE_FIELD)
1197df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fCombineField);
1198df3f5bacSStephan Aßmus 	if (flags & SHOW_SWAP_FIELD)
1199df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fSwapDisplaysField);
1200df3f5bacSStephan Aßmus 	if (flags & SHOW_LAPTOP_PANEL_FIELD)
1201df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fUseLaptopPanelField);
1202df3f5bacSStephan Aßmus 	if (flags & SHOW_TV_STANDARD_FIELD)
1203df3f5bacSStephan Aßmus 		menuFields.AddItem((void*)fTVStandardField);
1204df3f5bacSStephan Aßmus 
1205df3f5bacSStephan Aßmus 	if (sideBySide) {
1206df3f5bacSStephan Aßmus 		if (menuFields.CountItems() > 0) {
1207df3f5bacSStephan Aßmus 			((BMenuField*)menuFields.FirstItem())->MoveTo(frame.right + 8.0, frame.top);
1208df3f5bacSStephan Aßmus 			frame = frame | stack_and_align_menu_fields(menuFields);
1209df3f5bacSStephan Aßmus 		}
1210df3f5bacSStephan Aßmus 	} else {
1211df3f5bacSStephan Aßmus 		frame = stack_and_align_menu_fields(menuFields);
1212df3f5bacSStephan Aßmus 	}
1213df3f5bacSStephan Aßmus 
1214df3f5bacSStephan Aßmus 	return frame;
1215df3f5bacSStephan Aßmus }
1216df3f5bacSStephan Aßmus 
1217