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