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.