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