22#include <freerdp/config.h>
32#include <winpr/assert.h>
35#include <freerdp/log.h>
37#define TAG CLIENT_TAG("sdl")
39#include "sdl_monitor.hpp"
40#include "sdl_context.hpp"
54 MONITOR_INFO* monitors;
62 SDL_Init(SDL_INIT_VIDEO);
65 auto ids = SDL_GetDisplays(&nmonitors);
67 printf(
"listing %d monitors:\n", nmonitors);
68 for (
int i = 0; i < nmonitors; i++)
72 const auto brc = SDL_GetDisplayBounds(
id, &rect);
73 const char* name = SDL_GetDisplayName(
id);
77 printf(
" %s [%u] [%s] %dx%d\t+%d+%d\n", (i == 0) ?
"*" :
" ", id, name, rect.w, rect.h,
85[[nodiscard]]
static BOOL sdl_apply_mon_max_size(
SdlContext*
sdl, UINT32* pMaxWidth,
93 WINPR_ASSERT(pMaxWidth);
94 WINPR_ASSERT(pMaxHeight);
96 auto settings =
sdl->context()->settings;
97 WINPR_ASSERT(settings);
101 auto monitor =
static_cast<const rdpMonitor*
>(
102 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x));
104 left = std::min(monitor->x, left);
105 top = std::min(monitor->y, top);
106 right = std::max(monitor->x + monitor->width, right);
107 bottom = std::max(monitor->y + monitor->height, bottom);
110 const int32_t w = right - left;
111 const int32_t h = bottom - top;
113 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, w);
114 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, h);
118[[nodiscard]]
static BOOL sdl_apply_max_size(
SdlContext*
sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
121 WINPR_ASSERT(pMaxWidth);
122 WINPR_ASSERT(pMaxHeight);
124 auto settings =
sdl->context()->settings;
125 WINPR_ASSERT(settings);
132 auto monitor =
static_cast<const rdpMonitor*
>(
133 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x));
140 if (SDL_GetDisplayBounds(monitor->orig_screen, &rect))
142 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
143 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
148 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->width);
149 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, monitor->height);
154 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
155 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
156 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
161 SDL_GetDisplayUsableBounds(monitor->orig_screen, &rect);
163 *pMaxWidth = WINPR_ASSERTING_INT_CAST(uint32_t, rect.w);
164 *pMaxHeight = WINPR_ASSERTING_INT_CAST(uint32_t, rect.h);
167 *pMaxWidth = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.w) *
172 *pMaxHeight = (WINPR_ASSERTING_INT_CAST(uint32_t, rect.h) *
186[[nodiscard]]
static BOOL sdl_apply_display_properties(
SdlContext*
sdl)
190 rdpSettings* settings =
sdl->context()->settings;
191 WINPR_ASSERT(settings);
193 std::vector<rdpMonitor> monitors;
199 if (
sdl->monitorIds().empty())
201 const auto id =
sdl->monitorIds().front();
202 auto monitor =
sdl->getDisplay(
id);
203 monitor.is_primary =
true;
206 monitors.emplace_back(monitor);
212 for (
const auto&
id :
sdl->monitorIds())
214 const auto monitor =
sdl->getDisplay(
id);
215 monitors.emplace_back(monitor);
220 if (!monitors.empty() && std::none_of(monitors.cbegin(), monitors.cend(),
221 [](
const rdpMonitor& m) { return m.is_primary; }))
222 monitors.at(0).is_primary =
true;
227[[nodiscard]]
static BOOL sdl_detect_single_window(
SdlContext*
sdl, UINT32* pMaxWidth,
231 WINPR_ASSERT(pMaxWidth);
232 WINPR_ASSERT(pMaxHeight);
234 rdpSettings* settings =
sdl->context()->settings;
235 WINPR_ASSERT(settings);
246 SDL_DisplayID
id = 0;
247 const auto& ids =
sdl->monitorIds();
252 sdl->setMonitorIds({
id });
255 if (!sdl_apply_display_properties(
sdl))
257 return sdl_apply_max_size(
sdl, pMaxWidth, pMaxHeight);
259 return sdl_apply_mon_max_size(
sdl, pMaxWidth, pMaxHeight);
262BOOL sdl_detect_monitors(
SdlContext*
sdl, UINT32* pMaxWidth, UINT32* pMaxHeight)
265 WINPR_ASSERT(pMaxWidth);
266 WINPR_ASSERT(pMaxHeight);
268 rdpSettings* settings =
sdl->context()->settings;
269 WINPR_ASSERT(settings);
271 const auto& ids =
sdl->getDisplayIds();
276 sdl->setMonitorIds(ids);
279 sdl->setMonitorIds({ ids.front() });
288 "Found %" PRIu32
" monitor IDs, but only have %" PRIuz
" monitors connected",
293 std::vector<SDL_DisplayID> used;
294 for (
size_t x = 0; x < nr; x++)
296 auto cur =
static_cast<const UINT32*
>(
297 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
300 SDL_DisplayID
id = *cur;
303 if (std::find(ids.begin(), ids.end(),
id) == ids.end())
305 WLog_ERR(TAG,
"Supplied monitor ID[%" PRIuz
"]=%" PRIu32
" is invalid", x,
id);
310 if (std::find(used.begin(), used.end(),
id) != used.end())
312 WLog_ERR(TAG,
"Duplicate monitor ID[%" PRIuz
"]=%" PRIu32
" detected", x,
id);
317 sdl->setMonitorIds(used);
320 if (!sdl_apply_display_properties(
sdl))
323 auto size =
static_cast<uint32_t
>(
sdl->monitorIds().size());
327 return sdl_detect_single_window(
sdl, pMaxWidth, pMaxHeight);
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings *settings, const rdpMonitor *monitors, size_t count)
Sort monitor array according to:
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.