usb_ecm: Use the current configuration instead of a fixed one.
[haiku.git] / src / servers / app / VirtualScreen.cpp
blob94a9e1e1f2b812765cc35ae1e8945eb02ca6b648
1 /*
2 * Copyright 2005-2013, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 */
10 #include "VirtualScreen.h"
12 #include "HWInterface.h"
13 #include "Desktop.h"
15 #include <new>
18 VirtualScreen::VirtualScreen()
20 fScreenList(4, true),
21 fDrawingEngine(NULL),
22 fHWInterface(NULL)
27 VirtualScreen::~VirtualScreen()
29 _Reset();
33 void
34 VirtualScreen::_Reset()
36 ScreenList list;
37 for (int32 i = 0; i < fScreenList.CountItems(); i++) {
38 screen_item* item = fScreenList.ItemAt(i);
40 list.AddItem(item->screen);
43 gScreenManager->ReleaseScreens(list);
44 fScreenList.MakeEmpty();
46 fFrame.Set(0, 0, 0, 0);
47 fDrawingEngine = NULL;
48 fHWInterface = NULL;
52 status_t
53 VirtualScreen::SetConfiguration(Desktop& desktop,
54 ScreenConfigurations& configurations, uint32* _changedScreens)
56 // Remember previous screen modes
58 typedef std::map<Screen*, display_mode> ScreenModeMap;
59 ScreenModeMap previousModes;
60 bool previousModesFailed = false;
62 if (_changedScreens != NULL) {
63 *_changedScreens = 0;
65 try {
66 for (int32 i = 0; i < fScreenList.CountItems(); i++) {
67 Screen* screen = fScreenList.ItemAt(i)->screen;
69 display_mode mode;
70 screen->GetMode(mode);
72 previousModes.insert(std::make_pair(screen, mode));
74 } catch (...) {
75 previousModesFailed = true;
76 *_changedScreens = ~0L;
80 _Reset();
82 ScreenList list;
83 status_t status = gScreenManager->AcquireScreens(&desktop, NULL, 0,
84 desktop.TargetScreen(), false, list);
85 if (status != B_OK) {
86 // TODO: we would try again here with force == true
87 return status;
90 for (int32 i = 0; i < list.CountItems(); i++) {
91 Screen* screen = list.ItemAt(i);
93 AddScreen(screen, configurations);
95 if (!previousModesFailed && _changedScreens != NULL) {
96 // Figure out which screens have changed their mode
97 display_mode mode;
98 screen->GetMode(mode);
100 ScreenModeMap::const_iterator found = previousModes.find(screen);
101 if (found != previousModes.end()
102 && memcmp(&mode, &found->second, sizeof(display_mode)))
103 *_changedScreens |= 1 << i;
107 UpdateFrame();
108 return B_OK;
112 status_t
113 VirtualScreen::AddScreen(Screen* screen, ScreenConfigurations& configurations)
115 screen_item* item = new(std::nothrow) screen_item;
116 if (item == NULL)
117 return B_NO_MEMORY;
119 item->screen = screen;
121 status_t status = B_ERROR;
122 display_mode mode;
123 if (_GetMode(screen, configurations, mode) == B_OK) {
124 // we found settings for this screen, and try to apply them now
125 status = screen->SetMode(mode);
127 if (status != B_OK) {
128 status_t status = screen->SetPreferredMode();
129 if (status != B_OK)
130 status = screen->SetBestMode(1024, 768, B_RGB32, 60.f);
131 if (status != B_OK)
132 status = screen->SetBestMode(800, 600, B_RGB32, 60.f, false);
133 if (status != B_OK) {
134 debug_printf("app_server: Failed to set mode: %s\n",
135 strerror(status));
139 // TODO: this works only for single screen configurations
140 fDrawingEngine = screen->GetDrawingEngine();
141 fHWInterface = screen->HWInterface();
142 fFrame = screen->Frame();
143 item->frame = fFrame;
145 fScreenList.AddItem(item);
147 return B_OK;
151 status_t
152 VirtualScreen::RemoveScreen(Screen* screen)
154 // not implemented yet (config changes when running)
155 return B_ERROR;
159 void
160 VirtualScreen::UpdateFrame()
162 int32 virtualWidth = 0, virtualHeight = 0;
164 for (int32 i = 0; i < fScreenList.CountItems(); i++) {
165 Screen* screen = fScreenList.ItemAt(i)->screen;
167 uint16 width, height;
168 uint32 colorSpace;
169 float frequency;
170 screen->GetMode(width, height, colorSpace, frequency);
172 // TODO: compute virtual size depending on the actual screen position!
173 virtualWidth += width;
174 virtualHeight = max_c(virtualHeight, height);
177 fFrame.Set(0, 0, virtualWidth - 1, virtualHeight - 1);
181 /*! Returns the smallest frame that spans over all screens
183 BRect
184 VirtualScreen::Frame() const
186 return fFrame;
190 Screen*
191 VirtualScreen::ScreenAt(int32 index) const
193 screen_item* item = fScreenList.ItemAt(index);
194 if (item != NULL)
195 return item->screen;
197 return NULL;
201 Screen*
202 VirtualScreen::ScreenByID(int32 id) const
204 for (int32 i = fScreenList.CountItems(); i-- > 0;) {
205 screen_item* item = fScreenList.ItemAt(i);
207 if (item->screen->ID() == id || id == B_MAIN_SCREEN_ID.id)
208 return item->screen;
211 return NULL;
215 BRect
216 VirtualScreen::ScreenFrameAt(int32 index) const
218 screen_item* item = fScreenList.ItemAt(index);
219 if (item != NULL)
220 return item->frame;
222 return BRect(0, 0, 0, 0);
226 int32
227 VirtualScreen::CountScreens() const
229 return fScreenList.CountItems();
233 status_t
234 VirtualScreen::_GetMode(Screen* screen, ScreenConfigurations& configurations,
235 display_mode& mode) const
237 monitor_info info;
238 bool hasInfo = screen->GetMonitorInfo(info) == B_OK;
240 screen_configuration* configuration = configurations.BestFit(screen->ID(),
241 hasInfo ? &info : NULL);
242 if (configuration == NULL)
243 return B_NAME_NOT_FOUND;
245 mode = configuration->mode;
246 configuration->is_current = true;
248 return B_OK;