xref: /haiku/src/kits/interface/PrivateScreen.cpp (revision c27844865341578ec602735e06ecba0bd188cdeb)
1a817d6adSAxel Dörfler /*
257a6c095SAxel Dörfler  * Copyright 2002-2006, Haiku Inc.
3a817d6adSAxel Dörfler  * Distributed under the terms of the MIT License.
4a817d6adSAxel Dörfler  *
5a817d6adSAxel Dörfler  * Authors:
6a817d6adSAxel Dörfler  *		Stefano Ceccherini (burton666@libero.it)
7a817d6adSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
8a817d6adSAxel Dörfler  */
9a817d6adSAxel Dörfler 
1057a6c095SAxel Dörfler /*!
1157a6c095SAxel Dörfler 	BPrivateScreen is the class which does the real work for
1257a6c095SAxel Dörfler 	the proxy class BScreen (it interacts with the app_server).
13a817d6adSAxel Dörfler */
14a817d6adSAxel Dörfler 
15a817d6adSAxel Dörfler 
16d9525baaSAxel Dörfler #include "AppMisc.h"
17466871ccSAxel Dörfler #include "AppServerLink.h"
18466871ccSAxel Dörfler #include "PrivateScreen.h"
19466871ccSAxel Dörfler #include "ServerProtocol.h"
20466871ccSAxel Dörfler 
21*c2784486SAxel Dörfler #include <new>
22*c2784486SAxel Dörfler #include <stdlib.h>
23*c2784486SAxel Dörfler 
2457a6c095SAxel Dörfler #include <Application.h>
25a817d6adSAxel Dörfler #include <Autolock.h>
2616046321SStefano Ceccherini #include <Bitmap.h>
278eae8b05SStefano Ceccherini #include <Locker.h>
28b66d7537SAxel Dörfler #include <ObjectList.h>
29624df6c6SStefano Ceccherini #include <Window.h>
30314a1024SStefano Ceccherini 
31624df6c6SStefano Ceccherini 
32*c2784486SAxel Dörfler using namespace BPrivate;
33624df6c6SStefano Ceccherini 
34b66d7537SAxel Dörfler static BObjectList<BPrivateScreen> sScreens(2, true);
358eae8b05SStefano Ceccherini 
368eae8b05SStefano Ceccherini // used to synchronize creation/deletion of the sScreen object
378eae8b05SStefano Ceccherini static BLocker sScreenLock("screen lock");
38624df6c6SStefano Ceccherini 
39624df6c6SStefano Ceccherini 
40624df6c6SStefano Ceccherini BPrivateScreen *
41b66d7537SAxel Dörfler BPrivateScreen::Get(BWindow *window)
42624df6c6SStefano Ceccherini {
43d9525baaSAxel Dörfler 	screen_id id = B_MAIN_SCREEN_ID;
44d9525baaSAxel Dörfler 
45d9525baaSAxel Dörfler 	if (window != NULL) {
46d9525baaSAxel Dörfler 		BPrivate::AppServerLink link;
47d9525baaSAxel Dörfler 		link.StartMessage(AS_GET_SCREEN_ID_FROM_WINDOW);
48d9525baaSAxel Dörfler 		link.Attach<int32>(_get_object_token_(window));
49d9525baaSAxel Dörfler 
50d9525baaSAxel Dörfler 		status_t status;
51d9525baaSAxel Dörfler 		if (link.FlushWithReply(status) == B_OK && status == B_OK)
52d9525baaSAxel Dörfler 			link.Read<screen_id>(&id);
53d9525baaSAxel Dörfler 	}
54d9525baaSAxel Dörfler 
55b66d7537SAxel Dörfler 	return _Get(id, false);
56624df6c6SStefano Ceccherini }
57624df6c6SStefano Ceccherini 
58624df6c6SStefano Ceccherini 
59624df6c6SStefano Ceccherini BPrivateScreen *
60b66d7537SAxel Dörfler BPrivateScreen::Get(screen_id id)
61b66d7537SAxel Dörfler {
62b66d7537SAxel Dörfler 	return _Get(id, true);
63b66d7537SAxel Dörfler }
64b66d7537SAxel Dörfler 
65b66d7537SAxel Dörfler 
66b66d7537SAxel Dörfler BPrivateScreen *
67b66d7537SAxel Dörfler BPrivateScreen::_Get(screen_id id, bool check)
68624df6c6SStefano Ceccherini {
6957a6c095SAxel Dörfler 	// Nothing works without an app_server connection
7057a6c095SAxel Dörfler 	if (be_app == NULL)
7157a6c095SAxel Dörfler 		return NULL;
7257a6c095SAxel Dörfler 
73a817d6adSAxel Dörfler 	BAutolock locker(sScreenLock);
748eae8b05SStefano Ceccherini 
75b66d7537SAxel Dörfler 	// search for the screen ID
76b66d7537SAxel Dörfler 
77b66d7537SAxel Dörfler 	for (int32 i = sScreens.CountItems(); i-- > 0;) {
78b66d7537SAxel Dörfler 		BPrivateScreen* screen = sScreens.ItemAt(i);
79b66d7537SAxel Dörfler 
80b66d7537SAxel Dörfler 		if (screen->ID().id == id.id) {
81b66d7537SAxel Dörfler 			screen->_Acquire();
82b66d7537SAxel Dörfler 			return screen;
83b66d7537SAxel Dörfler 		}
848eae8b05SStefano Ceccherini 	}
858eae8b05SStefano Ceccherini 
86b66d7537SAxel Dörfler 	if (check) {
87b66d7537SAxel Dörfler 		// check if ID is valid
88b66d7537SAxel Dörfler 		if (!_IsValid(id))
89b66d7537SAxel Dörfler 			return NULL;
90b66d7537SAxel Dörfler 	}
91b66d7537SAxel Dörfler 
92b66d7537SAxel Dörfler 	// we need to allocate a new one
93b66d7537SAxel Dörfler 
94b66d7537SAxel Dörfler 	BPrivateScreen* screen = new (std::nothrow) BPrivateScreen(id);
95b66d7537SAxel Dörfler 	if (screen == NULL)
96b66d7537SAxel Dörfler 		return NULL;
97b66d7537SAxel Dörfler 
98b66d7537SAxel Dörfler 	sScreens.AddItem(screen);
99b66d7537SAxel Dörfler 	return screen;
100624df6c6SStefano Ceccherini }
101624df6c6SStefano Ceccherini 
102624df6c6SStefano Ceccherini 
103624df6c6SStefano Ceccherini void
104b66d7537SAxel Dörfler BPrivateScreen::Put(BPrivateScreen* screen)
105624df6c6SStefano Ceccherini {
106b66d7537SAxel Dörfler 	if (screen == NULL)
107b66d7537SAxel Dörfler 		return;
108b66d7537SAxel Dörfler 
109b66d7537SAxel Dörfler 	BAutolock locker(sScreenLock);
110b66d7537SAxel Dörfler 
111b66d7537SAxel Dörfler 	if (screen->_Release()) {
112b66d7537SAxel Dörfler 		if (screen->ID().id != B_MAIN_SCREEN_ID.id) {
113b66d7537SAxel Dörfler 			// we always keep the main screen object around - it will
114b66d7537SAxel Dörfler 			// never go away, even if you disconnect all monitors.
115b66d7537SAxel Dörfler 			sScreens.RemoveItem(screen);
116b66d7537SAxel Dörfler 		}
117b66d7537SAxel Dörfler 	}
118624df6c6SStefano Ceccherini }
119624df6c6SStefano Ceccherini 
120624df6c6SStefano Ceccherini 
121b66d7537SAxel Dörfler BPrivateScreen*
122b66d7537SAxel Dörfler BPrivateScreen::GetNext(BPrivateScreen* screen)
123624df6c6SStefano Ceccherini {
124b66d7537SAxel Dörfler 	BAutolock locker(sScreenLock);
125b66d7537SAxel Dörfler 
126b66d7537SAxel Dörfler 	screen_id id;
127b66d7537SAxel Dörfler 	status_t status = screen->GetNextID(id);
128b66d7537SAxel Dörfler 	if (status < B_OK)
129b66d7537SAxel Dörfler 		return NULL;
130b66d7537SAxel Dörfler 
131b66d7537SAxel Dörfler 	BPrivateScreen* nextScreen = Get(id);
132b66d7537SAxel Dörfler 	if (nextScreen == NULL)
133b66d7537SAxel Dörfler 		return NULL;
134b66d7537SAxel Dörfler 
135b66d7537SAxel Dörfler 	Put(screen);
136b66d7537SAxel Dörfler 	return nextScreen;
137624df6c6SStefano Ceccherini }
138624df6c6SStefano Ceccherini 
139624df6c6SStefano Ceccherini 
140b66d7537SAxel Dörfler bool
141b66d7537SAxel Dörfler BPrivateScreen::_IsValid(screen_id id)
142b66d7537SAxel Dörfler {
143b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
144b66d7537SAxel Dörfler 	link.StartMessage(AS_VALID_SCREEN_ID);
145b66d7537SAxel Dörfler 	link.Attach<screen_id>(id);
146b66d7537SAxel Dörfler 
147b66d7537SAxel Dörfler 	status_t status;
148b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
149b66d7537SAxel Dörfler 		return false;
150b66d7537SAxel Dörfler 
151b66d7537SAxel Dörfler 	return true;
152b66d7537SAxel Dörfler }
153b66d7537SAxel Dörfler 
154b66d7537SAxel Dörfler 
155b66d7537SAxel Dörfler //	#pragma mark -
156b66d7537SAxel Dörfler 
157b66d7537SAxel Dörfler 
158624df6c6SStefano Ceccherini color_space
159624df6c6SStefano Ceccherini BPrivateScreen::ColorSpace()
160624df6c6SStefano Ceccherini {
161624df6c6SStefano Ceccherini 	display_mode mode;
1621f41d635SStefano Ceccherini 	if (GetMode(B_CURRENT_WORKSPACE, &mode) == B_OK)
163624df6c6SStefano Ceccherini 		return (color_space)mode.space;
164624df6c6SStefano Ceccherini 
165624df6c6SStefano Ceccherini 	return B_NO_COLOR_SPACE;
166624df6c6SStefano Ceccherini }
167624df6c6SStefano Ceccherini 
168624df6c6SStefano Ceccherini 
169624df6c6SStefano Ceccherini BRect
170624df6c6SStefano Ceccherini BPrivateScreen::Frame()
171624df6c6SStefano Ceccherini {
17239ffb980SStefano Ceccherini 	// If something goes wrong, we just return this rectangle.
17339ffb980SStefano Ceccherini 
174b66d7537SAxel Dörfler 	if (system_time() > fLastUpdate + 100000) {
175b66d7537SAxel Dörfler 		// invalidate the settings after 0.1 secs
176b66d7537SAxel Dörfler 		display_mode mode;
177b66d7537SAxel Dörfler 		if (GetMode(B_CURRENT_WORKSPACE, &mode) == B_OK) {
178b66d7537SAxel Dörfler 			fFrame.Set(0, 0, (float)mode.virtual_width - 1,
179b66d7537SAxel Dörfler 				(float)mode.virtual_height - 1);
180b66d7537SAxel Dörfler 			fLastUpdate = system_time();
181b66d7537SAxel Dörfler 		}
182b66d7537SAxel Dörfler 	}
183b66d7537SAxel Dörfler 
184b66d7537SAxel Dörfler 	return fFrame;
185624df6c6SStefano Ceccherini }
186624df6c6SStefano Ceccherini 
187624df6c6SStefano Ceccherini 
188b66d7537SAxel Dörfler bool
189b66d7537SAxel Dörfler BPrivateScreen::IsValid() const
190624df6c6SStefano Ceccherini {
191b66d7537SAxel Dörfler 	return BPrivateScreen::_IsValid(ID());
192b66d7537SAxel Dörfler }
193b66d7537SAxel Dörfler 
194b66d7537SAxel Dörfler 
195b66d7537SAxel Dörfler status_t
196b66d7537SAxel Dörfler BPrivateScreen::GetNextID(screen_id& id)
197b66d7537SAxel Dörfler {
198b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
199b66d7537SAxel Dörfler 	link.StartMessage(AS_GET_NEXT_SCREEN_ID);
200b66d7537SAxel Dörfler 	link.Attach<screen_id>(ID());
201b66d7537SAxel Dörfler 
202b66d7537SAxel Dörfler 	status_t status;
203b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
204b66d7537SAxel Dörfler 		link.Read<screen_id>(&id);
205b66d7537SAxel Dörfler 		return B_OK;
206b66d7537SAxel Dörfler 	}
207b66d7537SAxel Dörfler 
208b66d7537SAxel Dörfler 	return status;
209624df6c6SStefano Ceccherini }
210624df6c6SStefano Ceccherini 
211624df6c6SStefano Ceccherini 
212624df6c6SStefano Ceccherini status_t
213624df6c6SStefano Ceccherini BPrivateScreen::WaitForRetrace(bigtime_t timeout)
214624df6c6SStefano Ceccherini {
215624df6c6SStefano Ceccherini 	// Get the retrace semaphore if it's the first time
216624df6c6SStefano Ceccherini 	// we are called. Cache the value then.
2175ec797a7SStephan Aßmus 	if (!fRetraceSemValid)
218a817d6adSAxel Dörfler 		fRetraceSem = _RetraceSemaphore();
219624df6c6SStefano Ceccherini 
2205ec797a7SStephan Aßmus 	if (fRetraceSem < 0) {
2215ec797a7SStephan Aßmus 		// syncing to retrace is not supported by the accelerant
2225ec797a7SStephan Aßmus 		return fRetraceSem;
2235ec797a7SStephan Aßmus 	}
2245ec797a7SStephan Aßmus 
2255ec797a7SStephan Aßmus 	status_t status;
226624df6c6SStefano Ceccherini 	do {
227624df6c6SStefano Ceccherini 		status = acquire_sem_etc(fRetraceSem, 1, B_RELATIVE_TIMEOUT, timeout);
228624df6c6SStefano Ceccherini 	} while (status == B_INTERRUPTED);
229624df6c6SStefano Ceccherini 
230624df6c6SStefano Ceccherini 	return status;
231624df6c6SStefano Ceccherini }
232624df6c6SStefano Ceccherini 
233624df6c6SStefano Ceccherini 
234624df6c6SStefano Ceccherini uint8
235624df6c6SStefano Ceccherini BPrivateScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
236624df6c6SStefano Ceccherini {
237624df6c6SStefano Ceccherini 	// Looks like this check is necessary
238a817d6adSAxel Dörfler 	if (red == B_TRANSPARENT_COLOR.red
239a817d6adSAxel Dörfler 		&& green == B_TRANSPARENT_COLOR.green
240a817d6adSAxel Dörfler 		&& blue == B_TRANSPARENT_COLOR.blue
241a817d6adSAxel Dörfler 		&& alpha == B_TRANSPARENT_COLOR.alpha)
242624df6c6SStefano Ceccherini 		return B_TRANSPARENT_8_BIT;
243624df6c6SStefano Ceccherini 
2440ef40c5eSMichael Lotz 	uint16 index = ((red & 0xf8) << 7) | ((green & 0xf8) << 2) | (blue >> 3);
245a817d6adSAxel Dörfler 	if (ColorMap())
2462ed35bc8SStefano Ceccherini 		return fColorMap->index_map[index];
247624df6c6SStefano Ceccherini 
248624df6c6SStefano Ceccherini 	return 0;
249624df6c6SStefano Ceccherini }
250624df6c6SStefano Ceccherini 
251624df6c6SStefano Ceccherini 
252624df6c6SStefano Ceccherini rgb_color
253624df6c6SStefano Ceccherini BPrivateScreen::ColorForIndex(const uint8 index)
254624df6c6SStefano Ceccherini {
255a817d6adSAxel Dörfler 	if (ColorMap())
256624df6c6SStefano Ceccherini 		return fColorMap->color_list[index];
257624df6c6SStefano Ceccherini 
258624df6c6SStefano Ceccherini 	return rgb_color();
259624df6c6SStefano Ceccherini }
260624df6c6SStefano Ceccherini 
261624df6c6SStefano Ceccherini 
262624df6c6SStefano Ceccherini uint8
263624df6c6SStefano Ceccherini BPrivateScreen::InvertIndex(uint8 index)
264624df6c6SStefano Ceccherini {
265a817d6adSAxel Dörfler 	if (ColorMap())
266624df6c6SStefano Ceccherini 		return fColorMap->inversion_map[index];
267624df6c6SStefano Ceccherini 
268624df6c6SStefano Ceccherini 	return 0;
269624df6c6SStefano Ceccherini }
270624df6c6SStefano Ceccherini 
271624df6c6SStefano Ceccherini 
272624df6c6SStefano Ceccherini const color_map *
273624df6c6SStefano Ceccherini BPrivateScreen::ColorMap()
274624df6c6SStefano Ceccherini {
275a817d6adSAxel Dörfler 	if (fColorMap == NULL) {
276a817d6adSAxel Dörfler 		BAutolock locker(sScreenLock);
277a817d6adSAxel Dörfler 
278a817d6adSAxel Dörfler 		if (fColorMap != NULL) {
279a817d6adSAxel Dörfler 			// someone could have been faster than us
280a817d6adSAxel Dörfler 			return fColorMap;
281a817d6adSAxel Dörfler 		}
282a817d6adSAxel Dörfler 
283a817d6adSAxel Dörfler 		// TODO: BeOS R5 here gets the colormap pointer
284a817d6adSAxel Dörfler 		// (with BApplication::ro_offset_to_ptr() ?)
285a817d6adSAxel Dörfler 		// which is contained in a shared area created by the server.
286a817d6adSAxel Dörfler 		BPrivate::AppServerLink link;
287a817d6adSAxel Dörfler 		link.StartMessage(AS_SCREEN_GET_COLORMAP);
288a817d6adSAxel Dörfler 		link.Attach<screen_id>(ID());
289a817d6adSAxel Dörfler 
290a817d6adSAxel Dörfler 		status_t status;
291a817d6adSAxel Dörfler 		if (link.FlushWithReply(status) == B_OK && status == B_OK) {
292a817d6adSAxel Dörfler 			fColorMap = (color_map *)malloc(sizeof(color_map));
293a817d6adSAxel Dörfler 			fOwnsColorMap = true;
294a817d6adSAxel Dörfler 			link.Read<color_map>(fColorMap);
295a817d6adSAxel Dörfler 		}
296a817d6adSAxel Dörfler 	}
297a817d6adSAxel Dörfler 
298624df6c6SStefano Ceccherini 	return fColorMap;
299624df6c6SStefano Ceccherini }
300624df6c6SStefano Ceccherini 
301624df6c6SStefano Ceccherini 
302624df6c6SStefano Ceccherini status_t
303466871ccSAxel Dörfler BPrivateScreen::GetBitmap(BBitmap **_bitmap, bool drawCursor, BRect *bounds)
304624df6c6SStefano Ceccherini {
305466871ccSAxel Dörfler 	if (_bitmap == NULL)
30616046321SStefano Ceccherini 		return B_BAD_VALUE;
30716046321SStefano Ceccherini 
308a817d6adSAxel Dörfler 	BRect rect;
309a817d6adSAxel Dörfler 	if (bounds != NULL)
310a817d6adSAxel Dörfler 		rect = *bounds;
311a817d6adSAxel Dörfler 	else
312a817d6adSAxel Dörfler 		rect = Frame();
313a817d6adSAxel Dörfler 
314a817d6adSAxel Dörfler 	BBitmap* bitmap = new (std::nothrow) BBitmap(rect, ColorSpace());
315466871ccSAxel Dörfler 	if (bitmap == NULL)
316466871ccSAxel Dörfler 		return B_NO_MEMORY;
317466871ccSAxel Dörfler 
318466871ccSAxel Dörfler 	status_t status = bitmap->InitCheck();
319466871ccSAxel Dörfler 	if (status == B_OK)
320a817d6adSAxel Dörfler 		status = ReadBitmap(bitmap, drawCursor, &rect);
321466871ccSAxel Dörfler 	if (status != B_OK) {
322466871ccSAxel Dörfler 		delete bitmap;
323466871ccSAxel Dörfler 		return status;
324466871ccSAxel Dörfler 	}
325466871ccSAxel Dörfler 
326466871ccSAxel Dörfler 	*_bitmap = bitmap;
327466871ccSAxel Dörfler 	return B_OK;
328624df6c6SStefano Ceccherini }
329624df6c6SStefano Ceccherini 
330624df6c6SStefano Ceccherini 
331624df6c6SStefano Ceccherini status_t
332a817d6adSAxel Dörfler BPrivateScreen::ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bounds)
333624df6c6SStefano Ceccherini {
33416046321SStefano Ceccherini 	if (bitmap == NULL)
33516046321SStefano Ceccherini 		return B_BAD_VALUE;
33616046321SStefano Ceccherini 
33716046321SStefano Ceccherini 	BRect rect;
338a817d6adSAxel Dörfler 	if (bounds != NULL)
339a817d6adSAxel Dörfler 		rect = *bounds;
34016046321SStefano Ceccherini 	else
34116046321SStefano Ceccherini 		rect = Frame();
34216046321SStefano Ceccherini 
34316046321SStefano Ceccherini 	BPrivate::AppServerLink link;
34416046321SStefano Ceccherini 	link.StartMessage(AS_READ_BITMAP);
3459a44fdc9SAxel Dörfler 	link.Attach<int32>(bitmap->_ServerToken());
34616046321SStefano Ceccherini 	link.Attach<bool>(drawCursor);
34716046321SStefano Ceccherini 	link.Attach<BRect>(rect);
34816046321SStefano Ceccherini 
349a817d6adSAxel Dörfler 	status_t status = B_ERROR;
350a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) < B_OK || status != B_OK)
351a817d6adSAxel Dörfler 		return status;
35216046321SStefano Ceccherini 
35316046321SStefano Ceccherini 	return B_OK;
354624df6c6SStefano Ceccherini }
355624df6c6SStefano Ceccherini 
356624df6c6SStefano Ceccherini 
357624df6c6SStefano Ceccherini rgb_color
35839ffb980SStefano Ceccherini BPrivateScreen::DesktopColor(uint32 workspace)
359624df6c6SStefano Ceccherini {
3603ba7d6f3SAxel Dörfler 	rgb_color color = { 51, 102, 152, 255 };
361dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
3623ba7d6f3SAxel Dörfler 
3633ba7d6f3SAxel Dörfler 	link.StartMessage(AS_GET_DESKTOP_COLOR);
3643f319b33SMichael Lotz 	link.Attach<uint32>(workspace);
3653ba7d6f3SAxel Dörfler 
3663ba7d6f3SAxel Dörfler 	int32 code;
367dd10337fSAxel Dörfler 	if (link.FlushWithReply(code) == B_OK
368a817d6adSAxel Dörfler 		&& code == B_OK)
3693ba7d6f3SAxel Dörfler 		link.Read<rgb_color>(&color);
3703ba7d6f3SAxel Dörfler 
37139ffb980SStefano Ceccherini 	return color;
372624df6c6SStefano Ceccherini }
373624df6c6SStefano Ceccherini 
374624df6c6SStefano Ceccherini 
375624df6c6SStefano Ceccherini void
376a817d6adSAxel Dörfler BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace,
377a817d6adSAxel Dörfler 	bool makeDefault)
378624df6c6SStefano Ceccherini {
379dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
3803ba7d6f3SAxel Dörfler 
3813ba7d6f3SAxel Dörfler 	link.StartMessage(AS_SET_DESKTOP_COLOR);
38239ffb980SStefano Ceccherini 	link.Attach<rgb_color>(color);
3838f9ab4d1SAxel Dörfler 	link.Attach<uint32>(workspace);
38439ffb980SStefano Ceccherini 	link.Attach<bool>(makeDefault);
38539ffb980SStefano Ceccherini 	link.Flush();
386624df6c6SStefano Ceccherini }
387624df6c6SStefano Ceccherini 
388624df6c6SStefano Ceccherini 
389624df6c6SStefano Ceccherini status_t
390c6418981SStefano Ceccherini BPrivateScreen::ProposeMode(display_mode *target,
391c6418981SStefano Ceccherini 	const display_mode *low, const display_mode *high)
392624df6c6SStefano Ceccherini {
393c6418981SStefano Ceccherini 	// We can't return B_BAD_VALUE here, because it's used to indicate
394c6418981SStefano Ceccherini 	// that the mode returned is supported, but it doesn't fall
395c6418981SStefano Ceccherini 	// within the limit (see ProposeMode() documentation)
396c6418981SStefano Ceccherini 	if (target == NULL || low == NULL || high == NULL)
397624df6c6SStefano Ceccherini 		return B_ERROR;
398c6418981SStefano Ceccherini 
399c6418981SStefano Ceccherini 	BPrivate::AppServerLink link;
400c6418981SStefano Ceccherini 	link.StartMessage(AS_PROPOSE_MODE);
401c6418981SStefano Ceccherini 	link.Attach<screen_id>(ID());
402583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*target);
403583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*low);
404583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*high);
405583f6c3eSStefano Ceccherini 
406c6418981SStefano Ceccherini 	status_t status = B_ERROR;
407a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
408c6418981SStefano Ceccherini 		link.Read<display_mode>(target);
409a817d6adSAxel Dörfler 
410a817d6adSAxel Dörfler 		bool withinLimits;
411a817d6adSAxel Dörfler 		link.Read<bool>(&withinLimits);
412a817d6adSAxel Dörfler 		if (!withinLimits)
413a817d6adSAxel Dörfler 			status = B_BAD_VALUE;
414c6418981SStefano Ceccherini 	}
415c6418981SStefano Ceccherini 
416c6418981SStefano Ceccherini 	return status;
417624df6c6SStefano Ceccherini }
418624df6c6SStefano Ceccherini 
419624df6c6SStefano Ceccherini 
420624df6c6SStefano Ceccherini status_t
421a817d6adSAxel Dörfler BPrivateScreen::GetModeList(display_mode **_modeList, uint32 *_count)
422624df6c6SStefano Ceccherini {
423a817d6adSAxel Dörfler 	if (_modeList == NULL || _count == NULL)
42410c5dab8SStefano Ceccherini 		return B_BAD_VALUE;
42510c5dab8SStefano Ceccherini 
42610c5dab8SStefano Ceccherini 	BPrivate::AppServerLink link;
42710c5dab8SStefano Ceccherini 	link.StartMessage(AS_GET_MODE_LIST);
42810c5dab8SStefano Ceccherini 	link.Attach<screen_id>(ID());
429a817d6adSAxel Dörfler 
430a817d6adSAxel Dörfler 	status_t status = B_ERROR;
431a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
43206740743SAxel Dörfler 		uint32 count;
43306740743SAxel Dörfler 		if (link.Read<uint32>(&count) < B_OK)
43406740743SAxel Dörfler 			return B_ERROR;
43506740743SAxel Dörfler 
436a817d6adSAxel Dörfler 		// TODO: this could get too big for the link
43706740743SAxel Dörfler 		int32 size = count * sizeof(display_mode);
43806740743SAxel Dörfler 		display_mode* modeList = (display_mode *)malloc(size);
43906740743SAxel Dörfler 		if (modeList == NULL)
440a817d6adSAxel Dörfler 			return B_NO_MEMORY;
441a817d6adSAxel Dörfler 
44206740743SAxel Dörfler 		if (link.Read(modeList, size) < B_OK) {
44306740743SAxel Dörfler 			free(modeList);
44406740743SAxel Dörfler 			return B_ERROR;
44506740743SAxel Dörfler 		}
44606740743SAxel Dörfler 
44706740743SAxel Dörfler 		*_modeList = modeList;
44806740743SAxel Dörfler 		*_count = count;
44910c5dab8SStefano Ceccherini 	}
45010c5dab8SStefano Ceccherini 
45110c5dab8SStefano Ceccherini 	return status;
452624df6c6SStefano Ceccherini }
453624df6c6SStefano Ceccherini 
454624df6c6SStefano Ceccherini 
455624df6c6SStefano Ceccherini status_t
456624df6c6SStefano Ceccherini BPrivateScreen::GetMode(uint32 workspace, display_mode *mode)
457624df6c6SStefano Ceccherini {
458314a1024SStefano Ceccherini 	if (mode == NULL)
459314a1024SStefano Ceccherini 		return B_BAD_VALUE;
460314a1024SStefano Ceccherini 
461dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
46234c39bf0SStefano Ceccherini 	link.StartMessage(AS_SCREEN_GET_MODE);
46334c39bf0SStefano Ceccherini 	link.Attach<screen_id>(ID());
46439ffb980SStefano Ceccherini 	link.Attach<uint32>(workspace);
465fca6492fSStefano Ceccherini 
46634c39bf0SStefano Ceccherini 	status_t status = B_ERROR;
467a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) != B_OK
468a817d6adSAxel Dörfler 		|| status != B_OK)
46939ffb980SStefano Ceccherini 		return status;
470a817d6adSAxel Dörfler 
471a817d6adSAxel Dörfler 	link.Read<display_mode>(mode);
472a817d6adSAxel Dörfler 	return B_OK;
473624df6c6SStefano Ceccherini }
474624df6c6SStefano Ceccherini 
475624df6c6SStefano Ceccherini 
476624df6c6SStefano Ceccherini status_t
477624df6c6SStefano Ceccherini BPrivateScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault)
478624df6c6SStefano Ceccherini {
479314a1024SStefano Ceccherini 	if (mode == NULL)
480314a1024SStefano Ceccherini 		return B_BAD_VALUE;
481314a1024SStefano Ceccherini 
482dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
483314a1024SStefano Ceccherini 	link.StartMessage(AS_SCREEN_SET_MODE);
484314a1024SStefano Ceccherini 	link.Attach<screen_id>(ID());
48539ffb980SStefano Ceccherini 	link.Attach<uint32>(workspace);
48639ffb980SStefano Ceccherini 	link.Attach<display_mode>(*mode);
48739ffb980SStefano Ceccherini 	link.Attach<bool>(makeDefault);
488314a1024SStefano Ceccherini 
489314a1024SStefano Ceccherini 	status_t status = B_ERROR;
490a817d6adSAxel Dörfler 	link.FlushWithReply(status);
491314a1024SStefano Ceccherini 
49239ffb980SStefano Ceccherini 	return status;
493624df6c6SStefano Ceccherini }
494624df6c6SStefano Ceccherini 
495624df6c6SStefano Ceccherini 
496624df6c6SStefano Ceccherini status_t
497624df6c6SStefano Ceccherini BPrivateScreen::GetDeviceInfo(accelerant_device_info *info)
498624df6c6SStefano Ceccherini {
499c6418981SStefano Ceccherini 	if (info == NULL)
500c6418981SStefano Ceccherini 		return B_BAD_VALUE;
501c6418981SStefano Ceccherini 
502c6418981SStefano Ceccherini 	BPrivate::AppServerLink link;
503c6418981SStefano Ceccherini 	link.StartMessage(AS_GET_ACCELERANT_INFO);
504c6418981SStefano Ceccherini 	link.Attach<screen_id>(ID());
505a817d6adSAxel Dörfler 
506a817d6adSAxel Dörfler 	status_t status = B_ERROR;
507a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
508c6418981SStefano Ceccherini 		link.Read<accelerant_device_info>(info);
509c6418981SStefano Ceccherini 		return B_OK;
510c6418981SStefano Ceccherini 	}
511c6418981SStefano Ceccherini 
512a817d6adSAxel Dörfler 	return status;
513624df6c6SStefano Ceccherini }
514624df6c6SStefano Ceccherini 
515624df6c6SStefano Ceccherini 
516624df6c6SStefano Ceccherini status_t
517*c2784486SAxel Dörfler BPrivateScreen::GetMonitorInfo(monitor_info* info)
518*c2784486SAxel Dörfler {
519*c2784486SAxel Dörfler 	if (info == NULL)
520*c2784486SAxel Dörfler 		return B_BAD_VALUE;
521*c2784486SAxel Dörfler 
522*c2784486SAxel Dörfler 	BPrivate::AppServerLink link;
523*c2784486SAxel Dörfler 	link.StartMessage(AS_GET_MONITOR_INFO);
524*c2784486SAxel Dörfler 	link.Attach<screen_id>(ID());
525*c2784486SAxel Dörfler 
526*c2784486SAxel Dörfler 	status_t status = B_ERROR;
527*c2784486SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
528*c2784486SAxel Dörfler 		link.Read<monitor_info>(info);
529*c2784486SAxel Dörfler 		return B_OK;
530*c2784486SAxel Dörfler 	}
531*c2784486SAxel Dörfler 
532*c2784486SAxel Dörfler 	return status;
533*c2784486SAxel Dörfler }
534*c2784486SAxel Dörfler 
535*c2784486SAxel Dörfler 
536*c2784486SAxel Dörfler status_t
537624df6c6SStefano Ceccherini BPrivateScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
538624df6c6SStefano Ceccherini {
53975de27f8SStefano Ceccherini 	if (mode == NULL || low == NULL || high == NULL)
54075de27f8SStefano Ceccherini 		return B_BAD_VALUE;
54175de27f8SStefano Ceccherini 
54275de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
54375de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_PIXEL_CLOCK_LIMITS);
54475de27f8SStefano Ceccherini 	link.Attach<screen_id>(ID());
54575de27f8SStefano Ceccherini 	link.Attach<display_mode>(*mode);
54675de27f8SStefano Ceccherini 
547a817d6adSAxel Dörfler 	status_t status;
548a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
54975de27f8SStefano Ceccherini 		link.Read<uint32>(low);
55075de27f8SStefano Ceccherini 		link.Read<uint32>(high);
55175de27f8SStefano Ceccherini 		return B_OK;
55275de27f8SStefano Ceccherini 	}
55375de27f8SStefano Ceccherini 
554a817d6adSAxel Dörfler 	return status;
555624df6c6SStefano Ceccherini }
556624df6c6SStefano Ceccherini 
557624df6c6SStefano Ceccherini 
558624df6c6SStefano Ceccherini status_t
559a817d6adSAxel Dörfler BPrivateScreen::GetTimingConstraints(display_timing_constraints *constraints)
560624df6c6SStefano Ceccherini {
561a817d6adSAxel Dörfler 	if (constraints == NULL)
56255b222b0SStefano Ceccherini 		return B_BAD_VALUE;
56355b222b0SStefano Ceccherini 
56475de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
56575de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_TIMING_CONSTRAINTS);
56675de27f8SStefano Ceccherini 	link.Attach<screen_id>(ID());
56775de27f8SStefano Ceccherini 
568a817d6adSAxel Dörfler 	status_t status = B_ERROR;
569a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
570a817d6adSAxel Dörfler 		link.Read<display_timing_constraints>(constraints);
57175de27f8SStefano Ceccherini 		return B_OK;
57275de27f8SStefano Ceccherini 	}
57375de27f8SStefano Ceccherini 
574a817d6adSAxel Dörfler 	return status;
575624df6c6SStefano Ceccherini }
576624df6c6SStefano Ceccherini 
577624df6c6SStefano Ceccherini 
578624df6c6SStefano Ceccherini status_t
579624df6c6SStefano Ceccherini BPrivateScreen::SetDPMS(uint32 dpmsState)
580624df6c6SStefano Ceccherini {
581dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
58255b222b0SStefano Ceccherini 	link.StartMessage(AS_SET_DPMS);
58339ffb980SStefano Ceccherini 	link.Attach<screen_id>(ID());
58439ffb980SStefano Ceccherini 	link.Attach<uint32>(dpmsState);
58555b222b0SStefano Ceccherini 
586a817d6adSAxel Dörfler 	status_t status = B_ERROR;
587a817d6adSAxel Dörfler 	link.FlushWithReply(status);
588a817d6adSAxel Dörfler 
589a817d6adSAxel Dörfler 	return status;
590624df6c6SStefano Ceccherini }
591624df6c6SStefano Ceccherini 
592624df6c6SStefano Ceccherini 
593624df6c6SStefano Ceccherini uint32
594624df6c6SStefano Ceccherini BPrivateScreen::DPMSState()
595624df6c6SStefano Ceccherini {
59639ffb980SStefano Ceccherini 	uint32 state = 0;
59755b222b0SStefano Ceccherini 
598dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
59955b222b0SStefano Ceccherini 	link.StartMessage(AS_GET_DPMS_STATE);
60039ffb980SStefano Ceccherini 	link.Attach<screen_id>(ID());
601a817d6adSAxel Dörfler 
602a817d6adSAxel Dörfler 	status_t status;
603a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
60455b222b0SStefano Ceccherini 		link.Read<uint32>(&state);
60555b222b0SStefano Ceccherini 
60639ffb980SStefano Ceccherini 	return state;
607624df6c6SStefano Ceccherini }
608624df6c6SStefano Ceccherini 
609624df6c6SStefano Ceccherini 
610624df6c6SStefano Ceccherini uint32
611624df6c6SStefano Ceccherini BPrivateScreen::DPMSCapabilites()
612624df6c6SStefano Ceccherini {
61339ffb980SStefano Ceccherini 	uint32 capabilities = 0;
61455b222b0SStefano Ceccherini 
615dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
61655b222b0SStefano Ceccherini 	link.StartMessage(AS_GET_DPMS_CAPABILITIES);
61739ffb980SStefano Ceccherini 	link.Attach<screen_id>(ID());
618a817d6adSAxel Dörfler 
619a817d6adSAxel Dörfler 	status_t status;
620a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
62155b222b0SStefano Ceccherini 		link.Read<uint32>(&capabilities);
62255b222b0SStefano Ceccherini 
62339ffb980SStefano Ceccherini 	return capabilities;
624624df6c6SStefano Ceccherini }
625624df6c6SStefano Ceccherini 
626624df6c6SStefano Ceccherini 
627624df6c6SStefano Ceccherini void *
628624df6c6SStefano Ceccherini BPrivateScreen::BaseAddress()
629624df6c6SStefano Ceccherini {
630b66d7537SAxel Dörfler 	frame_buffer_config config;
631b66d7537SAxel Dörfler 	if (_GetFrameBufferConfig(config) != B_OK)
632624df6c6SStefano Ceccherini 		return NULL;
633b66d7537SAxel Dörfler 
634b66d7537SAxel Dörfler 	return config.frame_buffer;
635624df6c6SStefano Ceccherini }
636624df6c6SStefano Ceccherini 
637624df6c6SStefano Ceccherini 
638624df6c6SStefano Ceccherini uint32
639624df6c6SStefano Ceccherini BPrivateScreen::BytesPerRow()
640624df6c6SStefano Ceccherini {
641b66d7537SAxel Dörfler 	frame_buffer_config config;
642b66d7537SAxel Dörfler 	if (_GetFrameBufferConfig(config) != B_OK)
643624df6c6SStefano Ceccherini 		return 0;
644624df6c6SStefano Ceccherini 
645b66d7537SAxel Dörfler 	return config.bytes_per_row;
646624df6c6SStefano Ceccherini }
647624df6c6SStefano Ceccherini 
648624df6c6SStefano Ceccherini 
649a817d6adSAxel Dörfler // #pragma mark - private methods
65075de27f8SStefano Ceccherini 
651a817d6adSAxel Dörfler 
652a817d6adSAxel Dörfler sem_id
653a817d6adSAxel Dörfler BPrivateScreen::_RetraceSemaphore()
654a817d6adSAxel Dörfler {
65575de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
65675de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_RETRACE_SEMAPHORE);
65775de27f8SStefano Ceccherini 	link.Attach<screen_id>(ID());
658a817d6adSAxel Dörfler 
659a817d6adSAxel Dörfler 	sem_id id = B_BAD_SEM_ID;
6605ec797a7SStephan Aßmus 	status_t status = B_ERROR;
6615ec797a7SStephan Aßmus 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
6625ec797a7SStephan Aßmus 		link.Read<sem_id>(&id);
6635ec797a7SStephan Aßmus 		fRetraceSemValid = true;
6645ec797a7SStephan Aßmus 	}
66575de27f8SStefano Ceccherini 
66675de27f8SStefano Ceccherini 	return id;
66775de27f8SStefano Ceccherini }
66875de27f8SStefano Ceccherini 
66975de27f8SStefano Ceccherini 
670b66d7537SAxel Dörfler status_t
671b66d7537SAxel Dörfler BPrivateScreen::_GetFrameBufferConfig(frame_buffer_config& config)
672b66d7537SAxel Dörfler {
673b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
674b66d7537SAxel Dörfler 	link.StartMessage(AS_GET_FRAME_BUFFER_CONFIG);
675b66d7537SAxel Dörfler 	link.Attach<screen_id>(ID());
676b66d7537SAxel Dörfler 
677b66d7537SAxel Dörfler 	status_t status = B_ERROR;
678b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
679b66d7537SAxel Dörfler 		link.Read<frame_buffer_config>(&config);
680b66d7537SAxel Dörfler 		return B_OK;
681b66d7537SAxel Dörfler 	}
682b66d7537SAxel Dörfler 
683b66d7537SAxel Dörfler 	return status;
684b66d7537SAxel Dörfler }
685b66d7537SAxel Dörfler 
686b66d7537SAxel Dörfler 
687b66d7537SAxel Dörfler BPrivateScreen::BPrivateScreen(screen_id id)
688624df6c6SStefano Ceccherini 	:
689b66d7537SAxel Dörfler 	fID(id),
690624df6c6SStefano Ceccherini 	fColorMap(NULL),
691624df6c6SStefano Ceccherini 	fRetraceSem(-1),
6925ec797a7SStephan Aßmus 	fRetraceSemValid(false),
693b66d7537SAxel Dörfler 	fOwnsColorMap(false),
694b66d7537SAxel Dörfler 	fFrame(0, 0, 0, 0),
695b66d7537SAxel Dörfler 	fLastUpdate(0)
696624df6c6SStefano Ceccherini {
697624df6c6SStefano Ceccherini }
698624df6c6SStefano Ceccherini 
699624df6c6SStefano Ceccherini 
700624df6c6SStefano Ceccherini BPrivateScreen::~BPrivateScreen()
701624df6c6SStefano Ceccherini {
702624df6c6SStefano Ceccherini 	if (fOwnsColorMap)
703624df6c6SStefano Ceccherini 		free(fColorMap);
704624df6c6SStefano Ceccherini }
705