1 /* 2 * Copyright 2005-2007, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "VirtualScreen.h" 11 12 #include "HWInterface.h" 13 #include "Desktop.h" 14 15 #include <new> 16 17 using std::nothrow; 18 19 20 VirtualScreen::VirtualScreen() 21 : 22 fScreenList(4, true), 23 fDrawingEngine(NULL), 24 fHWInterface(NULL) 25 { 26 } 27 28 29 VirtualScreen::~VirtualScreen() 30 { 31 _Reset(); 32 } 33 34 35 void 36 VirtualScreen::_Reset() 37 { 38 ScreenList list; 39 for (int32 i = 0; i < fScreenList.CountItems(); i++) { 40 screen_item* item = fScreenList.ItemAt(i); 41 42 list.AddItem(item->screen); 43 } 44 45 gScreenManager->ReleaseScreens(list); 46 fScreenList.MakeEmpty(); 47 fSettings.MakeEmpty(); 48 49 fFrame.Set(0, 0, 0, 0); 50 fDrawingEngine = NULL; 51 fHWInterface = NULL; 52 } 53 54 55 status_t 56 VirtualScreen::RestoreConfiguration(Desktop& desktop, const BMessage* settings) 57 { 58 _Reset(); 59 60 // Copy current Desktop workspace settings 61 if (settings) 62 fSettings = *settings; 63 64 ScreenList list; 65 status_t status = gScreenManager->AcquireScreens(&desktop, NULL, 0, false, list); 66 if (status < B_OK) { 67 // TODO: we would try again here with force == true 68 return status; 69 } 70 71 for (int32 i = 0; i < list.CountItems(); i++) { 72 Screen* screen = list.ItemAt(i); 73 74 AddScreen(screen); 75 } 76 77 return B_OK; 78 } 79 80 81 status_t 82 VirtualScreen::StoreConfiguration(BMessage& settings) 83 { 84 for (int32 i = 0; i < fScreenList.CountItems(); i++) { 85 screen_item* item = fScreenList.ItemAt(i); 86 Screen* screen = item->screen; 87 if (!screen->IsDefaultMode()) 88 continue; 89 90 BMessage screenSettings; 91 screenSettings.AddInt32("id", screen->ID()); 92 //screenSettings.AddString("name", "-"); 93 screenSettings.AddRect("frame", item->frame); 94 95 // TODO: or just store a display_mode completely? 96 uint16 width, height; 97 uint32 colorSpace; 98 float frequency; 99 screen->GetMode(width, height, colorSpace, frequency); 100 101 screenSettings.AddInt32("width", width); 102 screenSettings.AddInt32("height", height); 103 screenSettings.AddInt32("color space", colorSpace); 104 screenSettings.AddFloat("frequency", frequency); 105 106 settings.AddMessage("screen", &screenSettings); 107 } 108 109 return B_OK; 110 } 111 112 113 status_t 114 VirtualScreen::AddScreen(Screen* screen) 115 { 116 screen_item* item = new(nothrow) screen_item; 117 if (item == NULL) 118 return B_NO_MEMORY; 119 120 item->screen = screen; 121 122 status_t status = B_ERROR; 123 BMessage settings; 124 if (_FindConfiguration(screen, settings) == B_OK) { 125 // we found settings for this screen, and try to apply them now 126 int32 width, height, colorSpace; 127 float frequency; 128 if (settings.FindInt32("width", &width) == B_OK 129 && settings.FindInt32("height", &height) == B_OK 130 && settings.FindInt32("color space", &colorSpace) == B_OK 131 && settings.FindFloat("frequency", &frequency) == B_OK) 132 status = screen->SetMode(width, height, colorSpace, frequency, true); 133 } 134 if (status < B_OK) { 135 // TODO: more intelligent standard mode (monitor preference, desktop default, ...) 136 screen->SetMode(800, 600, B_RGB32, 60.f, false); 137 } 138 139 // TODO: this works only for single screen configurations 140 fDrawingEngine = screen->GetDrawingEngine(); 141 fHWInterface = screen->HWInterface(); 142 fFrame = screen->Frame(); 143 144 fScreenList.AddItem(item); 145 146 return B_OK; 147 } 148 149 150 status_t 151 VirtualScreen::RemoveScreen(Screen* screen) 152 { 153 // not implemented yet (config changes when running) 154 return B_ERROR; 155 } 156 157 158 void 159 VirtualScreen::UpdateFrame() 160 { 161 int32 virtualWidth = 0, virtualHeight = 0; 162 163 for (int32 i = 0; i < fScreenList.CountItems(); i++) { 164 Screen* screen = fScreenList.ItemAt(i)->screen; 165 166 uint16 width, height; 167 uint32 colorSpace; 168 float frequency; 169 screen->GetMode(width, height, colorSpace, frequency); 170 171 // TODO: compute virtual size depending on the actual screen position! 172 virtualWidth += width; 173 virtualHeight += height; 174 } 175 176 fFrame.Set(0, 0, virtualWidth - 1, virtualHeight - 1); 177 } 178 179 180 /*! 181 Returns the smallest frame that spans over all screens 182 */ 183 BRect 184 VirtualScreen::Frame() const 185 { 186 return fFrame; 187 } 188 189 190 Screen* 191 VirtualScreen::ScreenAt(int32 index) const 192 { 193 screen_item* item = fScreenList.ItemAt(index); 194 if (item != NULL) 195 return item->screen; 196 197 return NULL; 198 } 199 200 201 BRect 202 VirtualScreen::ScreenFrameAt(int32 index) const 203 { 204 screen_item* item = fScreenList.ItemAt(index); 205 if (item != NULL) 206 return item->frame; 207 208 return BRect(0, 0, 0, 0); 209 } 210 211 212 int32 213 VirtualScreen::CountScreens() const 214 { 215 return fScreenList.CountItems(); 216 } 217 218 219 status_t 220 VirtualScreen::_FindConfiguration(Screen* screen, BMessage& settings) 221 { 222 // TODO: we probably want to identify the resolution by connected monitor, 223 // and not the display driver used... 224 // For now, we just use the screen ID, which is almost nothing, anyway... 225 226 uint32 i = 0; 227 while (fSettings.FindMessage("screen", i++, &settings) == B_OK) { 228 int32 id; 229 if (settings.FindInt32("id", &id) != B_OK 230 || screen->ID() != id) 231 continue; 232 233 // we found our match 234 return B_OK; 235 } 236 237 return B_NAME_NOT_FOUND; 238 } 239 240