2 * Copyright 2005-2013, Haiku.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
10 #include "VirtualScreen.h"
12 #include "HWInterface.h"
18 VirtualScreen::VirtualScreen()
27 VirtualScreen::~VirtualScreen()
34 VirtualScreen::_Reset()
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
;
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
) {
66 for (int32 i
= 0; i
< fScreenList
.CountItems(); i
++) {
67 Screen
* screen
= fScreenList
.ItemAt(i
)->screen
;
70 screen
->GetMode(mode
);
72 previousModes
.insert(std::make_pair(screen
, mode
));
75 previousModesFailed
= true;
76 *_changedScreens
= ~0L;
83 status_t status
= gScreenManager
->AcquireScreens(&desktop
, NULL
, 0,
84 desktop
.TargetScreen(), false, list
);
86 // TODO: we would try again here with force == true
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
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
;
113 VirtualScreen::AddScreen(Screen
* screen
, ScreenConfigurations
& configurations
)
115 screen_item
* item
= new(std::nothrow
) screen_item
;
119 item
->screen
= screen
;
121 status_t status
= B_ERROR
;
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();
130 status
= screen
->SetBestMode(1024, 768, B_RGB32
, 60.f
);
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",
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
);
152 VirtualScreen::RemoveScreen(Screen
* screen
)
154 // not implemented yet (config changes when running)
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
;
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
184 VirtualScreen::Frame() const
191 VirtualScreen::ScreenAt(int32 index
) const
193 screen_item
* item
= fScreenList
.ItemAt(index
);
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
)
216 VirtualScreen::ScreenFrameAt(int32 index
) const
218 screen_item
* item
= fScreenList
.ItemAt(index
);
222 return BRect(0, 0, 0, 0);
227 VirtualScreen::CountScreens() const
229 return fScreenList
.CountItems();
234 VirtualScreen::_GetMode(Screen
* screen
, ScreenConfigurations
& configurations
,
235 display_mode
& mode
) const
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;