xref: /haiku/src/preferences/screen/ScreenWindow.cpp (revision 5a78744bedbbca9f8071f79ed681ad5857f51931)
1a10cf76eSAxel Dörfler /*
2a10cf76eSAxel Dörfler  * Copyright 2001-2005, 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
11a10cf76eSAxel Dörfler  */
12a10cf76eSAxel Dörfler 
13a10cf76eSAxel Dörfler 
14a10cf76eSAxel Dörfler #include <Alert.h>
15a10cf76eSAxel Dörfler #include <Application.h>
16a10cf76eSAxel Dörfler #include <Box.h>
17a10cf76eSAxel Dörfler #include <Button.h>
18a10cf76eSAxel Dörfler #include <InterfaceDefs.h>
19a10cf76eSAxel Dörfler #include <MenuItem.h>
20a10cf76eSAxel Dörfler #include <MenuField.h>
21a10cf76eSAxel Dörfler #include <Messenger.h>
22a10cf76eSAxel Dörfler #include <PopUpMenu.h>
23a10cf76eSAxel Dörfler #include <Screen.h>
24a10cf76eSAxel Dörfler #include <String.h>
25a10cf76eSAxel Dörfler #include <Window.h>
26a10cf76eSAxel Dörfler 
27a10cf76eSAxel Dörfler #include <cstdio>
28a10cf76eSAxel Dörfler #include <cstdlib>
29a10cf76eSAxel Dörfler #include <cstring>
30a10cf76eSAxel Dörfler 
31a10cf76eSAxel Dörfler #include "AlertWindow.h"
32a10cf76eSAxel Dörfler #include "Constants.h"
33a10cf76eSAxel Dörfler #include "RefreshWindow.h"
34a10cf76eSAxel Dörfler #include "MonitorView.h"
35a10cf76eSAxel Dörfler #include "ScreenSettings.h"
36a10cf76eSAxel Dörfler #include "ScreenWindow.h"
37a10cf76eSAxel Dörfler #include "Utility.h"
38a10cf76eSAxel Dörfler 
39a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant.
40a10cf76eSAxel Dörfler  * It's a solution that works with the current BeOS interface that Haiku
41a10cf76eSAxel Dörfler  * adopted.
42a10cf76eSAxel Dörfler  * However, it's not a nice and clean solution. Don't use this header in any
43a10cf76eSAxel Dörfler  * application if you can avoid it. No other driver is using this, or should
44a10cf76eSAxel Dörfler  * be using this.
45a10cf76eSAxel Dörfler  * It will be replaced as soon as we introduce an updated accelerant interface
46a10cf76eSAxel Dörfler  * which may even happen before R1 hits the streets.
47a10cf76eSAxel Dörfler  */
48a10cf76eSAxel Dörfler 
49a10cf76eSAxel Dörfler #include "multimon.h"	// the usual: DANGER WILL, ROBINSON!
50a10cf76eSAxel Dörfler 
51a10cf76eSAxel Dörfler 
52a10cf76eSAxel Dörfler #define USE_FIXED_REFRESH
53a10cf76eSAxel Dörfler 	// define to use fixed standard refresh rates
54a10cf76eSAxel Dörfler 	// undefine to get standard refresh rates from driver
55a10cf76eSAxel Dörfler 
56a10cf76eSAxel Dörfler 
57a10cf76eSAxel Dörfler // list of officially supported colour spaces
58a10cf76eSAxel Dörfler static const struct {
59a10cf76eSAxel Dörfler 	color_space	space;
60a10cf76eSAxel Dörfler 	int32		bits_per_pixel;
61a10cf76eSAxel Dörfler 	const char*	label;
62a10cf76eSAxel Dörfler } kColorSpaces[] = {
63a10cf76eSAxel Dörfler 	{ B_CMAP8, 8, "8 Bits/Pixel, 256 Colors" },
64a10cf76eSAxel Dörfler 	{ B_RGB15, 15, "15 Bits/Pixel, 32768 Colors" },
65a10cf76eSAxel Dörfler 	{ B_RGB16, 16, "16 Bits/Pixel, 65536 Colors" },
66a10cf76eSAxel Dörfler 	{ B_RGB32, 32, "32 Bits/Pixel, 16 Million Colors" }
67a10cf76eSAxel Dörfler };
68a10cf76eSAxel Dörfler static const int32 kColorSpaceCount = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]);
69a10cf76eSAxel Dörfler 
70a10cf76eSAxel Dörfler // list of standard refresh rates
71a10cf76eSAxel Dörfler static const int32 kRefreshRates[] = {56, 60, 70, 72, 75};
72a10cf76eSAxel Dörfler static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]);
73a10cf76eSAxel Dörfler 
74a10cf76eSAxel Dörfler 
75a10cf76eSAxel Dörfler // list of combine modes
76a10cf76eSAxel Dörfler static const struct {
77a10cf76eSAxel Dörfler 	combine_mode	mode;
78a10cf76eSAxel Dörfler 	const char		*name;
79a10cf76eSAxel Dörfler } kCombineModes[] = {
80a10cf76eSAxel Dörfler 	{ kCombineDisable, "disable" },
81a10cf76eSAxel Dörfler 	{ kCombineHorizontally, "horizontally" },
82a10cf76eSAxel Dörfler 	{ kCombineVertically, "vertically" }
83a10cf76eSAxel Dörfler };
84a10cf76eSAxel Dörfler static const int32 kCombineModeCount = sizeof(kCombineModes) / sizeof(kCombineModes[0]);
85a10cf76eSAxel Dörfler 
86a10cf76eSAxel Dörfler 
87a10cf76eSAxel Dörfler static BString
88a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode)
89a10cf76eSAxel Dörfler {
90a10cf76eSAxel Dörfler 	switch (mode) {
91a10cf76eSAxel Dörfler 		case 0:		return "disabled";
92a10cf76eSAxel Dörfler 		case 1:		return "NTSC";
93a10cf76eSAxel Dörfler 		case 2:		return "NTSC Japan";
94a10cf76eSAxel Dörfler 		case 3:		return "PAL BDGHI";
95a10cf76eSAxel Dörfler 		case 4:		return "PAL M";
96a10cf76eSAxel Dörfler 		case 5:		return "PAL N";
97a10cf76eSAxel Dörfler 		case 6:		return "SECAM";
98a10cf76eSAxel Dörfler 		case 101:	return "NTSC 443";
99a10cf76eSAxel Dörfler 		case 102:	return "PAL 60";
100a10cf76eSAxel Dörfler 		case 103:	return "PAL NC";
101a10cf76eSAxel Dörfler 		default:
102a10cf76eSAxel Dörfler 		{
103a10cf76eSAxel Dörfler 			BString name;
104a10cf76eSAxel Dörfler 			name << "??? (" << mode << ")";
105a10cf76eSAxel Dörfler 
106a10cf76eSAxel Dörfler 			return name;
107a10cf76eSAxel Dörfler 		}
108a10cf76eSAxel Dörfler 	}
109a10cf76eSAxel Dörfler }
110a10cf76eSAxel Dörfler 
111a10cf76eSAxel Dörfler 
112a10cf76eSAxel Dörfler static void
113a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string)
114a10cf76eSAxel Dörfler {
115a10cf76eSAxel Dörfler 	string << mode.width << " x " << mode.height;
116a10cf76eSAxel Dörfler }
117a10cf76eSAxel Dörfler 
118a10cf76eSAxel Dörfler 
119a10cf76eSAxel Dörfler static void
120a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string,
121a10cf76eSAxel Dörfler 	bool appendUnit = true, bool alwaysWithFraction = false)
122a10cf76eSAxel Dörfler {
123a10cf76eSAxel Dörfler 	snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, refresh);
124a10cf76eSAxel Dörfler 	string.UnlockBuffer();
125a10cf76eSAxel Dörfler 
126a10cf76eSAxel Dörfler 	if (appendUnit)
127a10cf76eSAxel Dörfler 		string << " Hz";
128a10cf76eSAxel Dörfler }
129a10cf76eSAxel Dörfler 
130a10cf76eSAxel Dörfler 
13107184a9eSAxel Dörfler static const char*
13207184a9eSAxel Dörfler screen_errors(status_t status)
13307184a9eSAxel Dörfler {
13407184a9eSAxel Dörfler 	switch (status) {
13507184a9eSAxel Dörfler 		case B_ENTRY_NOT_FOUND:
13607184a9eSAxel Dörfler 			return "Unknown Mode";
13707184a9eSAxel Dörfler 		// TODO: add more?
13807184a9eSAxel Dörfler 
13907184a9eSAxel Dörfler 		default:
14007184a9eSAxel Dörfler 			return strerror(status);
14107184a9eSAxel Dörfler 	}
14207184a9eSAxel Dörfler }
14307184a9eSAxel Dörfler 
14407184a9eSAxel Dörfler 
145a10cf76eSAxel Dörfler //	#pragma mark -
146a10cf76eSAxel Dörfler 
147a10cf76eSAxel Dörfler 
148*5a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings *settings)
149*5a78744bSAxel Dörfler 	: BWindow(settings->WindowFrame(), "Screen", B_TITLED_WINDOW,
150a10cf76eSAxel Dörfler 		B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES),
151a10cf76eSAxel Dörfler 	fScreenMode(this),
152a10cf76eSAxel Dörfler 	fChangingAllWorkspaces(false)
153a10cf76eSAxel Dörfler {
154a10cf76eSAxel Dörfler 	BScreen screen(this);
155a10cf76eSAxel Dörfler 	BRect frame(Bounds());
156a10cf76eSAxel Dörfler 
157a10cf76eSAxel Dörfler 	fScreenMode.Get(fOriginal);
158a10cf76eSAxel Dörfler 	fActive = fSelected = fOriginal;
159a10cf76eSAxel Dörfler 
160a10cf76eSAxel Dörfler 	BView *view = new BView(frame, "ScreenView", B_FOLLOW_ALL, B_WILL_DRAW);
161a10cf76eSAxel Dörfler 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
162a10cf76eSAxel Dörfler 	AddChild(view);
163a10cf76eSAxel Dörfler 
164*5a78744bSAxel Dörfler 	fSettings = settings;
165*5a78744bSAxel Dörfler 
166*5a78744bSAxel Dörfler 	// we need the "Current Workspace" first to get its height
167*5a78744bSAxel Dörfler 
168*5a78744bSAxel Dörfler 	BPopUpMenu *popUpMenu = new BPopUpMenu("Current Workspace", true, true);
169*5a78744bSAxel Dörfler 	fAllWorkspacesItem = new BMenuItem("All Workspaces", new BMessage(WORKSPACE_CHECK_MSG));
170*5a78744bSAxel Dörfler 	popUpMenu->AddItem(fAllWorkspacesItem);
171*5a78744bSAxel Dörfler 	BMenuItem *item = new BMenuItem("Current Workspace", new BMessage(WORKSPACE_CHECK_MSG));
172*5a78744bSAxel Dörfler 	item->SetMarked(true);
173*5a78744bSAxel Dörfler 	popUpMenu->AddItem(item);
174*5a78744bSAxel Dörfler 
175*5a78744bSAxel Dörfler 	BMenuField* workspaceMenuField = new BMenuField(BRect(0, 0, 125, 18),
176*5a78744bSAxel Dörfler 		"WorkspaceMenu", NULL, popUpMenu, true);
177*5a78744bSAxel Dörfler 	workspaceMenuField->ResizeToPreferred();
178a10cf76eSAxel Dörfler 
179a10cf76eSAxel Dörfler 	// box on the left with workspace count and monitor view
180a10cf76eSAxel Dörfler 
181*5a78744bSAxel Dörfler 	float labelWidth = be_plain_font->StringWidth("Workspaces count:") + 5.0f;
182a10cf76eSAxel Dörfler 
183*5a78744bSAxel Dörfler 	BRect rect(10.0, 7.0 + workspaceMenuField->Bounds().Height() / 2.0f,
184*5a78744bSAxel Dörfler 		26 + labelWidth + 32, 155.0);
185*5a78744bSAxel Dörfler 	BBox *screenBox = new BBox(rect, "left box");
186a10cf76eSAxel Dörfler 
187*5a78744bSAxel Dörfler 	rect = screenBox->Bounds().InsetByCopy(8, 8);
188*5a78744bSAxel Dörfler 	rect.bottom = rect.top + workspaceMenuField->Bounds().Height();
189*5a78744bSAxel Dörfler 	popUpMenu = new BPopUpMenu("", true, true);
190*5a78744bSAxel Dörfler 	BMenuField *menuField = new BMenuField(rect, "WorkspaceCountMenu",
191*5a78744bSAxel Dörfler 		"Workspace count:", popUpMenu, true);
192*5a78744bSAxel Dörfler 	float width, height;
193*5a78744bSAxel Dörfler 	menuField->GetPreferredSize(&width, &height);
194*5a78744bSAxel Dörfler 	menuField->ResizeTo(rect.Width(), height);
195*5a78744bSAxel Dörfler 	menuField->MoveTo(rect.left, screenBox->Bounds().bottom - 8 - height);
196*5a78744bSAxel Dörfler 	menuField->SetDivider(labelWidth);
197a10cf76eSAxel Dörfler 	screenBox->AddChild(menuField);
198a10cf76eSAxel Dörfler 
199a10cf76eSAxel Dörfler 	for (int32 count = 1; count <= 32; count++) {
200a10cf76eSAxel Dörfler 		BString workspaceCount;
201a10cf76eSAxel Dörfler 		workspaceCount << count;
202a10cf76eSAxel Dörfler 
203a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_WORKSPACE_CHANGED_MSG);
204a10cf76eSAxel Dörfler 		message->AddInt32("workspace count", count);
205a10cf76eSAxel Dörfler 
206a10cf76eSAxel Dörfler 		popUpMenu->AddItem(new BMenuItem(workspaceCount.String(),
207a10cf76eSAxel Dörfler 			message));
208a10cf76eSAxel Dörfler 	}
209a10cf76eSAxel Dörfler 
210*5a78744bSAxel Dörfler 	item = popUpMenu->ItemAt(count_workspaces() - 1);
211a10cf76eSAxel Dörfler 	if (item != NULL)
212a10cf76eSAxel Dörfler 		item->SetMarked(true);
213a10cf76eSAxel Dörfler 
214*5a78744bSAxel Dörfler 	rect = screenBox->Bounds().InsetByCopy(22, 22);
215*5a78744bSAxel Dörfler 	fMonitorView = new MonitorView(rect, "monitor",
216*5a78744bSAxel Dörfler 		screen.Frame().Width() + 1, screen.Frame().Height() + 1);
217*5a78744bSAxel Dörfler 	screenBox->AddChild(fMonitorView);
218*5a78744bSAxel Dörfler 
219a10cf76eSAxel Dörfler 	view->AddChild(screenBox);
220a10cf76eSAxel Dörfler 
221a10cf76eSAxel Dörfler 	// box on the right with screen resolution, etc.
222a10cf76eSAxel Dörfler 
223*5a78744bSAxel Dörfler 	rect = screenBox->Frame();
224*5a78744bSAxel Dörfler 	rect.top = 7.0f;
225*5a78744bSAxel Dörfler 	rect.left = rect.right + 10.0f;
226*5a78744bSAxel Dörfler 	rect.right = rect.left + 190.0f;
227a10cf76eSAxel Dörfler 	BBox* controlsBox = new BBox(rect);
228*5a78744bSAxel Dörfler 	controlsBox->SetLabel(workspaceMenuField);
229a10cf76eSAxel Dörfler 
230*5a78744bSAxel Dörfler 	rect.SetLeftTop(controlsBox->Bounds().RightBottom());
231a10cf76eSAxel Dörfler 	fApplyButton = new BButton(rect, "ApplyButton", "Apply",
232*5a78744bSAxel Dörfler 		new BMessage(BUTTON_APPLY_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
233a10cf76eSAxel Dörfler 	fApplyButton->ResizeToPreferred();
234*5a78744bSAxel Dörfler 	fApplyButton->MoveTo(rect.LeftTop() - BPoint(8, 8)
235*5a78744bSAxel Dörfler 		- fApplyButton->Bounds().RightBottom());
236a10cf76eSAxel Dörfler 	fApplyButton->SetEnabled(false);
237a10cf76eSAxel Dörfler 	controlsBox->AddChild(fApplyButton);
238a10cf76eSAxel Dörfler 
239*5a78744bSAxel Dörfler 	labelWidth = controlsBox->StringWidth("Refresh rate:") + 5.0f;
240a10cf76eSAxel Dörfler 	fResolutionMenu = new BPopUpMenu("resolution", true, true);
241a10cf76eSAxel Dörfler 
242a10cf76eSAxel Dörfler 	uint16 previousWidth = 0, previousHeight = 0;
243a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
244a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
245a10cf76eSAxel Dörfler 
246a10cf76eSAxel Dörfler 		if (mode.width == previousWidth && mode.height == previousHeight)
247a10cf76eSAxel Dörfler 			continue;
248a10cf76eSAxel Dörfler 
249a10cf76eSAxel Dörfler 		previousWidth = mode.width;
250a10cf76eSAxel Dörfler 		previousHeight = mode.height;
251a10cf76eSAxel Dörfler 
252a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_RESOLUTION_MSG);
253a10cf76eSAxel Dörfler 		message->AddInt32("width", mode.width);
254a10cf76eSAxel Dörfler 		message->AddInt32("height", mode.height);
255a10cf76eSAxel Dörfler 
256a10cf76eSAxel Dörfler 		BString name;
257a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
258a10cf76eSAxel Dörfler 
259a10cf76eSAxel Dörfler 		fResolutionMenu->AddItem(new BMenuItem(name.String(), message));
260a10cf76eSAxel Dörfler 	}
261a10cf76eSAxel Dörfler 
262*5a78744bSAxel Dörfler 	rect.Set(10.0, 30.0, 179.0, 48.0);
263a10cf76eSAxel Dörfler 	fResolutionField = new BMenuField(rect, "ResolutionMenu", "Resolution:",
264a10cf76eSAxel Dörfler 		fResolutionMenu, true);
265*5a78744bSAxel Dörfler 	fResolutionField->SetAlignment(B_ALIGN_RIGHT);
266*5a78744bSAxel Dörfler 	fResolutionField->SetDivider(labelWidth);
267a10cf76eSAxel Dörfler 	controlsBox->AddChild(fResolutionField);
268a10cf76eSAxel Dörfler 
269a10cf76eSAxel Dörfler 	fColorsMenu = new BPopUpMenu("colors", true, true);
270a10cf76eSAxel Dörfler 
271a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
272a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_COLORS_MSG);
273a10cf76eSAxel Dörfler 		message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel);
274a10cf76eSAxel Dörfler 		message->AddInt32("space", kColorSpaces[i].space);
275a10cf76eSAxel Dörfler 
276a10cf76eSAxel Dörfler 		fColorsMenu->AddItem(new BMenuItem(kColorSpaces[i].label, message));
277a10cf76eSAxel Dörfler 	}
278a10cf76eSAxel Dörfler 
279*5a78744bSAxel Dörfler 	rect.Set(10.0, 58.0, 179.0, 76.0);
280a10cf76eSAxel Dörfler 	fColorsField = new BMenuField(rect, "ColorsMenu", "Colors:", fColorsMenu, true);
281*5a78744bSAxel Dörfler 	fColorsField->SetAlignment(B_ALIGN_RIGHT);
282*5a78744bSAxel Dörfler 	fColorsField->SetDivider(labelWidth);
283a10cf76eSAxel Dörfler 	controlsBox->AddChild(fColorsField);
284a10cf76eSAxel Dörfler 
285a10cf76eSAxel Dörfler 	fRefreshMenu = new BPopUpMenu("refresh rate", true, true);
286a10cf76eSAxel Dörfler 
287a10cf76eSAxel Dörfler #ifdef USE_FIXED_REFRESH
288a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kRefreshRateCount; ++i) {
289a10cf76eSAxel Dörfler 		BString name;
290a10cf76eSAxel Dörfler 		name << kRefreshRates[i] << " Hz";
291a10cf76eSAxel Dörfler 
292a10cf76eSAxel Dörfler 		BMessage *message = new BMessage(POP_REFRESH_MSG);
293a10cf76eSAxel Dörfler 		message->AddFloat("refresh", kRefreshRates[i]);
294a10cf76eSAxel Dörfler 
295a10cf76eSAxel Dörfler 		fRefreshMenu->AddItem(new BMenuItem(name.String(), message));
296a10cf76eSAxel Dörfler 	}
297a10cf76eSAxel Dörfler #endif
298a10cf76eSAxel Dörfler 
299a10cf76eSAxel Dörfler 	BMessage *message = new BMessage(POP_OTHER_REFRESH_MSG);
300a10cf76eSAxel Dörfler 
301a10cf76eSAxel Dörfler 	fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message);
302a10cf76eSAxel Dörfler 	fRefreshMenu->AddItem(fOtherRefresh);
303a10cf76eSAxel Dörfler 
304*5a78744bSAxel Dörfler 	rect.Set(10.0, 86.0, 179.0, 104.0);
305a10cf76eSAxel Dörfler 	fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:", fRefreshMenu, true);
306*5a78744bSAxel Dörfler 	fRefreshField->SetAlignment(B_ALIGN_RIGHT);
307*5a78744bSAxel Dörfler 	fRefreshField->SetDivider(labelWidth);
308a10cf76eSAxel Dörfler 	controlsBox->AddChild(fRefreshField);
309a10cf76eSAxel Dörfler 
310a10cf76eSAxel Dörfler 	view->AddChild(controlsBox);
311a10cf76eSAxel Dörfler 
312a10cf76eSAxel Dörfler 	// enlarged area for multi-monitor settings
313a10cf76eSAxel Dörfler 	{
314a10cf76eSAxel Dörfler 		bool dummy;
315a10cf76eSAxel Dörfler 		uint32 dummy32;
316a10cf76eSAxel Dörfler 		bool multiMonSupport;
317a10cf76eSAxel Dörfler 		bool useLaptopPanelSupport;
318a10cf76eSAxel Dörfler 		bool tvStandardSupport;
319a10cf76eSAxel Dörfler 
320a10cf76eSAxel Dörfler 		multiMonSupport = TestMultiMonSupport(&screen) == B_OK;
321a10cf76eSAxel Dörfler 		useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK;
322a10cf76eSAxel Dörfler 		tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK;
323a10cf76eSAxel Dörfler 
324a10cf76eSAxel Dörfler 		// even if there is no support, we still create all controls
325a10cf76eSAxel Dörfler 		// to make sure we don't access NULL pointers later on
326*5a78744bSAxel Dörfler 		if (multiMonSupport)
327a10cf76eSAxel Dörfler 			controlsBox->ResizeTo(366, 148);
328a10cf76eSAxel Dörfler 
329a10cf76eSAxel Dörfler 		fCombineMenu = new BPopUpMenu("CombineDisplays", true, true);
330a10cf76eSAxel Dörfler 
331a10cf76eSAxel Dörfler 		for (int32 i = 0; i < kCombineModeCount; i++) {
332a10cf76eSAxel Dörfler 			message = new BMessage(POP_COMBINE_DISPLAYS_MSG);
333a10cf76eSAxel Dörfler 			message->AddInt32("mode", kCombineModes[i].mode);
334a10cf76eSAxel Dörfler 
335a10cf76eSAxel Dörfler 			fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, message));
336a10cf76eSAxel Dörfler 		}
337a10cf76eSAxel Dörfler 
338a10cf76eSAxel Dörfler 		rect.Set(185, 30, 356, 48);
339a10cf76eSAxel Dörfler 		BMenuField* menuField = new BMenuField(rect, "CombineMenu",
340a10cf76eSAxel Dörfler 			"Combine Displays:", fCombineMenu, true);
341a10cf76eSAxel Dörfler 		menuField->SetDivider(90);
342a10cf76eSAxel Dörfler 		controlsBox->AddChild(menuField);
343a10cf76eSAxel Dörfler 
344a10cf76eSAxel Dörfler 		if (!multiMonSupport)
345a10cf76eSAxel Dörfler 			menuField->Hide();
346a10cf76eSAxel Dörfler 
347a10cf76eSAxel Dörfler 		fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true);
348a10cf76eSAxel Dörfler 
349a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
350a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
351a10cf76eSAxel Dörfler 		message->AddBool("swap", false);
352a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("no", message));
353a10cf76eSAxel Dörfler 
354a10cf76eSAxel Dörfler 		message = new BMessage(POP_SWAP_DISPLAYS_MSG);
355a10cf76eSAxel Dörfler 		message->AddBool("swap", true);
356a10cf76eSAxel Dörfler 		fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message));
357a10cf76eSAxel Dörfler 
358a10cf76eSAxel Dörfler 		rect.Set(199, 58, 356, 76);
359a10cf76eSAxel Dörfler 		menuField = new BMenuField(rect, "SwapMenu", "Swap Displays:",
360a10cf76eSAxel Dörfler 			fSwapDisplaysMenu, true);
361a10cf76eSAxel Dörfler 		menuField->SetDivider(76);
362a10cf76eSAxel Dörfler 
363a10cf76eSAxel Dörfler 		controlsBox->AddChild(menuField);
364a10cf76eSAxel Dörfler 		if (!multiMonSupport)
365a10cf76eSAxel Dörfler 			menuField->Hide();
366a10cf76eSAxel Dörfler 
367a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true);
368a10cf76eSAxel Dörfler 
369a10cf76eSAxel Dörfler 		// !order is important - we rely that boolean value == idx
370a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
371a10cf76eSAxel Dörfler 		message->AddBool("use", false);
372a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message));
373a10cf76eSAxel Dörfler 
374a10cf76eSAxel Dörfler 		message = new BMessage(POP_USE_LAPTOP_PANEL_MSG);
375a10cf76eSAxel Dörfler 		message->AddBool("use", true);
376a10cf76eSAxel Dörfler 		fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message));
377a10cf76eSAxel Dörfler 
378a10cf76eSAxel Dörfler 		rect.Set(184, 86, 356, 104);
379a10cf76eSAxel Dörfler 		menuField = new BMenuField(rect, "UseLaptopPanel", "Use Laptop Panel:",
380a10cf76eSAxel Dörfler 			fUseLaptopPanelMenu, true);
381a10cf76eSAxel Dörfler 		menuField->SetDivider(91);
382a10cf76eSAxel Dörfler 
383a10cf76eSAxel Dörfler 		controlsBox->AddChild(menuField);
384a10cf76eSAxel Dörfler 		if (!useLaptopPanelSupport)
385a10cf76eSAxel Dörfler 			menuField->Hide();
386a10cf76eSAxel Dörfler 
387a10cf76eSAxel Dörfler 		fTVStandardMenu = new BPopUpMenu("TVStandard", true, true);
388a10cf76eSAxel Dörfler 
389a10cf76eSAxel Dörfler 		// arbitrary limit
390a10cf76eSAxel Dörfler 		uint32 i;
391a10cf76eSAxel Dörfler 		for (i = 0; i < 100; ++i) {
392a10cf76eSAxel Dörfler 			uint32 mode;
393a10cf76eSAxel Dörfler 
394a10cf76eSAxel Dörfler 			if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK)
395a10cf76eSAxel Dörfler 				break;
396a10cf76eSAxel Dörfler 
397a10cf76eSAxel Dörfler 			BString name = tv_standard_to_string(mode);
398a10cf76eSAxel Dörfler 
399a10cf76eSAxel Dörfler 			message = new BMessage(POP_TV_STANDARD_MSG);
400a10cf76eSAxel Dörfler 			message->AddInt32("tv_standard", mode);
401a10cf76eSAxel Dörfler 
402a10cf76eSAxel Dörfler 			fTVStandardMenu->AddItem(new BMenuItem(name.String(), message));
403a10cf76eSAxel Dörfler 		}
404a10cf76eSAxel Dörfler 
405a10cf76eSAxel Dörfler 		rect.Set(15, 114, 171, 132);
406a10cf76eSAxel Dörfler 		menuField = new BMenuField(rect, "tv standard", "Video Format:",
407a10cf76eSAxel Dörfler 			fTVStandardMenu, true);
408a10cf76eSAxel Dörfler 		menuField->SetDivider(73);
409a10cf76eSAxel Dörfler 
410a10cf76eSAxel Dörfler 		if (!tvStandardSupport || i == 0)
411a10cf76eSAxel Dörfler 			menuField->Hide();
412a10cf76eSAxel Dörfler 
413a10cf76eSAxel Dörfler 		controlsBox->AddChild(menuField);
414a10cf76eSAxel Dörfler 	}
415a10cf76eSAxel Dörfler 
416*5a78744bSAxel Dörfler 	rect.Set(10.0, screenBox->Frame().bottom + 10.0, 100.0, 200.0);
417a10cf76eSAxel Dörfler 	fDefaultsButton = new BButton(rect, "DefaultsButton", "Defaults",
418a10cf76eSAxel Dörfler 		new BMessage(BUTTON_DEFAULTS_MSG));
419a10cf76eSAxel Dörfler 	fDefaultsButton->ResizeToPreferred();
420a10cf76eSAxel Dörfler 	view->AddChild(fDefaultsButton);
421a10cf76eSAxel Dörfler 
422*5a78744bSAxel Dörfler 	rect.OffsetBy(fDefaultsButton->Bounds().Width() + 10, 0);
423a10cf76eSAxel Dörfler 	fRevertButton = new BButton(rect, "RevertButton", "Revert",
424a10cf76eSAxel Dörfler 		new BMessage(BUTTON_REVERT_MSG));
425a10cf76eSAxel Dörfler 	fRevertButton->ResizeToPreferred();
426a10cf76eSAxel Dörfler 	fRevertButton->SetEnabled(false);
427a10cf76eSAxel Dörfler 	view->AddChild(fRevertButton);
428a10cf76eSAxel Dörfler 
429*5a78744bSAxel Dörfler 	ResizeTo(controlsBox->Frame().right + 10,
430*5a78744bSAxel Dörfler 		fDefaultsButton->Frame().bottom + 10);
431*5a78744bSAxel Dörfler 
432a10cf76eSAxel Dörfler 	UpdateControls();
433a10cf76eSAxel Dörfler }
434a10cf76eSAxel Dörfler 
435a10cf76eSAxel Dörfler 
436a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow()
437a10cf76eSAxel Dörfler {
438a10cf76eSAxel Dörfler 	delete fSettings;
439a10cf76eSAxel Dörfler }
440a10cf76eSAxel Dörfler 
441a10cf76eSAxel Dörfler 
442a10cf76eSAxel Dörfler bool
443a10cf76eSAxel Dörfler ScreenWindow::QuitRequested()
444a10cf76eSAxel Dörfler {
445a10cf76eSAxel Dörfler 	fSettings->SetWindowFrame(Frame());
446a10cf76eSAxel Dörfler 	be_app->PostMessage(B_QUIT_REQUESTED);
447a10cf76eSAxel Dörfler 
448a10cf76eSAxel Dörfler 	return BWindow::QuitRequested();
449a10cf76eSAxel Dörfler }
450a10cf76eSAxel Dörfler 
451a10cf76eSAxel Dörfler 
452a10cf76eSAxel Dörfler /**	update resolution list according to combine mode
453a10cf76eSAxel Dörfler  *	(some resolution may not be combinable due to memory restrictions)
454a10cf76eSAxel Dörfler  */
455a10cf76eSAxel Dörfler 
456a10cf76eSAxel Dörfler void
457a10cf76eSAxel Dörfler ScreenWindow::CheckResolutionMenu()
458a10cf76eSAxel Dörfler {
459a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fResolutionMenu->CountItems(); i++)
460a10cf76eSAxel Dörfler 		fResolutionMenu->ItemAt(i)->SetEnabled(false);
461a10cf76eSAxel Dörfler 
462a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fScreenMode.CountModes(); i++) {
463a10cf76eSAxel Dörfler 		screen_mode mode = fScreenMode.ModeAt(i);
464a10cf76eSAxel Dörfler 		if (mode.combine != fSelected.combine)
465a10cf76eSAxel Dörfler 			continue;
466a10cf76eSAxel Dörfler 
467a10cf76eSAxel Dörfler 		BString name;
468a10cf76eSAxel Dörfler 		name << mode.width << " x " << mode.height;
469a10cf76eSAxel Dörfler 
470a10cf76eSAxel Dörfler 		BMenuItem *item = fResolutionMenu->FindItem(name.String());
471a10cf76eSAxel Dörfler 		if (item != NULL)
472a10cf76eSAxel Dörfler 			item->SetEnabled(true);
473a10cf76eSAxel Dörfler 	}
474a10cf76eSAxel Dörfler }
475a10cf76eSAxel Dörfler 
476a10cf76eSAxel Dörfler 
477a10cf76eSAxel Dörfler /**	update color and refresh options according to current mode
478a10cf76eSAxel Dörfler  *	(a color space is made active if there is any mode with
479a10cf76eSAxel Dörfler  *	given resolution and this colour space; same applies for
480a10cf76eSAxel Dörfler  *	refresh rate, though "Other…" is always possible)
481a10cf76eSAxel Dörfler  */
482a10cf76eSAxel Dörfler 
483a10cf76eSAxel Dörfler void
484a10cf76eSAxel Dörfler ScreenWindow::CheckColorMenu()
485a10cf76eSAxel Dörfler {
486a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kColorSpaceCount; i++) {
487a10cf76eSAxel Dörfler 		bool supported = false;
488a10cf76eSAxel Dörfler 
489a10cf76eSAxel Dörfler 		for (int32 j = 0; j < fScreenMode.CountModes(); j++) {
490a10cf76eSAxel Dörfler 			screen_mode mode = fScreenMode.ModeAt(j);
491a10cf76eSAxel Dörfler 
492a10cf76eSAxel Dörfler 			if (fSelected.width == mode.width
493a10cf76eSAxel Dörfler 				&& fSelected.height == mode.height
494a10cf76eSAxel Dörfler 				&& kColorSpaces[i].space == mode.space
495a10cf76eSAxel Dörfler 				&& fSelected.combine == mode.combine) {
496a10cf76eSAxel Dörfler 				supported = true;
497a10cf76eSAxel Dörfler 				break;
498a10cf76eSAxel Dörfler 			}
499a10cf76eSAxel Dörfler 		}
500a10cf76eSAxel Dörfler 
501a10cf76eSAxel Dörfler 		BMenuItem* item = fColorsMenu->ItemAt(i);
502a10cf76eSAxel Dörfler 		if (item)
503a10cf76eSAxel Dörfler 			item->SetEnabled(supported);
504a10cf76eSAxel Dörfler 	}
505a10cf76eSAxel Dörfler }
506a10cf76eSAxel Dörfler 
507a10cf76eSAxel Dörfler 
508a10cf76eSAxel Dörfler /**	Enable/disable refresh options according to current mode.
509a10cf76eSAxel Dörfler  *	Only needed when USE_FIXED_REFRESH is not defined.
510a10cf76eSAxel Dörfler  */
511a10cf76eSAxel Dörfler 
512a10cf76eSAxel Dörfler void
513a10cf76eSAxel Dörfler ScreenWindow::CheckRefreshMenu()
514a10cf76eSAxel Dörfler {
515a10cf76eSAxel Dörfler #ifndef USE_FIXED_REFRESH
516a10cf76eSAxel Dörfler 	// ToDo: does currently not compile!
517a10cf76eSAxel Dörfler 	for (int32 i = fRefreshMenu->CountItems() - 2; i >= 0; --i) {
518a10cf76eSAxel Dörfler 		delete fRefreshMenu->RemoveItem(i);
519a10cf76eSAxel Dörfler 	}
520a10cf76eSAxel Dörfler 
521a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fModeListCount; ++i) {
522a10cf76eSAxel Dörfler 		if (virtualWidth == fModeList[i].virtual_width
523a10cf76eSAxel Dörfler 			&& virtualHeight == fModeList[i].virtual_height
524a10cf76eSAxel Dörfler 			&& combine == get_combine_mode(&fModeList[i])) {
525a10cf76eSAxel Dörfler 			BString name;
526a10cf76eSAxel Dörfler 			BMenuItem *item;
527a10cf76eSAxel Dörfler 
528a10cf76eSAxel Dörfler 			int32 refresh10 = get_refresh10(fModeList[i]);
529a10cf76eSAxel Dörfler 			refresh10_to_string(name, refresh10);
530a10cf76eSAxel Dörfler 
531a10cf76eSAxel Dörfler 			item = fRefreshMenu->FindItem(name.String());
532a10cf76eSAxel Dörfler 			if (item == NULL) {
533a10cf76eSAxel Dörfler 				BMessage *msg = new BMessage(POP_REFRESH_MSG);
534a10cf76eSAxel Dörfler 				msg->AddFloat("refresh", refresh);
535a10cf76eSAxel Dörfler 
536a10cf76eSAxel Dörfler 				fRefreshMenu->AddItem(new BMenuItem(name.String(), msg),
537a10cf76eSAxel Dörfler 					fRefreshMenu->CountItems() - 1);
538a10cf76eSAxel Dörfler 			}
539a10cf76eSAxel Dörfler 		}
540a10cf76eSAxel Dörfler 	}
541a10cf76eSAxel Dörfler #endif
542a10cf76eSAxel Dörfler 
543a10cf76eSAxel Dörfler 	// TBD: some drivers lack many refresh rates; still, they
544a10cf76eSAxel Dörfler 	// can be used by generating the mode manually
545a10cf76eSAxel Dörfler /*
546a10cf76eSAxel Dörfler 	for( i = 0; i < sizeof( refresh_list ) / sizeof( refresh_list[0] ); ++i ) {
547a10cf76eSAxel Dörfler 		BMenuItem *item;
548a10cf76eSAxel Dörfler 		bool supported = false;
549a10cf76eSAxel Dörfler 
550a10cf76eSAxel Dörfler 		for( j = 0; j < fModeListCount; ++j ) {
551a10cf76eSAxel Dörfler 			if( width == fModeList[j].virtual_width &&
552a10cf76eSAxel Dörfler 				height == fModeList[j].virtual_height &&
553a10cf76eSAxel Dörfler 				refresh_list[i].refresh * 10 == getModeRefresh10( &fModeList[j] ))
554a10cf76eSAxel Dörfler 			{
555a10cf76eSAxel Dörfler 				supported = true;
556a10cf76eSAxel Dörfler 				break;
557a10cf76eSAxel Dörfler 			}
558a10cf76eSAxel Dörfler 		}
559a10cf76eSAxel Dörfler 
560a10cf76eSAxel Dörfler 		item = fRefreshMenu->ItemAt( i );
561a10cf76eSAxel Dörfler 		if( item )
562a10cf76eSAxel Dörfler 			item->SetEnabled( supported );
563a10cf76eSAxel Dörfler 	}
564a10cf76eSAxel Dörfler */
565a10cf76eSAxel Dörfler }
566a10cf76eSAxel Dörfler 
567a10cf76eSAxel Dörfler 
568a10cf76eSAxel Dörfler /** activate appropriate menu item according to selected refresh rate */
569a10cf76eSAxel Dörfler 
570a10cf76eSAxel Dörfler void
571a10cf76eSAxel Dörfler ScreenWindow::UpdateRefreshControl()
572a10cf76eSAxel Dörfler {
573a10cf76eSAxel Dörfler 	BString string;
574a10cf76eSAxel Dörfler 	refresh_rate_to_string(fSelected.refresh, string);
575a10cf76eSAxel Dörfler 
576a10cf76eSAxel Dörfler 	BMenuItem* item = fRefreshMenu->FindItem(string.String());
577a10cf76eSAxel Dörfler 	if (item) {
578a10cf76eSAxel Dörfler 		if (!item->IsMarked())
579a10cf76eSAxel Dörfler 			item->SetMarked(true);
580a10cf76eSAxel Dörfler 		// "Other…" items only contains a refresh rate when active
581a10cf76eSAxel Dörfler 		fOtherRefresh->SetLabel("Other…");
582a10cf76eSAxel Dörfler 		return;
583a10cf76eSAxel Dörfler 	}
584a10cf76eSAxel Dörfler 
585a10cf76eSAxel Dörfler 	// this is a non-standard refresh rate
586a10cf76eSAxel Dörfler 
587a10cf76eSAxel Dörfler 	fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh);
588a10cf76eSAxel Dörfler 	fOtherRefresh->SetMarked(true);
589a10cf76eSAxel Dörfler 
590a10cf76eSAxel Dörfler 	fRefreshMenu->Superitem()->SetLabel(string.String());
591a10cf76eSAxel Dörfler 
592a10cf76eSAxel Dörfler 	string.Append("/Other" B_UTF8_ELLIPSIS);
593a10cf76eSAxel Dörfler 	fOtherRefresh->SetLabel(string.String());
594a10cf76eSAxel Dörfler }
595a10cf76eSAxel Dörfler 
596a10cf76eSAxel Dörfler 
597a10cf76eSAxel Dörfler void
598a10cf76eSAxel Dörfler ScreenWindow::UpdateMonitorView()
599a10cf76eSAxel Dörfler {
600a10cf76eSAxel Dörfler 	BMessage updateMessage(UPDATE_DESKTOP_MSG);
601a10cf76eSAxel Dörfler 	updateMessage.AddInt32("width", fSelected.width);
602a10cf76eSAxel Dörfler 	updateMessage.AddInt32("height", fSelected.height);
603a10cf76eSAxel Dörfler 
604a10cf76eSAxel Dörfler 	PostMessage(&updateMessage, fMonitorView);
605a10cf76eSAxel Dörfler }
606a10cf76eSAxel Dörfler 
607a10cf76eSAxel Dörfler 
608a10cf76eSAxel Dörfler void
609a10cf76eSAxel Dörfler ScreenWindow::UpdateControls()
610a10cf76eSAxel Dörfler {
611a10cf76eSAxel Dörfler 	BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays);
612a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
613a10cf76eSAxel Dörfler 		item->SetMarked(true);
614a10cf76eSAxel Dörfler 
615a10cf76eSAxel Dörfler 	item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel);
616a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
617a10cf76eSAxel Dörfler 		item->SetMarked(true);
618a10cf76eSAxel Dörfler 
619a10cf76eSAxel Dörfler 	for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) {
620a10cf76eSAxel Dörfler 		item = fTVStandardMenu->ItemAt(i);
621a10cf76eSAxel Dörfler 
622a10cf76eSAxel Dörfler 		uint32 tvStandard;
623a10cf76eSAxel Dörfler 		item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard);
624a10cf76eSAxel Dörfler 		if (tvStandard == fSelected.tv_standard) {
625a10cf76eSAxel Dörfler 			if (!item->IsMarked())
626a10cf76eSAxel Dörfler 				item->SetMarked(true);
627a10cf76eSAxel Dörfler 			break;
628a10cf76eSAxel Dörfler 		}
629a10cf76eSAxel Dörfler 	}
630a10cf76eSAxel Dörfler 
631a10cf76eSAxel Dörfler 	CheckResolutionMenu();
632a10cf76eSAxel Dörfler 	CheckColorMenu();
633a10cf76eSAxel Dörfler 	CheckRefreshMenu();
634a10cf76eSAxel Dörfler 
635a10cf76eSAxel Dörfler 	BString string;
636a10cf76eSAxel Dörfler 	resolution_to_string(fSelected, string);
637a10cf76eSAxel Dörfler 	item = fResolutionMenu->FindItem(string.String());
638a10cf76eSAxel Dörfler 
639a10cf76eSAxel Dörfler 	if (item != NULL) {
640a10cf76eSAxel Dörfler 		if (!item->IsMarked())
641a10cf76eSAxel Dörfler 			item->SetMarked(true);
642a10cf76eSAxel Dörfler 	} else {
643a10cf76eSAxel Dörfler 		// this is bad luck - if mode has been set via screen references,
644a10cf76eSAxel Dörfler 		// this case cannot occur; there are three possible solutions:
645a10cf76eSAxel Dörfler 		// 1. add a new resolution to list
646a10cf76eSAxel Dörfler 		//    - we had to remove it as soon as a "valid" one is selected
647a10cf76eSAxel Dörfler 		//    - we don't know which frequencies/bit depths are supported
648a10cf76eSAxel Dörfler 		//    - as long as we haven't the GMT formula to create
649a10cf76eSAxel Dörfler 		//      parameters for any resolution given, we cannot
650a10cf76eSAxel Dörfler 		//      really set current mode - it's just not in the list
651a10cf76eSAxel Dörfler 		// 2. choose nearest resolution
652a10cf76eSAxel Dörfler 		//    - probably a good idea, but implies coding and testing
653a10cf76eSAxel Dörfler 		// 3. choose lowest resolution
654a10cf76eSAxel Dörfler 		//    - do you really think we are so lazy? yes, we are
655a10cf76eSAxel Dörfler 		item = fResolutionMenu->ItemAt(0);
656a10cf76eSAxel Dörfler 		if (item)
657a10cf76eSAxel Dörfler 			item->SetMarked(true);
658a10cf76eSAxel Dörfler 
659a10cf76eSAxel Dörfler 		// okay - at least we set menu label to active resolution
660a10cf76eSAxel Dörfler 		fResolutionMenu->Superitem()->SetLabel(string.String());
661a10cf76eSAxel Dörfler 	}
662a10cf76eSAxel Dörfler 
663a10cf76eSAxel Dörfler 	// mark active combine mode
664a10cf76eSAxel Dörfler 	for (int32 i = 0; i < kCombineModeCount; i++) {
665a10cf76eSAxel Dörfler 		if (kCombineModes[i].mode == fSelected.combine) {
666a10cf76eSAxel Dörfler 			item = fCombineMenu->ItemAt(i);
667a10cf76eSAxel Dörfler 			if (item && !item->IsMarked())
668a10cf76eSAxel Dörfler 				item->SetMarked(true);
669a10cf76eSAxel Dörfler 			break;
670a10cf76eSAxel Dörfler 		}
671a10cf76eSAxel Dörfler 	}
672a10cf76eSAxel Dörfler 
673a10cf76eSAxel Dörfler 	item = fColorsMenu->ItemAt(0);
674a10cf76eSAxel Dörfler 
675a10cf76eSAxel Dörfler 	for (int32 i = kColorSpaceCount; i-- > 0;) {
676a10cf76eSAxel Dörfler 		if (kColorSpaces[i].space == fSelected.space) {
677a10cf76eSAxel Dörfler 			item = fColorsMenu->ItemAt(i);
678a10cf76eSAxel Dörfler 			break;
679a10cf76eSAxel Dörfler 		}
680a10cf76eSAxel Dörfler 	}
681a10cf76eSAxel Dörfler 
682a10cf76eSAxel Dörfler 	if (item && !item->IsMarked())
683a10cf76eSAxel Dörfler 		item->SetMarked(true);
684a10cf76eSAxel Dörfler 
685a10cf76eSAxel Dörfler 	string.Truncate(0);
686a10cf76eSAxel Dörfler 	string << fSelected.BitsPerPixel() << " Bits/Pixel";
687a10cf76eSAxel Dörfler 	if (string != fColorsMenu->Superitem()->Label())
688a10cf76eSAxel Dörfler 		fColorsMenu->Superitem()->SetLabel(string.String());
689a10cf76eSAxel Dörfler 
690a10cf76eSAxel Dörfler 	UpdateMonitorView();
691a10cf76eSAxel Dörfler 	UpdateRefreshControl();
692a10cf76eSAxel Dörfler 
693a10cf76eSAxel Dörfler 	CheckApplyEnabled();
694a10cf76eSAxel Dörfler }
695a10cf76eSAxel Dörfler 
696a10cf76eSAxel Dörfler 
697a10cf76eSAxel Dörfler /** reflect active mode in chosen settings */
698a10cf76eSAxel Dörfler 
699a10cf76eSAxel Dörfler void
700a10cf76eSAxel Dörfler ScreenWindow::UpdateActiveMode()
701a10cf76eSAxel Dörfler {
702a10cf76eSAxel Dörfler 	// usually, this function gets called after a mode
703a10cf76eSAxel Dörfler 	// has been set manually; still, as the graphics driver
704a10cf76eSAxel Dörfler 	// is free to fiddle with mode passed, we better ask
705a10cf76eSAxel Dörfler 	// what kind of mode we actually got
706a10cf76eSAxel Dörfler 	fScreenMode.Get(fActive);
707a10cf76eSAxel Dörfler 	fSelected = fActive;
708a10cf76eSAxel Dörfler 
709a10cf76eSAxel Dörfler 	UpdateControls();
710a10cf76eSAxel Dörfler }
711a10cf76eSAxel Dörfler 
712a10cf76eSAxel Dörfler 
713a10cf76eSAxel Dörfler void
714a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode)
715a10cf76eSAxel Dörfler {
716a10cf76eSAxel Dörfler 	// move window on screen, if necessary
717a10cf76eSAxel Dörfler 	if (frame.right <= Frame().right
718a10cf76eSAxel Dörfler 		&& frame.bottom <= Frame().bottom) {
719a10cf76eSAxel Dörfler 		MoveTo((frame.Width() - Frame().Width()) / 2,
720a10cf76eSAxel Dörfler 			(frame.Height() - Frame().Height()) / 2);
721a10cf76eSAxel Dörfler 	}
722a10cf76eSAxel Dörfler }
723a10cf76eSAxel Dörfler 
724a10cf76eSAxel Dörfler 
725a10cf76eSAxel Dörfler void
726a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state)
727a10cf76eSAxel Dörfler {
728a10cf76eSAxel Dörfler 	if (fChangingAllWorkspaces) {
729a10cf76eSAxel Dörfler 		// we're currently changing all workspaces, so there is no need
730a10cf76eSAxel Dörfler 		// to update the interface
731a10cf76eSAxel Dörfler 		return;
732a10cf76eSAxel Dörfler 	}
733a10cf76eSAxel Dörfler 
734a10cf76eSAxel Dörfler 	fScreenMode.Get(fOriginal);
735a10cf76eSAxel Dörfler 	fScreenMode.UpdateOriginalMode();
736a10cf76eSAxel Dörfler 
737a10cf76eSAxel Dörfler 	// only override current settings if they have not been changed yet
738a10cf76eSAxel Dörfler 	if (fSelected == fActive)
739a10cf76eSAxel Dörfler 		UpdateActiveMode();
740a10cf76eSAxel Dörfler 
7416edaa0f6SStefano Ceccherini 	BMessage message(UPDATE_DESKTOP_COLOR_MSG);
7426edaa0f6SStefano Ceccherini 	PostMessage(&message, fMonitorView);
743a10cf76eSAxel Dörfler }
744a10cf76eSAxel Dörfler 
745a10cf76eSAxel Dörfler 
746a10cf76eSAxel Dörfler void
747a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message)
748a10cf76eSAxel Dörfler {
749a10cf76eSAxel Dörfler 	switch (message->what) {
750a10cf76eSAxel Dörfler 		case WORKSPACE_CHECK_MSG:
751a10cf76eSAxel Dörfler 			CheckApplyEnabled();
752a10cf76eSAxel Dörfler 			break;
753a10cf76eSAxel Dörfler 
754a10cf76eSAxel Dörfler 		case POP_WORKSPACE_CHANGED_MSG:
755a10cf76eSAxel Dörfler 		{
756a10cf76eSAxel Dörfler 			int32 index;
757a10cf76eSAxel Dörfler 			if (message->FindInt32("index", &index) == B_OK)
758a10cf76eSAxel Dörfler 				set_workspace_count(index + 1);
759a10cf76eSAxel Dörfler 			break;
760a10cf76eSAxel Dörfler 		}
761a10cf76eSAxel Dörfler 
762a10cf76eSAxel Dörfler 		case POP_RESOLUTION_MSG:
763a10cf76eSAxel Dörfler 		{
764a10cf76eSAxel Dörfler 			message->FindInt32("width", &fSelected.width);
765a10cf76eSAxel Dörfler 			message->FindInt32("height", &fSelected.height);
766a10cf76eSAxel Dörfler 
767a10cf76eSAxel Dörfler 			CheckColorMenu();
768a10cf76eSAxel Dörfler 			CheckRefreshMenu();
769a10cf76eSAxel Dörfler 
770a10cf76eSAxel Dörfler 			UpdateMonitorView();
771a10cf76eSAxel Dörfler 			UpdateRefreshControl();
772a10cf76eSAxel Dörfler 
773a10cf76eSAxel Dörfler 			CheckApplyEnabled();
774a10cf76eSAxel Dörfler 			break;
775a10cf76eSAxel Dörfler 		}
776a10cf76eSAxel Dörfler 
777a10cf76eSAxel Dörfler 		case POP_COLORS_MSG:
778a10cf76eSAxel Dörfler 		{
779a10cf76eSAxel Dörfler 			message->FindInt32("space", (int32 *)&fSelected.space);
780a10cf76eSAxel Dörfler 
781a10cf76eSAxel Dörfler 			BString string;
782a10cf76eSAxel Dörfler 			string << fSelected.BitsPerPixel() << " Bits/Pixel";
783a10cf76eSAxel Dörfler 			fColorsMenu->Superitem()->SetLabel(string.String());
784a10cf76eSAxel Dörfler 
785a10cf76eSAxel Dörfler 			CheckApplyEnabled();
786a10cf76eSAxel Dörfler 			break;
787a10cf76eSAxel Dörfler 		}
788a10cf76eSAxel Dörfler 
789a10cf76eSAxel Dörfler 		case POP_REFRESH_MSG:
790a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
791a10cf76eSAxel Dörfler 			fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS);
792a10cf76eSAxel Dörfler 				// revert "Other…" label - it might have had a refresh rate prefix
793a10cf76eSAxel Dörfler 
794a10cf76eSAxel Dörfler 			CheckApplyEnabled();
795a10cf76eSAxel Dörfler 			break;
796a10cf76eSAxel Dörfler 
797a10cf76eSAxel Dörfler 		case POP_OTHER_REFRESH_MSG:
798a10cf76eSAxel Dörfler 		{
799a10cf76eSAxel Dörfler 			// make sure menu shows something usefull
800a10cf76eSAxel Dörfler 			UpdateRefreshControl();
801a10cf76eSAxel Dörfler 
802a10cf76eSAxel Dörfler 			BRect frame(Frame());
803a10cf76eSAxel Dörfler 			RefreshWindow *fRefreshWindow = new RefreshWindow(BRect(frame.left + 201.0,
804a10cf76eSAxel Dörfler 				frame.top + 34.0, frame.left + 509.0, frame.top + 169.0),
805a10cf76eSAxel Dörfler 				int32(fSelected.refresh * 10));
806a10cf76eSAxel Dörfler 			fRefreshWindow->Show();
807a10cf76eSAxel Dörfler 			break;
808a10cf76eSAxel Dörfler 		}
809a10cf76eSAxel Dörfler 
810a10cf76eSAxel Dörfler 		case SET_CUSTOM_REFRESH_MSG:
811a10cf76eSAxel Dörfler 		{
812a10cf76eSAxel Dörfler 			// user pressed "done" in "Other…" refresh dialog;
813a10cf76eSAxel Dörfler 			// select the refresh rate chosen
814a10cf76eSAxel Dörfler 			message->FindFloat("refresh", &fSelected.refresh);
815a10cf76eSAxel Dörfler 
816a10cf76eSAxel Dörfler 			UpdateRefreshControl();
817a10cf76eSAxel Dörfler 			CheckApplyEnabled();
818a10cf76eSAxel Dörfler 			break;
819a10cf76eSAxel Dörfler 		}
820a10cf76eSAxel Dörfler 
821a10cf76eSAxel Dörfler 		case POP_COMBINE_DISPLAYS_MSG:
822a10cf76eSAxel Dörfler 		{
823a10cf76eSAxel Dörfler 			// new combine mode has bee chosen
824a10cf76eSAxel Dörfler 			int32 mode;
825a10cf76eSAxel Dörfler 			if (message->FindInt32("mode", &mode) == B_OK)
826a10cf76eSAxel Dörfler 				fSelected.combine = (combine_mode)mode;
827a10cf76eSAxel Dörfler 
828a10cf76eSAxel Dörfler 			CheckResolutionMenu();
829a10cf76eSAxel Dörfler 			CheckApplyEnabled();
830a10cf76eSAxel Dörfler 			break;
831a10cf76eSAxel Dörfler 		}
832a10cf76eSAxel Dörfler 
833a10cf76eSAxel Dörfler 		case POP_SWAP_DISPLAYS_MSG:
834a10cf76eSAxel Dörfler 			message->FindBool("swap", &fSelected.swap_displays);
835a10cf76eSAxel Dörfler 			CheckApplyEnabled();
836a10cf76eSAxel Dörfler 			break;
837a10cf76eSAxel Dörfler 
838a10cf76eSAxel Dörfler 		case POP_USE_LAPTOP_PANEL_MSG:
839a10cf76eSAxel Dörfler 			message->FindBool("use", &fSelected.use_laptop_panel);
840a10cf76eSAxel Dörfler 			CheckApplyEnabled();
841a10cf76eSAxel Dörfler 			break;
842a10cf76eSAxel Dörfler 
843a10cf76eSAxel Dörfler 		case POP_TV_STANDARD_MSG:
844a10cf76eSAxel Dörfler 			message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard);
845a10cf76eSAxel Dörfler 			CheckApplyEnabled();
846a10cf76eSAxel Dörfler 			break;
847a10cf76eSAxel Dörfler 
848a10cf76eSAxel Dörfler 		case BUTTON_DEFAULTS_MSG:
849a10cf76eSAxel Dörfler 		{
850a10cf76eSAxel Dörfler 			fSelected.width = 640;
851a10cf76eSAxel Dörfler 			fSelected.height = 480;
852a10cf76eSAxel Dörfler 			fSelected.space = B_CMAP8;
853a10cf76eSAxel Dörfler 			fSelected.refresh = 60.0;
854a10cf76eSAxel Dörfler 			fSelected.combine = kCombineDisable;
855a10cf76eSAxel Dörfler 			fSelected.swap_displays = false;
856a10cf76eSAxel Dörfler 			fSelected.use_laptop_panel = false;
857a10cf76eSAxel Dörfler 			fSelected.tv_standard = 0;
858a10cf76eSAxel Dörfler 
859a10cf76eSAxel Dörfler 			UpdateControls();
860a10cf76eSAxel Dörfler 			break;
861a10cf76eSAxel Dörfler 		}
862a10cf76eSAxel Dörfler 
863a10cf76eSAxel Dörfler 		case BUTTON_REVERT_MSG:
864a10cf76eSAxel Dörfler 		case SET_INITIAL_MODE_MSG:
865a10cf76eSAxel Dörfler 			fScreenMode.Revert();
866a10cf76eSAxel Dörfler 			UpdateActiveMode();
867a10cf76eSAxel Dörfler 			break;
868a10cf76eSAxel Dörfler 
869a10cf76eSAxel Dörfler 		case BUTTON_APPLY_MSG:
870a10cf76eSAxel Dörfler 			Apply();
871a10cf76eSAxel Dörfler 			break;
872a10cf76eSAxel Dörfler 
873a10cf76eSAxel Dörfler 		case MAKE_INITIAL_MSG: {
874a10cf76eSAxel Dörfler 			// user pressed "keep" in confirmation box;
875a10cf76eSAxel Dörfler 			// select this mode in dialog and mark it as
876a10cf76eSAxel Dörfler 			// previous mode; if "all workspaces" is selected,
877a10cf76eSAxel Dörfler 			// distribute mode to all workspaces
878a10cf76eSAxel Dörfler 
879a10cf76eSAxel Dörfler 			// use the mode that has eventually been set and
880a10cf76eSAxel Dörfler 			// thus we know to be working; it can differ from
881a10cf76eSAxel Dörfler 			// the mode selected by user due to hardware limitation
882a10cf76eSAxel Dörfler 			display_mode newMode;
883a10cf76eSAxel Dörfler 			BScreen screen(this);
884a10cf76eSAxel Dörfler 			screen.GetMode(&newMode);
885a10cf76eSAxel Dörfler 
886a10cf76eSAxel Dörfler 			if (fAllWorkspacesItem->IsMarked()) {
887a10cf76eSAxel Dörfler 				int32 originatingWorkspace;
888a10cf76eSAxel Dörfler 
889a10cf76eSAxel Dörfler 				// the original panel activates each workspace in turn;
890a10cf76eSAxel Dörfler 				// this is disguisting and there is a SetMode
891a10cf76eSAxel Dörfler 				// variant that accepts a workspace id, so let's take
892a10cf76eSAxel Dörfler 				// this one
893a10cf76eSAxel Dörfler 				originatingWorkspace = current_workspace();
894a10cf76eSAxel Dörfler 
895a10cf76eSAxel Dörfler 				// well, this "cannot be reverted" message is not
896a10cf76eSAxel Dörfler 				// entirely true - at least, you can revert it
897a10cf76eSAxel Dörfler 				// for current workspace; to not overwrite original
898a10cf76eSAxel Dörfler 				// mode during workspace switch, we use this flag
899a10cf76eSAxel Dörfler 				fChangingAllWorkspaces = true;
900a10cf76eSAxel Dörfler 
901a10cf76eSAxel Dörfler 				for (int32 i = 0; i < count_workspaces(); i++) {
902a10cf76eSAxel Dörfler 					if (i != originatingWorkspace)
903a10cf76eSAxel Dörfler 						screen.SetMode(i, &newMode, true);
904a10cf76eSAxel Dörfler 				}
905a10cf76eSAxel Dörfler 
906a10cf76eSAxel Dörfler 				fChangingAllWorkspaces = false;
907a10cf76eSAxel Dörfler 			}
908a10cf76eSAxel Dörfler 
909a10cf76eSAxel Dörfler 			UpdateActiveMode();
910a10cf76eSAxel Dörfler 			break;
911a10cf76eSAxel Dörfler 		}
912a10cf76eSAxel Dörfler 
913a10cf76eSAxel Dörfler 		default:
914a10cf76eSAxel Dörfler 			BWindow::MessageReceived(message);
915a10cf76eSAxel Dörfler 			break;
916a10cf76eSAxel Dörfler 	}
917a10cf76eSAxel Dörfler }
918a10cf76eSAxel Dörfler 
919a10cf76eSAxel Dörfler 
920a10cf76eSAxel Dörfler bool
921a10cf76eSAxel Dörfler ScreenWindow::CanApply() const
922a10cf76eSAxel Dörfler {
923a10cf76eSAxel Dörfler 	if (fAllWorkspacesItem->IsMarked())
924a10cf76eSAxel Dörfler 		return true;
925a10cf76eSAxel Dörfler 
926a10cf76eSAxel Dörfler 	return fSelected != fActive;
927a10cf76eSAxel Dörfler }
928a10cf76eSAxel Dörfler 
929a10cf76eSAxel Dörfler 
930a10cf76eSAxel Dörfler bool
931a10cf76eSAxel Dörfler ScreenWindow::CanRevert() const
932a10cf76eSAxel Dörfler {
933a10cf76eSAxel Dörfler 	if (fActive != fOriginal)
934a10cf76eSAxel Dörfler 		return true;
935a10cf76eSAxel Dörfler 
936a10cf76eSAxel Dörfler 	return CanApply();
937a10cf76eSAxel Dörfler }
938a10cf76eSAxel Dörfler 
939a10cf76eSAxel Dörfler 
940a10cf76eSAxel Dörfler void
941a10cf76eSAxel Dörfler ScreenWindow::CheckApplyEnabled()
942a10cf76eSAxel Dörfler {
943a10cf76eSAxel Dörfler 	fApplyButton->SetEnabled(CanApply());
944a10cf76eSAxel Dörfler 	fRevertButton->SetEnabled(CanRevert());
945a10cf76eSAxel Dörfler }
946a10cf76eSAxel Dörfler 
947a10cf76eSAxel Dörfler 
948a10cf76eSAxel Dörfler void
949a10cf76eSAxel Dörfler ScreenWindow::Apply()
950a10cf76eSAxel Dörfler {
951a10cf76eSAxel Dörfler 	if (fAllWorkspacesItem->IsMarked()) {
952a10cf76eSAxel Dörfler 		BAlert *workspacesAlert = new BAlert("WorkspacesAlert",
953a10cf76eSAxel Dörfler 			"Change all workspaces? This action cannot be reverted.", "Okay", "Cancel",
954a10cf76eSAxel Dörfler 			NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
955a10cf76eSAxel Dörfler 
956a10cf76eSAxel Dörfler 		if (workspacesAlert->Go() == 1)
957a10cf76eSAxel Dörfler 			return;
958a10cf76eSAxel Dörfler 	}
959a10cf76eSAxel Dörfler 
96007184a9eSAxel Dörfler 	status_t status = fScreenMode.Set(fSelected);
96107184a9eSAxel Dörfler 	if (status == B_OK) {
962a10cf76eSAxel Dörfler 		fActive = fSelected;
963a10cf76eSAxel Dörfler 
964a10cf76eSAxel Dörfler 		// ToDo: only show alert when this is an unknown mode
965a10cf76eSAxel Dörfler 		BWindow* window = new AlertWindow(this);
966a10cf76eSAxel Dörfler 		window->Show();
96707184a9eSAxel Dörfler 	} else {
96807184a9eSAxel Dörfler 		char message[256];
96907184a9eSAxel Dörfler 		snprintf(message, sizeof(message),
97007184a9eSAxel Dörfler 			"The screen mode could not be set:\n\t%s\n", screen_errors(status));
97107184a9eSAxel Dörfler 		BAlert* alert = new BAlert("Screen Alert", message, "Okay", NULL, NULL,
97207184a9eSAxel Dörfler 			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
97307184a9eSAxel Dörfler 		alert->Go();
974a10cf76eSAxel Dörfler 	}
97507184a9eSAxel Dörfler }
97607184a9eSAxel Dörfler 
977