xref: /haiku/src/kits/interface/PrivateScreen.cpp (revision aadbd94ef7c89e9acbca53bf6f18c1f25ba4ba25)
1a817d6adSAxel Dörfler /*
20eed9183SAxel Dörfler  * Copyright 2002-2009, 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 
100eed9183SAxel Dörfler 
110eed9183SAxel 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 
21c2784486SAxel Dörfler #include <new>
22c2784486SAxel Dörfler #include <stdlib.h>
23c2784486SAxel 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 
32c2784486SAxel Dörfler using namespace BPrivate;
33624df6c6SStefano Ceccherini 
34*aadbd94eSAxel Dörfler 
35b66d7537SAxel Dörfler static BObjectList<BPrivateScreen> sScreens(2, true);
368eae8b05SStefano Ceccherini 
378eae8b05SStefano Ceccherini // used to synchronize creation/deletion of the sScreen object
388eae8b05SStefano Ceccherini static BLocker sScreenLock("screen lock");
39624df6c6SStefano Ceccherini 
40624df6c6SStefano Ceccherini 
41624df6c6SStefano Ceccherini BPrivateScreen*
42b66d7537SAxel Dörfler BPrivateScreen::Get(BWindow* window)
43624df6c6SStefano Ceccherini {
440eed9183SAxel Dörfler 	int32 id = B_MAIN_SCREEN_ID.id;
45d9525baaSAxel Dörfler 
46d9525baaSAxel Dörfler 	if (window != NULL) {
47d9525baaSAxel Dörfler 		BPrivate::AppServerLink link;
48d9525baaSAxel Dörfler 		link.StartMessage(AS_GET_SCREEN_ID_FROM_WINDOW);
49d9525baaSAxel Dörfler 		link.Attach<int32>(_get_object_token_(window));
50d9525baaSAxel Dörfler 
51d9525baaSAxel Dörfler 		status_t status;
52d9525baaSAxel Dörfler 		if (link.FlushWithReply(status) == B_OK && status == B_OK)
530eed9183SAxel Dörfler 			link.Read<int32>(&id);
54d9525baaSAxel Dörfler 	}
55d9525baaSAxel Dörfler 
56b66d7537SAxel Dörfler 	return _Get(id, false);
57624df6c6SStefano Ceccherini }
58624df6c6SStefano Ceccherini 
59624df6c6SStefano Ceccherini 
60624df6c6SStefano Ceccherini BPrivateScreen*
610eed9183SAxel Dörfler BPrivateScreen::Get(int32 id)
62b66d7537SAxel Dörfler {
63b66d7537SAxel Dörfler 	return _Get(id, true);
64b66d7537SAxel Dörfler }
65b66d7537SAxel Dörfler 
66b66d7537SAxel Dörfler 
67b66d7537SAxel Dörfler BPrivateScreen*
680eed9183SAxel Dörfler BPrivateScreen::_Get(int32 id, bool check)
69624df6c6SStefano Ceccherini {
7057a6c095SAxel Dörfler 	// Nothing works without an app_server connection
7157a6c095SAxel Dörfler 	if (be_app == NULL)
7257a6c095SAxel Dörfler 		return NULL;
7357a6c095SAxel Dörfler 
74a817d6adSAxel Dörfler 	BAutolock locker(sScreenLock);
758eae8b05SStefano Ceccherini 
76b66d7537SAxel Dörfler 	// search for the screen ID
77b66d7537SAxel Dörfler 
78b66d7537SAxel Dörfler 	for (int32 i = sScreens.CountItems(); i-- > 0;) {
79b66d7537SAxel Dörfler 		BPrivateScreen* screen = sScreens.ItemAt(i);
80b66d7537SAxel Dörfler 
810eed9183SAxel Dörfler 		if (screen->ID() == id) {
82b66d7537SAxel Dörfler 			screen->_Acquire();
83b66d7537SAxel Dörfler 			return screen;
84b66d7537SAxel Dörfler 		}
858eae8b05SStefano Ceccherini 	}
868eae8b05SStefano Ceccherini 
87b66d7537SAxel Dörfler 	if (check) {
88b66d7537SAxel Dörfler 		// check if ID is valid
89b66d7537SAxel Dörfler 		if (!_IsValid(id))
90b66d7537SAxel Dörfler 			return NULL;
91b66d7537SAxel Dörfler 	}
92b66d7537SAxel Dörfler 
93b66d7537SAxel Dörfler 	// we need to allocate a new one
94b66d7537SAxel Dörfler 
95b66d7537SAxel Dörfler 	BPrivateScreen* screen = new (std::nothrow) BPrivateScreen(id);
96b66d7537SAxel Dörfler 	if (screen == NULL)
97b66d7537SAxel Dörfler 		return NULL;
98b66d7537SAxel Dörfler 
99b66d7537SAxel Dörfler 	sScreens.AddItem(screen);
100b66d7537SAxel Dörfler 	return screen;
101624df6c6SStefano Ceccherini }
102624df6c6SStefano Ceccherini 
103624df6c6SStefano Ceccherini 
104624df6c6SStefano Ceccherini void
105b66d7537SAxel Dörfler BPrivateScreen::Put(BPrivateScreen* screen)
106624df6c6SStefano Ceccherini {
107b66d7537SAxel Dörfler 	if (screen == NULL)
108b66d7537SAxel Dörfler 		return;
109b66d7537SAxel Dörfler 
110b66d7537SAxel Dörfler 	BAutolock locker(sScreenLock);
111b66d7537SAxel Dörfler 
112b66d7537SAxel Dörfler 	if (screen->_Release()) {
1130eed9183SAxel Dörfler 		if (screen->ID() != B_MAIN_SCREEN_ID.id) {
114b66d7537SAxel Dörfler 			// we always keep the main screen object around - it will
115b66d7537SAxel Dörfler 			// never go away, even if you disconnect all monitors.
116b66d7537SAxel Dörfler 			sScreens.RemoveItem(screen);
117b66d7537SAxel Dörfler 		}
118b66d7537SAxel Dörfler 	}
119624df6c6SStefano Ceccherini }
120624df6c6SStefano Ceccherini 
121624df6c6SStefano Ceccherini 
122b66d7537SAxel Dörfler BPrivateScreen*
123b66d7537SAxel Dörfler BPrivateScreen::GetNext(BPrivateScreen* screen)
124624df6c6SStefano Ceccherini {
125b66d7537SAxel Dörfler 	BAutolock locker(sScreenLock);
126b66d7537SAxel Dörfler 
1270eed9183SAxel Dörfler 	int32 id;
128b66d7537SAxel Dörfler 	status_t status = screen->GetNextID(id);
1290eed9183SAxel Dörfler 	if (status != B_OK)
130b66d7537SAxel Dörfler 		return NULL;
131b66d7537SAxel Dörfler 
132b66d7537SAxel Dörfler 	BPrivateScreen* nextScreen = Get(id);
133b66d7537SAxel Dörfler 	if (nextScreen == NULL)
134b66d7537SAxel Dörfler 		return NULL;
135b66d7537SAxel Dörfler 
136b66d7537SAxel Dörfler 	Put(screen);
137b66d7537SAxel Dörfler 	return nextScreen;
138624df6c6SStefano Ceccherini }
139624df6c6SStefano Ceccherini 
140624df6c6SStefano Ceccherini 
141b66d7537SAxel Dörfler bool
1420eed9183SAxel Dörfler BPrivateScreen::_IsValid(int32 id)
143b66d7537SAxel Dörfler {
144b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
145b66d7537SAxel Dörfler 	link.StartMessage(AS_VALID_SCREEN_ID);
1460eed9183SAxel Dörfler 	link.Attach<int32>(id);
147b66d7537SAxel Dörfler 
148b66d7537SAxel Dörfler 	status_t status;
149b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
150b66d7537SAxel Dörfler 		return false;
151b66d7537SAxel Dörfler 
152b66d7537SAxel Dörfler 	return true;
153b66d7537SAxel Dörfler }
154b66d7537SAxel Dörfler 
155b66d7537SAxel Dörfler 
156b66d7537SAxel Dörfler //	#pragma mark -
157b66d7537SAxel Dörfler 
158b66d7537SAxel Dörfler 
159624df6c6SStefano Ceccherini color_space
160624df6c6SStefano Ceccherini BPrivateScreen::ColorSpace()
161624df6c6SStefano Ceccherini {
162624df6c6SStefano Ceccherini 	display_mode mode;
163*aadbd94eSAxel Dörfler 	if (GetMode(B_CURRENT_WORKSPACE_INDEX, &mode) == B_OK)
164624df6c6SStefano Ceccherini 		return (color_space)mode.space;
165624df6c6SStefano Ceccherini 
166624df6c6SStefano Ceccherini 	return B_NO_COLOR_SPACE;
167624df6c6SStefano Ceccherini }
168624df6c6SStefano Ceccherini 
169624df6c6SStefano Ceccherini 
170624df6c6SStefano Ceccherini BRect
171624df6c6SStefano Ceccherini BPrivateScreen::Frame()
172624df6c6SStefano Ceccherini {
17339ffb980SStefano Ceccherini 	// If something goes wrong, we just return this rectangle.
17439ffb980SStefano Ceccherini 
175*aadbd94eSAxel Dörfler 	if (system_time() > fLastUpdate + 10000) {
176*aadbd94eSAxel Dörfler 		// invalidate the settings after 10 msecs
177b66d7537SAxel Dörfler 		display_mode mode;
178*aadbd94eSAxel Dörfler 		if (GetMode(B_CURRENT_WORKSPACE_INDEX, &mode) == B_OK) {
179b66d7537SAxel Dörfler 			fFrame.Set(0, 0, (float)mode.virtual_width - 1,
180b66d7537SAxel Dörfler 				(float)mode.virtual_height - 1);
181b66d7537SAxel Dörfler 			fLastUpdate = system_time();
182b66d7537SAxel Dörfler 		}
183b66d7537SAxel Dörfler 	}
184b66d7537SAxel Dörfler 
185b66d7537SAxel Dörfler 	return fFrame;
186624df6c6SStefano Ceccherini }
187624df6c6SStefano Ceccherini 
188624df6c6SStefano Ceccherini 
189b66d7537SAxel Dörfler bool
190b66d7537SAxel Dörfler BPrivateScreen::IsValid() const
191624df6c6SStefano Ceccherini {
192b66d7537SAxel Dörfler 	return BPrivateScreen::_IsValid(ID());
193b66d7537SAxel Dörfler }
194b66d7537SAxel Dörfler 
195b66d7537SAxel Dörfler 
196b66d7537SAxel Dörfler status_t
1970eed9183SAxel Dörfler BPrivateScreen::GetNextID(int32& id)
198b66d7537SAxel Dörfler {
199b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
200b66d7537SAxel Dörfler 	link.StartMessage(AS_GET_NEXT_SCREEN_ID);
2010eed9183SAxel Dörfler 	link.Attach<int32>(ID());
202b66d7537SAxel Dörfler 
203b66d7537SAxel Dörfler 	status_t status;
204b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
2050eed9183SAxel Dörfler 		link.Read<int32>(&id);
206b66d7537SAxel Dörfler 		return B_OK;
207b66d7537SAxel Dörfler 	}
208b66d7537SAxel Dörfler 
209b66d7537SAxel Dörfler 	return status;
210624df6c6SStefano Ceccherini }
211624df6c6SStefano Ceccherini 
212624df6c6SStefano Ceccherini 
213624df6c6SStefano Ceccherini status_t
214624df6c6SStefano Ceccherini BPrivateScreen::WaitForRetrace(bigtime_t timeout)
215624df6c6SStefano Ceccherini {
216624df6c6SStefano Ceccherini 	// Get the retrace semaphore if it's the first time
217624df6c6SStefano Ceccherini 	// we are called. Cache the value then.
2185ec797a7SStephan Aßmus 	if (!fRetraceSemValid)
219a817d6adSAxel Dörfler 		fRetraceSem = _RetraceSemaphore();
220624df6c6SStefano Ceccherini 
2215ec797a7SStephan Aßmus 	if (fRetraceSem < 0) {
2225ec797a7SStephan Aßmus 		// syncing to retrace is not supported by the accelerant
2235ec797a7SStephan Aßmus 		return fRetraceSem;
2245ec797a7SStephan Aßmus 	}
2255ec797a7SStephan Aßmus 
2265ec797a7SStephan Aßmus 	status_t status;
227624df6c6SStefano Ceccherini 	do {
228624df6c6SStefano Ceccherini 		status = acquire_sem_etc(fRetraceSem, 1, B_RELATIVE_TIMEOUT, timeout);
229624df6c6SStefano Ceccherini 	} while (status == B_INTERRUPTED);
230624df6c6SStefano Ceccherini 
231624df6c6SStefano Ceccherini 	return status;
232624df6c6SStefano Ceccherini }
233624df6c6SStefano Ceccherini 
234624df6c6SStefano Ceccherini 
235624df6c6SStefano Ceccherini uint8
236624df6c6SStefano Ceccherini BPrivateScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
237624df6c6SStefano Ceccherini {
238624df6c6SStefano Ceccherini 	// Looks like this check is necessary
239a817d6adSAxel Dörfler 	if (red == B_TRANSPARENT_COLOR.red
240a817d6adSAxel Dörfler 		&& green == B_TRANSPARENT_COLOR.green
241a817d6adSAxel Dörfler 		&& blue == B_TRANSPARENT_COLOR.blue
242a817d6adSAxel Dörfler 		&& alpha == B_TRANSPARENT_COLOR.alpha)
243624df6c6SStefano Ceccherini 		return B_TRANSPARENT_8_BIT;
244624df6c6SStefano Ceccherini 
2450ef40c5eSMichael Lotz 	uint16 index = ((red & 0xf8) << 7) | ((green & 0xf8) << 2) | (blue >> 3);
246a817d6adSAxel Dörfler 	if (ColorMap())
2472ed35bc8SStefano Ceccherini 		return fColorMap->index_map[index];
248624df6c6SStefano Ceccherini 
249624df6c6SStefano Ceccherini 	return 0;
250624df6c6SStefano Ceccherini }
251624df6c6SStefano Ceccherini 
252624df6c6SStefano Ceccherini 
253624df6c6SStefano Ceccherini rgb_color
254624df6c6SStefano Ceccherini BPrivateScreen::ColorForIndex(const uint8 index)
255624df6c6SStefano Ceccherini {
256a817d6adSAxel Dörfler 	if (ColorMap())
257624df6c6SStefano Ceccherini 		return fColorMap->color_list[index];
258624df6c6SStefano Ceccherini 
259624df6c6SStefano Ceccherini 	return rgb_color();
260624df6c6SStefano Ceccherini }
261624df6c6SStefano Ceccherini 
262624df6c6SStefano Ceccherini 
263624df6c6SStefano Ceccherini uint8
264624df6c6SStefano Ceccherini BPrivateScreen::InvertIndex(uint8 index)
265624df6c6SStefano Ceccherini {
266a817d6adSAxel Dörfler 	if (ColorMap())
267624df6c6SStefano Ceccherini 		return fColorMap->inversion_map[index];
268624df6c6SStefano Ceccherini 
269624df6c6SStefano Ceccherini 	return 0;
270624df6c6SStefano Ceccherini }
271624df6c6SStefano Ceccherini 
272624df6c6SStefano Ceccherini 
273624df6c6SStefano Ceccherini const color_map*
274624df6c6SStefano Ceccherini BPrivateScreen::ColorMap()
275624df6c6SStefano Ceccherini {
276a817d6adSAxel Dörfler 	if (fColorMap == NULL) {
277a817d6adSAxel Dörfler 		BAutolock locker(sScreenLock);
278a817d6adSAxel Dörfler 
279a817d6adSAxel Dörfler 		if (fColorMap != NULL) {
280a817d6adSAxel Dörfler 			// someone could have been faster than us
281a817d6adSAxel Dörfler 			return fColorMap;
282a817d6adSAxel Dörfler 		}
283a817d6adSAxel Dörfler 
284a817d6adSAxel Dörfler 		// TODO: BeOS R5 here gets the colormap pointer
285a817d6adSAxel Dörfler 		// (with BApplication::ro_offset_to_ptr() ?)
286a817d6adSAxel Dörfler 		// which is contained in a shared area created by the server.
287a817d6adSAxel Dörfler 		BPrivate::AppServerLink link;
288a817d6adSAxel Dörfler 		link.StartMessage(AS_SCREEN_GET_COLORMAP);
2890eed9183SAxel Dörfler 		link.Attach<int32>(ID());
290a817d6adSAxel Dörfler 
291a817d6adSAxel Dörfler 		status_t status;
292a817d6adSAxel Dörfler 		if (link.FlushWithReply(status) == B_OK && status == B_OK) {
293a817d6adSAxel Dörfler 			fColorMap = (color_map*)malloc(sizeof(color_map));
294a817d6adSAxel Dörfler 			fOwnsColorMap = true;
295a817d6adSAxel Dörfler 			link.Read<color_map>(fColorMap);
296a817d6adSAxel Dörfler 		}
297a817d6adSAxel Dörfler 	}
298a817d6adSAxel Dörfler 
299624df6c6SStefano Ceccherini 	return fColorMap;
300624df6c6SStefano Ceccherini }
301624df6c6SStefano Ceccherini 
302624df6c6SStefano Ceccherini 
303624df6c6SStefano Ceccherini status_t
304466871ccSAxel Dörfler BPrivateScreen::GetBitmap(BBitmap**_bitmap, bool drawCursor, BRect* bounds)
305624df6c6SStefano Ceccherini {
306466871ccSAxel Dörfler 	if (_bitmap == NULL)
30716046321SStefano Ceccherini 		return B_BAD_VALUE;
30816046321SStefano Ceccherini 
309a817d6adSAxel Dörfler 	BRect rect;
310a817d6adSAxel Dörfler 	if (bounds != NULL)
311a817d6adSAxel Dörfler 		rect = *bounds;
312a817d6adSAxel Dörfler 	else
313a817d6adSAxel Dörfler 		rect = Frame();
314a817d6adSAxel Dörfler 
315a817d6adSAxel Dörfler 	BBitmap* bitmap = new (std::nothrow) BBitmap(rect, ColorSpace());
316466871ccSAxel Dörfler 	if (bitmap == NULL)
317466871ccSAxel Dörfler 		return B_NO_MEMORY;
318466871ccSAxel Dörfler 
319466871ccSAxel Dörfler 	status_t status = bitmap->InitCheck();
320466871ccSAxel Dörfler 	if (status == B_OK)
321a817d6adSAxel Dörfler 		status = ReadBitmap(bitmap, drawCursor, &rect);
322466871ccSAxel Dörfler 	if (status != B_OK) {
323466871ccSAxel Dörfler 		delete bitmap;
324466871ccSAxel Dörfler 		return status;
325466871ccSAxel Dörfler 	}
326466871ccSAxel Dörfler 
327466871ccSAxel Dörfler 	*_bitmap = bitmap;
328466871ccSAxel Dörfler 	return B_OK;
329624df6c6SStefano Ceccherini }
330624df6c6SStefano Ceccherini 
331624df6c6SStefano Ceccherini 
332624df6c6SStefano Ceccherini status_t
333a817d6adSAxel Dörfler BPrivateScreen::ReadBitmap(BBitmap* bitmap, bool drawCursor, BRect* bounds)
334624df6c6SStefano Ceccherini {
33516046321SStefano Ceccherini 	if (bitmap == NULL)
33616046321SStefano Ceccherini 		return B_BAD_VALUE;
33716046321SStefano Ceccherini 
33816046321SStefano Ceccherini 	BRect rect;
339a817d6adSAxel Dörfler 	if (bounds != NULL)
340a817d6adSAxel Dörfler 		rect = *bounds;
34116046321SStefano Ceccherini 	else
34216046321SStefano Ceccherini 		rect = Frame();
34316046321SStefano Ceccherini 
34416046321SStefano Ceccherini 	BPrivate::AppServerLink link;
34516046321SStefano Ceccherini 	link.StartMessage(AS_READ_BITMAP);
3469a44fdc9SAxel Dörfler 	link.Attach<int32>(bitmap->_ServerToken());
34716046321SStefano Ceccherini 	link.Attach<bool>(drawCursor);
34816046321SStefano Ceccherini 	link.Attach<BRect>(rect);
34916046321SStefano Ceccherini 
350a817d6adSAxel Dörfler 	status_t status = B_ERROR;
351a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) < B_OK || status != B_OK)
352a817d6adSAxel Dörfler 		return status;
35316046321SStefano Ceccherini 
35416046321SStefano Ceccherini 	return B_OK;
355624df6c6SStefano Ceccherini }
356624df6c6SStefano Ceccherini 
357624df6c6SStefano Ceccherini 
358624df6c6SStefano Ceccherini rgb_color
35939ffb980SStefano Ceccherini BPrivateScreen::DesktopColor(uint32 workspace)
360624df6c6SStefano Ceccherini {
3613ba7d6f3SAxel Dörfler 	rgb_color color = { 51, 102, 152, 255 };
362dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
3633ba7d6f3SAxel Dörfler 
3643ba7d6f3SAxel Dörfler 	link.StartMessage(AS_GET_DESKTOP_COLOR);
3653f319b33SMichael Lotz 	link.Attach<uint32>(workspace);
3663ba7d6f3SAxel Dörfler 
3673ba7d6f3SAxel Dörfler 	int32 code;
368dd10337fSAxel Dörfler 	if (link.FlushWithReply(code) == B_OK
369a817d6adSAxel Dörfler 		&& code == B_OK)
3703ba7d6f3SAxel Dörfler 		link.Read<rgb_color>(&color);
3713ba7d6f3SAxel Dörfler 
37239ffb980SStefano Ceccherini 	return color;
373624df6c6SStefano Ceccherini }
374624df6c6SStefano Ceccherini 
375624df6c6SStefano Ceccherini 
376624df6c6SStefano Ceccherini void
377a817d6adSAxel Dörfler BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace,
378a817d6adSAxel Dörfler 	bool makeDefault)
379624df6c6SStefano Ceccherini {
380dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
3813ba7d6f3SAxel Dörfler 
3823ba7d6f3SAxel Dörfler 	link.StartMessage(AS_SET_DESKTOP_COLOR);
38339ffb980SStefano Ceccherini 	link.Attach<rgb_color>(color);
3848f9ab4d1SAxel Dörfler 	link.Attach<uint32>(workspace);
38539ffb980SStefano Ceccherini 	link.Attach<bool>(makeDefault);
38639ffb980SStefano Ceccherini 	link.Flush();
387624df6c6SStefano Ceccherini }
388624df6c6SStefano Ceccherini 
389624df6c6SStefano Ceccherini 
390624df6c6SStefano Ceccherini status_t
391c6418981SStefano Ceccherini BPrivateScreen::ProposeMode(display_mode* target,
392c6418981SStefano Ceccherini 	const display_mode* low, const display_mode* high)
393624df6c6SStefano Ceccherini {
394c6418981SStefano Ceccherini 	// We can't return B_BAD_VALUE here, because it's used to indicate
395c6418981SStefano Ceccherini 	// that the mode returned is supported, but it doesn't fall
396c6418981SStefano Ceccherini 	// within the limit (see ProposeMode() documentation)
397c6418981SStefano Ceccherini 	if (target == NULL || low == NULL || high == NULL)
398624df6c6SStefano Ceccherini 		return B_ERROR;
399c6418981SStefano Ceccherini 
400c6418981SStefano Ceccherini 	BPrivate::AppServerLink link;
401c6418981SStefano Ceccherini 	link.StartMessage(AS_PROPOSE_MODE);
4020eed9183SAxel Dörfler 	link.Attach<int32>(ID());
403583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*target);
404583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*low);
405583f6c3eSStefano Ceccherini 	link.Attach<display_mode>(*high);
406583f6c3eSStefano Ceccherini 
407c6418981SStefano Ceccherini 	status_t status = B_ERROR;
408a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
409c6418981SStefano Ceccherini 		link.Read<display_mode>(target);
410a817d6adSAxel Dörfler 
411a817d6adSAxel Dörfler 		bool withinLimits;
412a817d6adSAxel Dörfler 		link.Read<bool>(&withinLimits);
413a817d6adSAxel Dörfler 		if (!withinLimits)
414a817d6adSAxel Dörfler 			status = B_BAD_VALUE;
415c6418981SStefano Ceccherini 	}
416c6418981SStefano Ceccherini 
417c6418981SStefano Ceccherini 	return status;
418624df6c6SStefano Ceccherini }
419624df6c6SStefano Ceccherini 
420624df6c6SStefano Ceccherini 
421624df6c6SStefano Ceccherini status_t
422a817d6adSAxel Dörfler BPrivateScreen::GetModeList(display_mode** _modeList, uint32* _count)
423624df6c6SStefano Ceccherini {
424a817d6adSAxel Dörfler 	if (_modeList == NULL || _count == NULL)
42510c5dab8SStefano Ceccherini 		return B_BAD_VALUE;
42610c5dab8SStefano Ceccherini 
42710c5dab8SStefano Ceccherini 	BPrivate::AppServerLink link;
42810c5dab8SStefano Ceccherini 	link.StartMessage(AS_GET_MODE_LIST);
4290eed9183SAxel Dörfler 	link.Attach<int32>(ID());
430a817d6adSAxel Dörfler 
431a817d6adSAxel Dörfler 	status_t status = B_ERROR;
432a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
43306740743SAxel Dörfler 		uint32 count;
43406740743SAxel Dörfler 		if (link.Read<uint32>(&count) < B_OK)
43506740743SAxel Dörfler 			return B_ERROR;
43606740743SAxel Dörfler 
437a817d6adSAxel Dörfler 		// TODO: this could get too big for the link
43806740743SAxel Dörfler 		int32 size = count * sizeof(display_mode);
43906740743SAxel Dörfler 		display_mode* modeList = (display_mode *)malloc(size);
44006740743SAxel Dörfler 		if (modeList == NULL)
441a817d6adSAxel Dörfler 			return B_NO_MEMORY;
442a817d6adSAxel Dörfler 
44306740743SAxel Dörfler 		if (link.Read(modeList, size) < B_OK) {
44406740743SAxel Dörfler 			free(modeList);
44506740743SAxel Dörfler 			return B_ERROR;
44606740743SAxel Dörfler 		}
44706740743SAxel Dörfler 
44806740743SAxel Dörfler 		*_modeList = modeList;
44906740743SAxel Dörfler 		*_count = count;
45010c5dab8SStefano Ceccherini 	}
45110c5dab8SStefano Ceccherini 
45210c5dab8SStefano Ceccherini 	return status;
453624df6c6SStefano Ceccherini }
454624df6c6SStefano Ceccherini 
455624df6c6SStefano Ceccherini 
456624df6c6SStefano Ceccherini status_t
457624df6c6SStefano Ceccherini BPrivateScreen::GetMode(uint32 workspace, display_mode *mode)
458624df6c6SStefano Ceccherini {
459314a1024SStefano Ceccherini 	if (mode == NULL)
460314a1024SStefano Ceccherini 		return B_BAD_VALUE;
461314a1024SStefano Ceccherini 
462dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
46334c39bf0SStefano Ceccherini 	link.StartMessage(AS_SCREEN_GET_MODE);
4640eed9183SAxel Dörfler 	link.Attach<int32>(ID());
46539ffb980SStefano Ceccherini 	link.Attach<uint32>(workspace);
466fca6492fSStefano Ceccherini 
46734c39bf0SStefano Ceccherini 	status_t status = B_ERROR;
468a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) != B_OK
469a817d6adSAxel Dörfler 		|| status != B_OK)
47039ffb980SStefano Ceccherini 		return status;
471a817d6adSAxel Dörfler 
472a817d6adSAxel Dörfler 	link.Read<display_mode>(mode);
473a817d6adSAxel Dörfler 	return B_OK;
474624df6c6SStefano Ceccherini }
475624df6c6SStefano Ceccherini 
476624df6c6SStefano Ceccherini 
477624df6c6SStefano Ceccherini status_t
478624df6c6SStefano Ceccherini BPrivateScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault)
479624df6c6SStefano Ceccherini {
480314a1024SStefano Ceccherini 	if (mode == NULL)
481314a1024SStefano Ceccherini 		return B_BAD_VALUE;
482314a1024SStefano Ceccherini 
483dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
484314a1024SStefano Ceccherini 	link.StartMessage(AS_SCREEN_SET_MODE);
4850eed9183SAxel Dörfler 	link.Attach<int32>(ID());
48639ffb980SStefano Ceccherini 	link.Attach<uint32>(workspace);
48739ffb980SStefano Ceccherini 	link.Attach<display_mode>(*mode);
48839ffb980SStefano Ceccherini 	link.Attach<bool>(makeDefault);
489314a1024SStefano Ceccherini 
490314a1024SStefano Ceccherini 	status_t status = B_ERROR;
491a817d6adSAxel Dörfler 	link.FlushWithReply(status);
492314a1024SStefano Ceccherini 
49339ffb980SStefano Ceccherini 	return status;
494624df6c6SStefano Ceccherini }
495624df6c6SStefano Ceccherini 
496624df6c6SStefano Ceccherini 
497624df6c6SStefano Ceccherini status_t
498624df6c6SStefano Ceccherini BPrivateScreen::GetDeviceInfo(accelerant_device_info *info)
499624df6c6SStefano Ceccherini {
500c6418981SStefano Ceccherini 	if (info == NULL)
501c6418981SStefano Ceccherini 		return B_BAD_VALUE;
502c6418981SStefano Ceccherini 
503c6418981SStefano Ceccherini 	BPrivate::AppServerLink link;
504c6418981SStefano Ceccherini 	link.StartMessage(AS_GET_ACCELERANT_INFO);
5050eed9183SAxel Dörfler 	link.Attach<int32>(ID());
506a817d6adSAxel Dörfler 
507a817d6adSAxel Dörfler 	status_t status = B_ERROR;
508a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
509c6418981SStefano Ceccherini 		link.Read<accelerant_device_info>(info);
510c6418981SStefano Ceccherini 		return B_OK;
511c6418981SStefano Ceccherini 	}
512c6418981SStefano Ceccherini 
513a817d6adSAxel Dörfler 	return status;
514624df6c6SStefano Ceccherini }
515624df6c6SStefano Ceccherini 
516624df6c6SStefano Ceccherini 
517624df6c6SStefano Ceccherini status_t
518c2784486SAxel Dörfler BPrivateScreen::GetMonitorInfo(monitor_info* info)
519c2784486SAxel Dörfler {
520c2784486SAxel Dörfler 	if (info == NULL)
521c2784486SAxel Dörfler 		return B_BAD_VALUE;
522c2784486SAxel Dörfler 
523c2784486SAxel Dörfler 	BPrivate::AppServerLink link;
524c2784486SAxel Dörfler 	link.StartMessage(AS_GET_MONITOR_INFO);
5250eed9183SAxel Dörfler 	link.Attach<int32>(ID());
526c2784486SAxel Dörfler 
527c2784486SAxel Dörfler 	status_t status = B_ERROR;
528c2784486SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
529c2784486SAxel Dörfler 		link.Read<monitor_info>(info);
530c2784486SAxel Dörfler 		return B_OK;
531c2784486SAxel Dörfler 	}
532c2784486SAxel Dörfler 
533c2784486SAxel Dörfler 	return status;
534c2784486SAxel Dörfler }
535c2784486SAxel Dörfler 
536c2784486SAxel Dörfler 
537c2784486SAxel Dörfler status_t
538624df6c6SStefano Ceccherini BPrivateScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
539624df6c6SStefano Ceccherini {
54075de27f8SStefano Ceccherini 	if (mode == NULL || low == NULL || high == NULL)
54175de27f8SStefano Ceccherini 		return B_BAD_VALUE;
54275de27f8SStefano Ceccherini 
54375de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
54475de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_PIXEL_CLOCK_LIMITS);
5450eed9183SAxel Dörfler 	link.Attach<int32>(ID());
54675de27f8SStefano Ceccherini 	link.Attach<display_mode>(*mode);
54775de27f8SStefano Ceccherini 
548a817d6adSAxel Dörfler 	status_t status;
549a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
55075de27f8SStefano Ceccherini 		link.Read<uint32>(low);
55175de27f8SStefano Ceccherini 		link.Read<uint32>(high);
55275de27f8SStefano Ceccherini 		return B_OK;
55375de27f8SStefano Ceccherini 	}
55475de27f8SStefano Ceccherini 
555a817d6adSAxel Dörfler 	return status;
556624df6c6SStefano Ceccherini }
557624df6c6SStefano Ceccherini 
558624df6c6SStefano Ceccherini 
559624df6c6SStefano Ceccherini status_t
560a817d6adSAxel Dörfler BPrivateScreen::GetTimingConstraints(display_timing_constraints *constraints)
561624df6c6SStefano Ceccherini {
562a817d6adSAxel Dörfler 	if (constraints == NULL)
56355b222b0SStefano Ceccherini 		return B_BAD_VALUE;
56455b222b0SStefano Ceccherini 
56575de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
56675de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_TIMING_CONSTRAINTS);
5670eed9183SAxel Dörfler 	link.Attach<int32>(ID());
56875de27f8SStefano Ceccherini 
569a817d6adSAxel Dörfler 	status_t status = B_ERROR;
570a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
571a817d6adSAxel Dörfler 		link.Read<display_timing_constraints>(constraints);
57275de27f8SStefano Ceccherini 		return B_OK;
57375de27f8SStefano Ceccherini 	}
57475de27f8SStefano Ceccherini 
575a817d6adSAxel Dörfler 	return status;
576624df6c6SStefano Ceccherini }
577624df6c6SStefano Ceccherini 
578624df6c6SStefano Ceccherini 
579624df6c6SStefano Ceccherini status_t
580624df6c6SStefano Ceccherini BPrivateScreen::SetDPMS(uint32 dpmsState)
581624df6c6SStefano Ceccherini {
582dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
58355b222b0SStefano Ceccherini 	link.StartMessage(AS_SET_DPMS);
5840eed9183SAxel Dörfler 	link.Attach<int32>(ID());
58539ffb980SStefano Ceccherini 	link.Attach<uint32>(dpmsState);
58655b222b0SStefano Ceccherini 
587a817d6adSAxel Dörfler 	status_t status = B_ERROR;
588a817d6adSAxel Dörfler 	link.FlushWithReply(status);
589a817d6adSAxel Dörfler 
590a817d6adSAxel Dörfler 	return status;
591624df6c6SStefano Ceccherini }
592624df6c6SStefano Ceccherini 
593624df6c6SStefano Ceccherini 
594624df6c6SStefano Ceccherini uint32
595624df6c6SStefano Ceccherini BPrivateScreen::DPMSState()
596624df6c6SStefano Ceccherini {
59739ffb980SStefano Ceccherini 	uint32 state = 0;
59855b222b0SStefano Ceccherini 
599dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
60055b222b0SStefano Ceccherini 	link.StartMessage(AS_GET_DPMS_STATE);
6010eed9183SAxel Dörfler 	link.Attach<int32>(ID());
602a817d6adSAxel Dörfler 
603a817d6adSAxel Dörfler 	status_t status;
604a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
60555b222b0SStefano Ceccherini 		link.Read<uint32>(&state);
60655b222b0SStefano Ceccherini 
60739ffb980SStefano Ceccherini 	return state;
608624df6c6SStefano Ceccherini }
609624df6c6SStefano Ceccherini 
610624df6c6SStefano Ceccherini 
611624df6c6SStefano Ceccherini uint32
612624df6c6SStefano Ceccherini BPrivateScreen::DPMSCapabilites()
613624df6c6SStefano Ceccherini {
61439ffb980SStefano Ceccherini 	uint32 capabilities = 0;
61555b222b0SStefano Ceccherini 
616dd10337fSAxel Dörfler 	BPrivate::AppServerLink link;
61755b222b0SStefano Ceccherini 	link.StartMessage(AS_GET_DPMS_CAPABILITIES);
6180eed9183SAxel Dörfler 	link.Attach<int32>(ID());
619a817d6adSAxel Dörfler 
620a817d6adSAxel Dörfler 	status_t status;
621a817d6adSAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
62255b222b0SStefano Ceccherini 		link.Read<uint32>(&capabilities);
62355b222b0SStefano Ceccherini 
62439ffb980SStefano Ceccherini 	return capabilities;
625624df6c6SStefano Ceccherini }
626624df6c6SStefano Ceccherini 
627624df6c6SStefano Ceccherini 
628624df6c6SStefano Ceccherini void *
629624df6c6SStefano Ceccherini BPrivateScreen::BaseAddress()
630624df6c6SStefano Ceccherini {
631b66d7537SAxel Dörfler 	frame_buffer_config config;
632b66d7537SAxel Dörfler 	if (_GetFrameBufferConfig(config) != B_OK)
633624df6c6SStefano Ceccherini 		return NULL;
634b66d7537SAxel Dörfler 
635b66d7537SAxel Dörfler 	return config.frame_buffer;
636624df6c6SStefano Ceccherini }
637624df6c6SStefano Ceccherini 
638624df6c6SStefano Ceccherini 
639624df6c6SStefano Ceccherini uint32
640624df6c6SStefano Ceccherini BPrivateScreen::BytesPerRow()
641624df6c6SStefano Ceccherini {
642b66d7537SAxel Dörfler 	frame_buffer_config config;
643b66d7537SAxel Dörfler 	if (_GetFrameBufferConfig(config) != B_OK)
644624df6c6SStefano Ceccherini 		return 0;
645624df6c6SStefano Ceccherini 
646b66d7537SAxel Dörfler 	return config.bytes_per_row;
647624df6c6SStefano Ceccherini }
648624df6c6SStefano Ceccherini 
649624df6c6SStefano Ceccherini 
650a817d6adSAxel Dörfler // #pragma mark - private methods
65175de27f8SStefano Ceccherini 
652a817d6adSAxel Dörfler 
653*aadbd94eSAxel Dörfler void
654*aadbd94eSAxel Dörfler BPrivateScreen::_Acquire()
655*aadbd94eSAxel Dörfler {
656*aadbd94eSAxel Dörfler 	fReferenceCount++;
657*aadbd94eSAxel Dörfler 
658*aadbd94eSAxel Dörfler 	fLastUpdate = 0;
659*aadbd94eSAxel Dörfler 		// force an update for the new BScreen object
660*aadbd94eSAxel Dörfler }
661*aadbd94eSAxel Dörfler 
662*aadbd94eSAxel Dörfler 
663*aadbd94eSAxel Dörfler bool
664*aadbd94eSAxel Dörfler BPrivateScreen::_Release()
665*aadbd94eSAxel Dörfler {
666*aadbd94eSAxel Dörfler 	return --fReferenceCount == 0;
667*aadbd94eSAxel Dörfler }
668*aadbd94eSAxel Dörfler 
669*aadbd94eSAxel Dörfler 
670a817d6adSAxel Dörfler sem_id
671a817d6adSAxel Dörfler BPrivateScreen::_RetraceSemaphore()
672a817d6adSAxel Dörfler {
67375de27f8SStefano Ceccherini 	BPrivate::AppServerLink link;
67475de27f8SStefano Ceccherini 	link.StartMessage(AS_GET_RETRACE_SEMAPHORE);
6750eed9183SAxel Dörfler 	link.Attach<int32>(ID());
676a817d6adSAxel Dörfler 
677a817d6adSAxel Dörfler 	sem_id id = B_BAD_SEM_ID;
6785ec797a7SStephan Aßmus 	status_t status = B_ERROR;
6795ec797a7SStephan Aßmus 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
6805ec797a7SStephan Aßmus 		link.Read<sem_id>(&id);
6815ec797a7SStephan Aßmus 		fRetraceSemValid = true;
6825ec797a7SStephan Aßmus 	}
68375de27f8SStefano Ceccherini 
68475de27f8SStefano Ceccherini 	return id;
68575de27f8SStefano Ceccherini }
68675de27f8SStefano Ceccherini 
68775de27f8SStefano Ceccherini 
688b66d7537SAxel Dörfler status_t
689b66d7537SAxel Dörfler BPrivateScreen::_GetFrameBufferConfig(frame_buffer_config& config)
690b66d7537SAxel Dörfler {
691b66d7537SAxel Dörfler 	BPrivate::AppServerLink link;
692b66d7537SAxel Dörfler 	link.StartMessage(AS_GET_FRAME_BUFFER_CONFIG);
6930eed9183SAxel Dörfler 	link.Attach<int32>(ID());
694b66d7537SAxel Dörfler 
695b66d7537SAxel Dörfler 	status_t status = B_ERROR;
696b66d7537SAxel Dörfler 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
697b66d7537SAxel Dörfler 		link.Read<frame_buffer_config>(&config);
698b66d7537SAxel Dörfler 		return B_OK;
699b66d7537SAxel Dörfler 	}
700b66d7537SAxel Dörfler 
701b66d7537SAxel Dörfler 	return status;
702b66d7537SAxel Dörfler }
703b66d7537SAxel Dörfler 
704b66d7537SAxel Dörfler 
7050eed9183SAxel Dörfler BPrivateScreen::BPrivateScreen(int32 id)
706624df6c6SStefano Ceccherini 	:
707b66d7537SAxel Dörfler 	fID(id),
708*aadbd94eSAxel Dörfler 	fReferenceCount(0),
709624df6c6SStefano Ceccherini 	fColorMap(NULL),
710624df6c6SStefano Ceccherini 	fRetraceSem(-1),
7115ec797a7SStephan Aßmus 	fRetraceSemValid(false),
712b66d7537SAxel Dörfler 	fOwnsColorMap(false),
713b66d7537SAxel Dörfler 	fFrame(0, 0, 0, 0),
714b66d7537SAxel Dörfler 	fLastUpdate(0)
715624df6c6SStefano Ceccherini {
716624df6c6SStefano Ceccherini }
717624df6c6SStefano Ceccherini 
718624df6c6SStefano Ceccherini 
719624df6c6SStefano Ceccherini BPrivateScreen::~BPrivateScreen()
720624df6c6SStefano Ceccherini {
721624df6c6SStefano Ceccherini 	if (fOwnsColorMap)
722624df6c6SStefano Ceccherini 		free(fColorMap);
723624df6c6SStefano Ceccherini }
724