xref: /haiku/src/servers/app/VirtualScreen.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
1 /*
2  * Copyright 2005-2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include "VirtualScreen.h"
11 
12 #include "HWInterface.h"
13 #include "Desktop.h"
14 
15 #include <new>
16 
17 using std::nothrow;
18 
19 
20 VirtualScreen::VirtualScreen()
21 	:
22 	fScreenList(4, true),
23 	fDrawingEngine(NULL),
24 	fHWInterface(NULL)
25 {
26 }
27 
28 
29 VirtualScreen::~VirtualScreen()
30 {
31 	_Reset();
32 }
33 
34 
35 void
36 VirtualScreen::_Reset()
37 {
38 	ScreenList list;
39 	for (int32 i = 0; i < fScreenList.CountItems(); i++) {
40 		screen_item* item = fScreenList.ItemAt(i);
41 
42 		list.AddItem(item->screen);
43 	}
44 
45 	gScreenManager->ReleaseScreens(list);
46 	fScreenList.MakeEmpty();
47 	fSettings.MakeEmpty();
48 
49 	fFrame.Set(0, 0, 0, 0);
50 	fDrawingEngine = NULL;
51 	fHWInterface = NULL;
52 }
53 
54 
55 status_t
56 VirtualScreen::RestoreConfiguration(Desktop& desktop, const BMessage* settings)
57 {
58 	_Reset();
59 
60 	// Copy current Desktop workspace settings
61 	if (settings)
62 		fSettings = *settings;
63 
64 	ScreenList list;
65 	status_t status = gScreenManager->AcquireScreens(&desktop, NULL, 0, false, list);
66 	if (status < B_OK) {
67 		// TODO: we would try again here with force == true
68 		return status;
69 	}
70 
71 	for (int32 i = 0; i < list.CountItems(); i++) {
72 		Screen* screen = list.ItemAt(i);
73 
74 		AddScreen(screen);
75 	}
76 
77 	return B_OK;
78 }
79 
80 
81 status_t
82 VirtualScreen::StoreConfiguration(BMessage& settings)
83 {
84 	for (int32 i = 0; i < fScreenList.CountItems(); i++) {
85 		screen_item* item = fScreenList.ItemAt(i);
86 		Screen* screen = item->screen;
87 		if (!screen->IsDefaultMode())
88 			continue;
89 
90 		BMessage screenSettings;
91 		screenSettings.AddInt32("id", screen->ID());
92 		//screenSettings.AddString("name", "-");
93 		screenSettings.AddRect("frame", item->frame);
94 
95 		// TODO: or just store a display_mode completely?
96 		uint16 width, height;
97 		uint32 colorSpace;
98 		float frequency;
99 		screen->GetMode(width, height, colorSpace, frequency);
100 
101 		screenSettings.AddInt32("width", width);
102 		screenSettings.AddInt32("height", height);
103 		screenSettings.AddInt32("color space", colorSpace);
104 		screenSettings.AddFloat("frequency", frequency);
105 
106 		settings.AddMessage("screen", &screenSettings);
107 	}
108 
109 	return B_OK;
110 }
111 
112 
113 status_t
114 VirtualScreen::AddScreen(Screen* screen)
115 {
116 	screen_item* item = new(nothrow) screen_item;
117 	if (item == NULL)
118 		return B_NO_MEMORY;
119 
120 	item->screen = screen;
121 
122 	status_t status = B_ERROR;
123 	BMessage settings;
124 	if (_FindConfiguration(screen, settings) == B_OK) {
125 		// we found settings for this screen, and try to apply them now
126 		int32 width, height, colorSpace;
127 		float frequency;
128 		if (settings.FindInt32("width", &width) == B_OK
129 			&& settings.FindInt32("height", &height) == B_OK
130 			&& settings.FindInt32("color space", &colorSpace) == B_OK
131 			&& settings.FindFloat("frequency", &frequency) == B_OK)
132 			status = screen->SetMode(width, height, colorSpace, frequency, true);
133 	}
134 	if (status < B_OK) {
135 		// TODO: more intelligent standard mode (monitor preference, desktop default, ...)
136 		screen->SetMode(800, 600, B_RGB32, 60.f, false);
137 	}
138 
139 	// TODO: this works only for single screen configurations
140 	fDrawingEngine = screen->GetDrawingEngine();
141 	fHWInterface = screen->HWInterface();
142 	fFrame = screen->Frame();
143 
144 	fScreenList.AddItem(item);
145 
146 	return B_OK;
147 }
148 
149 
150 status_t
151 VirtualScreen::RemoveScreen(Screen* screen)
152 {
153 	// not implemented yet (config changes when running)
154 	return B_ERROR;
155 }
156 
157 
158 /*!
159 	Returns the smallest frame that spans over all screens
160 */
161 BRect
162 VirtualScreen::Frame() const
163 {
164 	return fFrame;
165 }
166 
167 
168 Screen*
169 VirtualScreen::ScreenAt(int32 index) const
170 {
171 	screen_item* item = fScreenList.ItemAt(index);
172 	if (item != NULL)
173 		return item->screen;
174 
175 	return NULL;
176 }
177 
178 
179 BRect
180 VirtualScreen::ScreenFrameAt(int32 index) const
181 {
182 	screen_item* item = fScreenList.ItemAt(index);
183 	if (item != NULL)
184 		return item->frame;
185 
186 	return BRect(0, 0, 0, 0);
187 }
188 
189 
190 int32
191 VirtualScreen::CountScreens() const
192 {
193 	return fScreenList.CountItems();
194 }
195 
196 
197 status_t
198 VirtualScreen::_FindConfiguration(Screen* screen, BMessage& settings)
199 {
200 	// TODO: we probably want to identify the resolution by connected monitor,
201 	//		and not the display driver used...
202 	//		For now, we just use the screen ID, which is almost nothing, anyway...
203 
204 	uint32 i = 0;
205 	while (fSettings.FindMessage("screen", i++, &settings) == B_OK) {
206 		int32 id;
207 		if (settings.FindInt32("id", &id) != B_OK
208 			|| screen->ID() != id)
209 			continue;
210 
211 		// we found our match
212 		return B_OK;
213 	}
214 
215 	return B_NAME_NOT_FOUND;
216 }
217 
218