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 = monitor->width;
125 *pMaxHeight = monitor->height;
130 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
132 *pMaxHeight = rect.h;
137 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
140 *pMaxHeight = rect.h;
160 #if SDL_VERSION_ATLEAST(2, 0, 10)
161 static UINT32 sdl_orientaion_to_rdp(SDL_DisplayOrientation orientation)
165 case SDL_ORIENTATION_LANDSCAPE:
166 return ORIENTATION_LANDSCAPE;
167 case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
168 return ORIENTATION_LANDSCAPE_FLIPPED;
169 case SDL_ORIENTATION_PORTRAIT_FLIPPED:
170 return ORIENTATION_PORTRAIT_FLIPPED;
171 case SDL_ORIENTATION_PORTRAIT:
173 return ORIENTATION_PORTRAIT;
178 static Uint32 scale(Uint32 val,
float scale)
180 const auto dval =
static_cast<float>(val);
181 const auto sval = dval / scale;
182 return static_cast<Uint32
>(sval);
185 static BOOL sdl_apply_display_properties(
SdlContext* sdl)
189 rdpSettings* settings = sdl->context()->settings;
190 WINPR_ASSERT(settings);
202 for (UINT32 x = 0; x < numIds; x++)
204 auto id =
static_cast<const int*
>(
205 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
213 if (SDL_GetDisplayBounds(*
id, &rect) < 0)
216 if (SDL_GetDisplayDPI(*
id, &ddpi, &hdpi, &vdpi) < 0)
219 WINPR_ASSERT(rect.w > 0);
220 WINPR_ASSERT(rect.h > 0);
221 WINPR_ASSERT(ddpi > 0);
222 WINPR_ASSERT(hdpi > 0);
223 WINPR_ASSERT(vdpi > 0);
225 bool highDpi = hdpi > 100;
232 const SDL_Rect scaleRect = rect;
233 for (
int i = 0; i < SDL_GetNumDisplayModes(*
id); i++)
235 SDL_DisplayMode mode = {};
236 SDL_GetDisplayMode(x, i, &mode);
243 else if (mode.w == rect.w)
253 const float dw = 1.0f *
static_cast<float>(rect.w) /
static_cast<float>(scaleRect.w);
254 const float dh = 1.0f *
static_cast<float>(rect.h) /
static_cast<float>(scaleRect.h);
259 #if SDL_VERSION_ATLEAST(2, 0, 10)
260 const SDL_DisplayOrientation orientation = SDL_GetDisplayOrientation(*
id);
261 const UINT32 rdp_orientation = sdl_orientaion_to_rdp(orientation);
263 const UINT32 rdp_orientation = ORIENTATION_LANDSCAPE;
267 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x));
268 WINPR_ASSERT(monitor);
271 const auto factor = ddpi / 96.0f * 100.0f;
272 monitor->orig_screen = x;
275 monitor->width = rect.w;
276 monitor->height = rect.h;
277 monitor->is_primary = x == 0;
278 monitor->attributes.desktopScaleFactor =
static_cast<UINT32
>(factor);
279 monitor->attributes.deviceScaleFactor = 100;
280 monitor->attributes.orientation = rdp_orientation;
281 monitor->attributes.physicalWidth = scale(rect.w, hdpi);
282 monitor->attributes.physicalHeight = scale(rect.h, vdpi);
287 static BOOL sdl_detect_single_window(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
290 WINPR_ASSERT(pMaxWidth);
291 WINPR_ASSERT(pMaxHeight);
293 rdpSettings* settings = sdl->context()->settings;
294 WINPR_ASSERT(settings);
306 (!sdl->windows.empty()) ? sdl->windows.begin()->second.displayIndex() : 0;
322 if (!sdl_apply_display_properties(sdl))
324 return sdl_apply_max_size(sdl, pMaxWidth, pMaxHeight);
329 BOOL sdl_detect_monitors(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
332 WINPR_ASSERT(pMaxWidth);
333 WINPR_ASSERT(pMaxHeight);
335 rdpSettings* settings = sdl->context()->settings;
336 WINPR_ASSERT(settings);
338 const int numDisplays = SDL_GetNumVideoDisplays();
346 static_cast<size_t>(numDisplays)))
348 for (
size_t x = 0; x < static_cast<size_t>(numDisplays); x++)
350 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorIds, x, &x))
358 if (nr >
static_cast<UINT32
>(numDisplays))
361 "Found %" PRIu32
" monitor IDs, but only have %" PRIu32
" monitors connected",
366 std::vector<UINT32> used;
367 for (
size_t x = 0; x < nr; x++)
369 auto cur =
static_cast<const UINT32*
>(
370 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
379 "Supplied monitor ID[%" PRIuz
"]=%" PRIu32
" is invalid, only [0-%" PRIu32
386 if (std::find(used.begin(), used.end(),
id) != used.end())
388 WLog_ERR(TAG,
"Duplicate monitor ID[%" PRIuz
"]=%" PRIu32
" detected", x,
id);
391 used.push_back(*cur);
395 if (!sdl_apply_display_properties(sdl))
398 return sdl_detect_single_window(sdl, pMaxWidth, pMaxHeight);
401 INT64 sdl_monitor_id_for_index(
SdlContext* sdl, UINT32 index)
404 auto settings = sdl->context()->settings;
413 auto cur =
static_cast<const UINT32*
>(
414 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.