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