xref: /haiku/src/servers/app/VirtualScreen.cpp (revision 0c93c0a807b27096abbfad677436afb7d1712d4a)
1 /*
2  * Copyright 2005-2007, 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 void
159 VirtualScreen::UpdateFrame()
160 {
161 	int32 virtualWidth = 0, virtualHeight = 0;
162 
163 	for (int32 i = 0; i < fScreenList.CountItems(); i++) {
164 		Screen* screen = fScreenList.ItemAt(i)->screen;
165 
166 		uint16 width, height;
167 		uint32 colorSpace;
168 		float frequency;
169 		screen->GetMode(width, height, colorSpace, frequency);
170 
171 		// TODO: compute virtual size depending on the actual screen position!
172 		virtualWidth += width;
173 		virtualHeight += height;
174 	}
175 
176 	fFrame.Set(0, 0, virtualWidth - 1, virtualHeight - 1);
177 }
178 
179 
180 /*!
181 	Returns the smallest frame that spans over all screens
182 */
183 BRect
184 VirtualScreen::Frame() const
185 {
186 	return fFrame;
187 }
188 
189 
190 Screen*
191 VirtualScreen::ScreenAt(int32 index) const
192 {
193 	screen_item* item = fScreenList.ItemAt(index);
194 	if (item != NULL)
195 		return item->screen;
196 
197 	return NULL;
198 }
199 
200 
201 BRect
202 VirtualScreen::ScreenFrameAt(int32 index) const
203 {
204 	screen_item* item = fScreenList.ItemAt(index);
205 	if (item != NULL)
206 		return item->frame;
207 
208 	return BRect(0, 0, 0, 0);
209 }
210 
211 
212 int32
213 VirtualScreen::CountScreens() const
214 {
215 	return fScreenList.CountItems();
216 }
217 
218 
219 status_t
220 VirtualScreen::_FindConfiguration(Screen* screen, BMessage& settings)
221 {
222 	// TODO: we probably want to identify the resolution by connected monitor,
223 	//		and not the display driver used...
224 	//		For now, we just use the screen ID, which is almost nothing, anyway...
225 
226 	uint32 i = 0;
227 	while (fSettings.FindMessage("screen", i++, &settings) == B_OK) {
228 		int32 id;
229 		if (settings.FindInt32("id", &id) != B_OK
230 			|| screen->ID() != id)
231 			continue;
232 
233 		// we found our match
234 		return B_OK;
235 	}
236 
237 	return B_NAME_NOT_FOUND;
238 }
239 
240