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 = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->width);
128 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->height);
133 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
134 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
135 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
140 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
142 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
143 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
146 *pMaxWidth = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.w) *
151 *pMaxHeight = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.h) *
165 static UINT32 sdl_orientaion_to_rdp(SDL_DisplayOrientation orientation)
169 case SDL_ORIENTATION_LANDSCAPE:
170 return ORIENTATION_LANDSCAPE;
171 case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
172 return ORIENTATION_LANDSCAPE_FLIPPED;
173 case SDL_ORIENTATION_PORTRAIT_FLIPPED:
174 return ORIENTATION_PORTRAIT_FLIPPED;
175 case SDL_ORIENTATION_PORTRAIT:
177 return ORIENTATION_PORTRAIT;
181 static Uint32 scale(Uint32 val,
float scale)
183 const auto dval =
static_cast<float>(val);
184 const auto sval = dval / scale;
185 return static_cast<Uint32
>(sval);
188 static BOOL sdl_apply_display_properties(
SdlContext* sdl)
192 rdpSettings* settings = sdl->context()->settings;
193 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));
210 float dpi = SDL_GetDisplayContentScale(WINPR_ASSERTING_INT_CAST(uint32_t, *
id));
215 if (!SDL_GetDisplayBounds(WINPR_ASSERTING_INT_CAST(uint32_t, *
id), &rect))
218 WINPR_ASSERT(rect.w > 0);
219 WINPR_ASSERT(rect.h > 0);
221 bool highDpi = dpi > 100;
228 const SDL_Rect scaleRect = rect;
230 auto modes = SDL_GetFullscreenDisplayModes(x, &count);
231 for (
int i = 0; i < count; i++)
233 auto mode = modes[i];
237 if (mode->w > rect.w)
242 else if (mode->w == rect.w)
244 if (mode->h > rect.h)
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 const SDL_DisplayOrientation orientation =
260 SDL_GetCurrentDisplayOrientation(WINPR_ASSERTING_INT_CAST(uint32_t, *
id));
261 const UINT32 rdp_orientation = sdl_orientaion_to_rdp(orientation);
264 freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x));
265 WINPR_ASSERT(monitor);
268 const auto factor = dpi / 96.0f * 100.0f;
269 monitor->orig_screen = x;
272 monitor->width = rect.w;
273 monitor->height = rect.h;
274 monitor->is_primary = x == 0;
275 monitor->attributes.desktopScaleFactor =
static_cast<UINT32
>(factor);
276 monitor->attributes.deviceScaleFactor = 100;
277 monitor->attributes.orientation = rdp_orientation;
278 monitor->attributes.physicalWidth = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.w), hdpi);
279 monitor->attributes.physicalHeight =
280 scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.h), vdpi);
285 static BOOL sdl_detect_single_window(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
288 WINPR_ASSERT(pMaxWidth);
289 WINPR_ASSERT(pMaxHeight);
291 rdpSettings* settings = sdl->context()->settings;
292 WINPR_ASSERT(settings);
304 (!sdl->windows.empty())
305 ? WINPR_ASSERTING_INT_CAST(
size_t, sdl->windows.begin()->second.displayIndex())
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 std::vector<SDL_DisplayID> ids;
341 auto sids = SDL_GetDisplays(&numDisplays);
342 if (sids && (numDisplays > 0))
343 ids = std::vector<SDL_DisplayID>(sids, sids + numDisplays);
355 for (
size_t x = 0; x < ids.size(); x++)
358 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorIds, x, &
id))
368 "Found %" PRIu32
" monitor IDs, but only have %" PRIuz
" monitors connected",
373 std::vector<UINT32> used;
374 for (
size_t x = 0; x < nr; x++)
376 auto cur =
static_cast<const UINT32*
>(
377 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
383 if (std::find(ids.begin(), ids.end(),
id) == ids.end())
385 WLog_ERR(TAG,
"Supplied monitor ID[%" PRIuz
"]=%" PRIu32
" is invalid", x,
id);
390 if (std::find(used.begin(), used.end(),
id) != used.end())
392 WLog_ERR(TAG,
"Duplicate monitor ID[%" PRIuz
"]=%" PRIu32
" detected", x,
id);
395 used.push_back(*cur);
399 if (!sdl_apply_display_properties(sdl))
402 return sdl_detect_single_window(sdl, pMaxWidth, pMaxHeight);
405 INT64 sdl_monitor_id_for_index(
SdlContext* sdl, UINT32 index)
408 auto settings = sdl->context()->settings;
417 auto cur =
static_cast<const UINT32*
>(
418 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.