22 #include <freerdp/config.h>
31 #include <winpr/assert.h>
32 #include <winpr/crt.h>
34 #include <freerdp/log.h>
36 #define TAG CLIENT_TAG("sdl")
38 #include "sdl_monitor.hpp"
39 #include "sdl_freerdp.hpp"
41 using MONITOR_INFO =
struct
48 using VIRTUAL_SCREEN =
struct
53 MONITOR_INFO* monitors;
61 SDL_Init(SDL_INIT_VIDEO);
62 const int nmonitors = SDL_GetNumVideoDisplays();
64 printf(
"listing %d monitors:\n", nmonitors);
65 for (
int i = 0; i < nmonitors; i++)
68 const int brc = SDL_GetDisplayBounds(i, &rect);
69 const char* name = SDL_GetDisplayName(i);
73 printf(
" %s [%d] [%s] %dx%d\t+%d+%d\n", (i == 0) ?
"*" :
" ", i, name, rect.w, rect.h,
81 static BOOL sdl_is_monitor_id_active(
SdlContext* sdl, UINT32
id)
83 const rdpSettings* settings =
nullptr;
87 settings = sdl->context()->settings;
88 WINPR_ASSERT(settings);
94 for (UINT32 index = 0; index < NumMonitorIds; index++)
96 auto cur =
static_cast<const UINT32*
>(
97 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, index));
98 if (cur && (*cur ==
id))
105 static BOOL sdl_apply_max_size(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
108 WINPR_ASSERT(pMaxWidth);
109 WINPR_ASSERT(pMaxHeight);
111 auto settings = sdl->context()->settings;
112 WINPR_ASSERT(settings);
119 auto monitor =
static_cast<const rdpMonitor*
>(
120 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x));
124 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->width);
125 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->height);
130 SDL_GetDisplayUsableBounds(WINPR_ASSERTING_INT_CAST(
int, monitor->orig_screen), &rect);
131 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
132 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
137 SDL_GetDisplayUsableBounds(WINPR_ASSERTING_INT_CAST(
int, monitor->orig_screen), &rect);
139 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
140 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
143 *pMaxWidth = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.w) *
148 *pMaxHeight = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.h) *
162 #if SDL_VERSION_ATLEAST(2, 0, 10)
163 static UINT32 sdl_orientaion_to_rdp(SDL_DisplayOrientation orientation)
167 case SDL_ORIENTATION_LANDSCAPE:
168 return ORIENTATION_LANDSCAPE;
169 case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
170 return ORIENTATION_LANDSCAPE_FLIPPED;
171 case SDL_ORIENTATION_PORTRAIT_FLIPPED:
172 return ORIENTATION_PORTRAIT_FLIPPED;
173 case SDL_ORIENTATION_PORTRAIT:
175 return ORIENTATION_PORTRAIT;
180 static Uint32 scale(Uint32 val,
float scale)
182 const auto dval =
static_cast<float>(val);
183 const auto sval = dval / scale;
184 return static_cast<Uint32
>(sval);
187 static BOOL sdl_apply_display_properties(
SdlContext* sdl)
191 rdpSettings* settings = sdl->context()->settings;
192 WINPR_ASSERT(settings);
204 for (UINT32 x = 0; x < numIds; x++)
206 auto id =
static_cast<const int*
>(
207 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
215 if (SDL_GetDisplayBounds(*
id, &rect) < 0)
218 if (SDL_GetDisplayDPI(*
id, &ddpi, &hdpi, &vdpi) < 0)
221 WINPR_ASSERT(rect.w > 0);
222 WINPR_ASSERT(rect.h > 0);
223 WINPR_ASSERT(ddpi > 0);
224 WINPR_ASSERT(hdpi > 0);
225 WINPR_ASSERT(vdpi > 0);
227 bool highDpi = hdpi > 100;
234 const SDL_Rect scaleRect = rect;
235 for (
int i = 0; i < SDL_GetNumDisplayModes(*
id); i++)
237 SDL_DisplayMode mode = {};
238 SDL_GetDisplayMode(WINPR_ASSERTING_INT_CAST(
int, x), i, &mode);
245 else if (mode.w == rect.w)
255 const float dw = 1.0f *
static_cast<float>(rect.w) /
static_cast<float>(scaleRect.w);
256 const float dh = 1.0f *
static_cast<float>(rect.h) /
static_cast<float>(scaleRect.h);
261 #if SDL_VERSION_ATLEAST(2, 0, 10)
262 const SDL_DisplayOrientation orientation = SDL_GetDisplayOrientation(*
id);
263 const UINT32 rdp_orientation = sdl_orientaion_to_rdp(orientation);
265 const UINT32 rdp_orientation = ORIENTATION_LANDSCAPE;
269 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x));
270 WINPR_ASSERT(monitor);
273 const auto factor = ddpi / 96.0f * 100.0f;
274 monitor->orig_screen = x;
277 monitor->width = rect.w;
278 monitor->height = rect.h;
279 monitor->is_primary = x == 0;
280 monitor->attributes.desktopScaleFactor =
static_cast<UINT32
>(factor);
281 monitor->attributes.deviceScaleFactor = 100;
282 monitor->attributes.orientation = rdp_orientation;
283 monitor->attributes.physicalWidth = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.w), hdpi);
284 monitor->attributes.physicalHeight =
285 scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.h), vdpi);
290 static BOOL sdl_detect_single_window(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
293 WINPR_ASSERT(pMaxWidth);
294 WINPR_ASSERT(pMaxHeight);
296 rdpSettings* settings = sdl->context()->settings;
297 WINPR_ASSERT(settings);
308 const size_t id = (!sdl->windows.empty())
309 ? WINPR_ASSERTING_INT_CAST(
310 uint32_t, sdl->windows.begin()->second.displayIndex())
327 if (!sdl_apply_display_properties(sdl))
329 return sdl_apply_max_size(sdl, pMaxWidth, pMaxHeight);
334 BOOL sdl_detect_monitors(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
337 WINPR_ASSERT(pMaxWidth);
338 WINPR_ASSERT(pMaxHeight);
340 rdpSettings* settings = sdl->context()->settings;
341 WINPR_ASSERT(settings);
343 const int numDisplays = SDL_GetNumVideoDisplays();
351 static_cast<size_t>(numDisplays)))
353 for (
size_t x = 0; x < static_cast<size_t>(numDisplays); x++)
355 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorIds, x, &x))
363 if (nr >
static_cast<UINT32
>(numDisplays))
366 "Found %" PRIu32
" monitor IDs, but only have %" PRIu32
" monitors connected",
371 std::vector<UINT32> used;
372 for (
size_t x = 0; x < nr; x++)
374 auto cur =
static_cast<const UINT32*
>(
375 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
384 "Supplied monitor ID[%" PRIuz
"]=%" PRIu32
" is invalid, only [0-%" PRIu32
391 if (std::find(used.begin(), used.end(),
id) != used.end())
393 WLog_ERR(TAG,
"Duplicate monitor ID[%" PRIuz
"]=%" PRIu32
" detected", x,
id);
396 used.push_back(*cur);
400 if (!sdl_apply_display_properties(sdl))
403 return sdl_detect_single_window(sdl, pMaxWidth, pMaxHeight);
406 INT64 sdl_monitor_id_for_index(
SdlContext* sdl, UINT32 index)
409 auto settings = sdl->context()->settings;
418 auto cur =
static_cast<const UINT32*
>(
419 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, index));
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.