22#include <freerdp/config.h>
31#include <winpr/assert.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;
59int sdl_list_monitors([[maybe_unused]]
SdlContext* sdl)
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,
84static BOOL sdl_apply_max_size(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
87 WINPR_ASSERT(pMaxWidth);
88 WINPR_ASSERT(pMaxHeight);
90 auto settings = sdl->context()->settings;
91 WINPR_ASSERT(settings);
99 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x));
103 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->width);
104 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->height);
109 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
110 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
111 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
116 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
118 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
119 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
122 *pMaxWidth = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.w) *
127 *pMaxHeight = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.h) *
141static Uint32 scale(Uint32 val,
float scale)
143 const auto dval =
static_cast<float>(val);
144 const auto sval = dval / scale;
145 return static_cast<Uint32
>(sval);
148static BOOL sdl_apply_display_properties(
SdlContext* sdl)
152 rdpSettings* settings = sdl->context()->settings;
153 WINPR_ASSERT(settings);
158 std::vector<rdpMonitor> monitors;
159 const auto& ids = sdl->monitorIds();
161 for (UINT32 x = 0; x < ids.size(); x++)
165 float dpi = SDL_GetDisplayContentScale(
id);
170 if (!SDL_GetDisplayBounds(
id, &rect))
173 WINPR_ASSERT(rect.w > 0);
174 WINPR_ASSERT(rect.h > 0);
176 bool highDpi = dpi > 100;
183 const SDL_Rect scaleRect = rect;
185 auto modes = SDL_GetFullscreenDisplayModes(x, &count);
186 for (
int i = 0; i < count; i++)
188 auto mode = modes[i];
192 if (mode->w > rect.w)
197 else if (mode->w == rect.w)
199 if (mode->h > rect.h)
206 SDL_free(
static_cast<void*
>(modes));
208 const float dw = 1.0f *
static_cast<float>(rect.w) /
static_cast<float>(scaleRect.w);
209 const float dh = 1.0f *
static_cast<float>(rect.h) /
static_cast<float>(scaleRect.h);
214 const SDL_DisplayOrientation orientation = SDL_GetCurrentDisplayOrientation(
id);
215 const UINT32 rdp_orientation = sdl::utils::orientaion_to_rdp(orientation);
220 const auto factor = dpi / 96.0f * 100.0f;
221 monitor.orig_screen = x;
224 monitor.width = rect.w;
225 monitor.height = rect.h;
226 monitor.is_primary = x == 0;
227 monitor.attributes.desktopScaleFactor =
static_cast<UINT32
>(factor);
228 monitor.attributes.deviceScaleFactor = 100;
229 monitor.attributes.orientation = rdp_orientation;
230 monitor.attributes.physicalWidth = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.w), hdpi);
231 monitor.attributes.physicalHeight = scale(WINPR_ASSERTING_INT_CAST(uint32_t, rect.h), vdpi);
232 monitors.emplace_back(monitor);
238static BOOL sdl_detect_single_window(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
241 WINPR_ASSERT(pMaxWidth);
242 WINPR_ASSERT(pMaxHeight);
244 rdpSettings* settings = sdl->context()->settings;
245 WINPR_ASSERT(settings);
256 SDL_DisplayID
id = 0;
257 const auto& ids = sdl->monitorIds();
262 sdl->setMonitorIds({
id });
266 if (!sdl_apply_display_properties(sdl))
268 return sdl_apply_max_size(sdl, pMaxWidth, pMaxHeight);
273BOOL sdl_detect_monitors(
SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
276 WINPR_ASSERT(pMaxWidth);
277 WINPR_ASSERT(pMaxHeight);
279 rdpSettings* settings = sdl->context()->settings;
280 WINPR_ASSERT(settings);
282 std::vector<SDL_DisplayID> ids;
285 auto sids = SDL_GetDisplays(&numDisplays);
286 if (sids && (numDisplays > 0))
287 ids = std::vector<SDL_DisplayID>(sids, sids + numDisplays);
297 sdl->setMonitorIds(ids);
300 sdl->setMonitorIds({ ids.front() });
309 "Found %" PRIu32
" monitor IDs, but only have %" PRIuz
" monitors connected",
314 std::vector<SDL_DisplayID> used;
315 for (
size_t x = 0; x < nr; x++)
317 auto cur =
static_cast<const UINT32*
>(
318 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
321 SDL_DisplayID
id = *cur;
324 if (std::find(ids.begin(), ids.end(),
id) == ids.end())
326 WLog_ERR(TAG,
"Supplied monitor ID[%" PRIuz
"]=%" PRIu32
" is invalid", x,
id);
331 if (std::find(used.begin(), used.end(),
id) != used.end())
333 WLog_ERR(TAG,
"Duplicate monitor ID[%" PRIuz
"]=%" PRIu32
" detected", x,
id);
338 sdl->setMonitorIds(used);
341 if (!sdl_apply_display_properties(sdl))
344 auto size =
static_cast<uint32_t
>(sdl->monitorIds().size());
348 return sdl_detect_single_window(sdl, pMaxWidth, pMaxHeight);
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_monitor_def_array_sorted(rdpSettings *settings, const rdpMonitor *monitors, size_t count)
Sort monitor array according to:
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.