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"
53 MONITOR_INFO* monitors;
61 SDL_Init(SDL_INIT_VIDEO);
64 auto ids = SDL_GetDisplays(&nmonitors);
66 printf(
"listing %d monitors:\n", nmonitors);
67 for (
int i = 0; i < nmonitors; i++)
71 const auto brc = SDL_GetDisplayBounds(
id, &rect);
72 const char* name = SDL_GetDisplayName(
id);
76 printf(
" %s [%u] [%s] %dx%d\t+%d+%d\n", (i == 0) ?
"*" :
" ",
id, name, rect.w, rect.h,
84 static BOOL sdl_is_monitor_id_active(
SdlContext* sdl, UINT32
id)
86 const rdpSettings* settings =
nullptr;
90 settings = sdl->context()->settings;
91 WINPR_ASSERT(settings);
97 for (UINT32 index = 0; index < NumMonitorIds; index++)
99 auto cur =
static_cast<const UINT32*
>(
100 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, index));
101 if (cur && (*cur ==
id))
108 static BOOL sdl_apply_max_size(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
111 WINPR_ASSERT(pMaxWidth);
112 WINPR_ASSERT(pMaxHeight);
114 auto settings = sdl->context()->settings;
115 WINPR_ASSERT(settings);
122 auto monitor =
static_cast<const rdpMonitor*
>(
123 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x));
127 *pMaxWidth = monitor->width;
128 *pMaxHeight = monitor->height;
133 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
135 *pMaxHeight = rect.h;
140 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
143 *pMaxHeight = rect.h;
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;
179 static Uint32 scale(Uint32 val,
float scale)
181 const auto dval =
static_cast<float>(val);
182 const auto sval = dval / scale;
183 return static_cast<Uint32
>(sval);
186 static BOOL sdl_apply_display_properties(
SdlContext* sdl)
190 rdpSettings* settings = sdl->context()->settings;
191 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));
208 float dpi = SDL_GetDisplayContentScale(*
id);
213 if (!SDL_GetDisplayBounds(*
id, &rect))
216 WINPR_ASSERT(rect.w > 0);
217 WINPR_ASSERT(rect.h > 0);
219 bool highDpi = dpi > 100;
226 const SDL_Rect scaleRect = rect;
228 auto modes = SDL_GetFullscreenDisplayModes(x, &count);
229 for (
int i = 0; i < count; i++)
231 auto mode = modes[i];
235 if (mode->w > rect.w)
240 else if (mode->w == rect.w)
242 if (mode->h > rect.h)
251 const float dw = 1.0f *
static_cast<float>(rect.w) /
static_cast<float>(scaleRect.w);
252 const float dh = 1.0f *
static_cast<float>(rect.h) /
static_cast<float>(scaleRect.h);
257 const SDL_DisplayOrientation orientation = SDL_GetCurrentDisplayOrientation(*
id);
258 const UINT32 rdp_orientation = sdl_orientaion_to_rdp(orientation);
261 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x));
262 WINPR_ASSERT(monitor);
265 const auto factor = dpi / 96.0f * 100.0f;
266 monitor->orig_screen = x;
269 monitor->width = rect.w;
270 monitor->height = rect.h;
271 monitor->is_primary = x == 0;
272 monitor->attributes.desktopScaleFactor =
static_cast<UINT32
>(factor);
273 monitor->attributes.deviceScaleFactor = 100;
274 monitor->attributes.orientation = rdp_orientation;
275 monitor->attributes.physicalWidth = scale(rect.w, hdpi);
276 monitor->attributes.physicalHeight = scale(rect.h, vdpi);
281 static BOOL sdl_detect_single_window(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
284 WINPR_ASSERT(pMaxWidth);
285 WINPR_ASSERT(pMaxHeight);
287 rdpSettings* settings = sdl->context()->settings;
288 WINPR_ASSERT(settings);
300 (!sdl->windows.empty()) ? sdl->windows.begin()->second.displayIndex() : 0;
316 if (!sdl_apply_display_properties(sdl))
318 return sdl_apply_max_size(sdl, pMaxWidth, pMaxHeight);
323 BOOL sdl_detect_monitors(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
326 WINPR_ASSERT(pMaxWidth);
327 WINPR_ASSERT(pMaxHeight);
329 rdpSettings* settings = sdl->context()->settings;
330 WINPR_ASSERT(settings);
332 std::vector<SDL_DisplayID> ids;
335 auto sids = SDL_GetDisplays(&numDisplays);
336 if (sids && (numDisplays > 0))
337 ids = std::vector<SDL_DisplayID>(sids, sids + numDisplays);
349 for (
size_t x = 0; x < ids.size(); x++)
352 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorIds, x, &
id))
362 "Found %" PRIu32
" monitor IDs, but only have %" PRIuz
" monitors connected",
367 std::vector<UINT32> used;
368 for (
size_t x = 0; x < nr; x++)
370 auto cur =
static_cast<const UINT32*
>(
371 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
377 if (std::find(ids.begin(), ids.end(),
id) == ids.end())
379 WLog_ERR(TAG,
"Supplied monitor ID[%" PRIuz
"]=%" PRIu32
" is invalid", x,
id);
384 if (std::find(used.begin(), used.end(),
id) != used.end())
386 WLog_ERR(TAG,
"Duplicate monitor ID[%" PRIuz
"]=%" PRIu32
" detected", x,
id);
389 used.push_back(*cur);
393 if (!sdl_apply_display_properties(sdl))
396 return sdl_detect_single_window(sdl, pMaxWidth, pMaxHeight);
399 INT64 sdl_monitor_id_for_index(
SdlContext* sdl, UINT32 index)
402 auto settings = sdl->context()->settings;
411 auto cur =
static_cast<const UINT32*
>(
412 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.