24#include "sdl_window.hpp"
25#include "sdl_utils.hpp"
27#include <freerdp/utils/string.h>
30 [[maybe_unused]] Uint32 flags)
31 : _initialW(rect.w), _initialH(rect.h), _displayID(id)
33 float pd = SDL_GetDisplayContentScale(
id);
36 const int createW =
static_cast<int>(std::ceil(
static_cast<float>(rect.w) / pd));
37 const int createH =
static_cast<int>(std::ceil(
static_cast<float>(rect.h) / pd));
39 auto props = SDL_CreateProperties();
40 SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title.c_str());
41 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, rect.x);
42 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, rect.y);
43 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, createW);
44 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, createH);
45 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN,
true);
47 if (flags & SDL_WINDOW_HIGH_PIXEL_DENSITY)
48 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN,
true);
50 if (flags & SDL_WINDOW_FULLSCREEN)
51 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN,
true);
53 if (flags & SDL_WINDOW_BORDERLESS)
54 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN,
true);
56 if (flags & SDL_WINDOW_TRANSPARENT)
57 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN,
true);
60 if (flags & SDL_WINDOW_HIDDEN)
61 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN,
true);
63 _window = SDL_CreateWindowWithProperties(props);
64 SDL_DestroyProperties(props);
65 SDL_SetHint(SDL_HINT_APP_NAME,
"");
66 std::ignore = SDL_SyncWindow(_window);
68 _renderer = SDL_CreateRenderer(_window,
nullptr);
70 std::ignore = resizeToScale();
72 _monitor = query(_window,
id,
true);
76 : _window(other._window), _renderer(other._renderer), _renderTarget(other._renderTarget),
77 _gdiTexture(other._gdiTexture), _gdiTextureW(other._gdiTextureW),
78 _gdiTextureH(other._gdiTextureH), _initialW(other._initialW), _initialH(other._initialH),
79 _displayID(other._displayID), _offset_x(other._offset_x), _offset_y(other._offset_y),
80 _monitor(other._monitor)
82 other._window =
nullptr;
83 other._renderer =
nullptr;
84 other._renderTarget =
nullptr;
85 other._gdiTexture =
nullptr;
88SdlWindow::~SdlWindow()
91 SDL_DestroyTexture(_gdiTexture);
93 SDL_DestroyTexture(_renderTarget);
95 SDL_DestroyRenderer(_renderer);
97 SDL_DestroyWindow(_window);
100SDL_WindowID SdlWindow::id()
const
104 return SDL_GetWindowID(_window);
107SDL_DisplayID SdlWindow::displayIndex()
const
111 return SDL_GetDisplayForWindow(_window);
114SDL_Rect SdlWindow::rect()
const
116 return rect(_window);
119SDL_Rect SdlWindow::bounds()
const
124 if (!SDL_GetWindowPosition(_window, &rect.x, &rect.y))
126 if (!SDL_GetWindowSize(_window, &rect.w, &rect.h))
132SDL_Window* SdlWindow::window()
const
137SDL_Renderer* SdlWindow::renderer()
const
142Sint32 SdlWindow::offsetX()
const
147void SdlWindow::setOffsetX(Sint32 x)
152void SdlWindow::setOffsetY(Sint32 y)
157Sint32 SdlWindow::offsetY()
const
162rdpMonitor SdlWindow::monitor(
bool isPrimary)
const
178float SdlWindow::scale()
const
180 return SDL_GetWindowDisplayScale(_window);
183SDL_DisplayOrientation SdlWindow::orientation()
const
185 const auto did = displayIndex();
186 return SDL_GetCurrentDisplayOrientation(did);
189bool SdlWindow::grabKeyboard(
bool enable)
193 SDL_SetWindowKeyboardGrab(_window, enable);
197bool SdlWindow::grabMouse(
bool enable)
201 SDL_SetWindowMouseGrab(_window, enable);
205void SdlWindow::setBordered(
bool bordered)
208 SDL_SetWindowBordered(_window, bordered);
209 std::ignore = SDL_SyncWindow(_window);
212void SdlWindow::raise()
214 SDL_RaiseWindow(_window);
215 std::ignore = SDL_SyncWindow(_window);
218void SdlWindow::resizeable(
bool use)
220 SDL_SetWindowResizable(_window, use);
221 std::ignore = SDL_SyncWindow(_window);
224void SdlWindow::fullscreen(
bool enter,
bool forceOriginalDisplay)
226 if (enter && forceOriginalDisplay && _displayID != 0)
233 std::ignore = SDL_GetDisplayBounds(_displayID, &rect);
234 std::ignore = SDL_SetWindowPosition(_window, rect.x, rect.y);
236 std::ignore = SDL_SetWindowFullscreen(_window, enter);
237 std::ignore = SDL_SyncWindow(_window);
240void SdlWindow::minimize()
242 SDL_MinimizeWindow(_window);
243 std::ignore = SDL_SyncWindow(_window);
246bool SdlWindow::resizeToScale()
248 if (!_window || _initialW <= 0 || _initialH <= 0)
250 if ((SDL_GetWindowFlags(_window) & SDL_WINDOW_FULLSCREEN) != 0)
253 float pd = SDL_GetWindowPixelDensity(_window);
257 const int targetW =
static_cast<int>(std::ceil(
static_cast<float>(_initialW) / pd));
258 const int targetH =
static_cast<int>(std::ceil(
static_cast<float>(_initialH) / pd));
262 if (!SDL_GetWindowSize(_window, &curW, &curH))
265 if (curW == targetW && curH == targetH)
268 return resize({ targetW, targetH });
271bool SdlWindow::resize(
const SDL_Point& size)
273 return SDL_SetWindowSize(_window, size.x, size.y);
276void SdlWindow::ensureRenderTarget()
283 SDL_GetWindowSizeInPixels(_window, &w, &h);
284 if (w <= 0 || h <= 0)
292 if (!SDL_GetTextureSize(_renderTarget, &tw, &th))
294 if (
static_cast<int>(tw) == w &&
static_cast<int>(th) == h)
296 SDL_DestroyTexture(_renderTarget);
300 SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_TARGET, w, h);
303 SDL_LogError(SDL_LOG_CATEGORY_RENDER,
"SDL_CreateTexture (render target): %s",
308 std::ignore = SDL_SetTextureBlendMode(_renderTarget, SDL_BLENDMODE_NONE);
311 if (SDL_SetRenderTarget(_renderer, _renderTarget))
313 std::ignore = SDL_SetRenderDrawColor(_renderer, 0x00, 0x00, 0x00, 0x00);
314 std::ignore = SDL_RenderClear(_renderer);
318bool SdlWindow::drawRect(SDL_Surface* surface, SDL_Point offset,
const SDL_Rect& srcRect)
320 WINPR_ASSERT(surface);
321 SDL_Rect dstRect = { offset.x + srcRect.x, offset.y + srcRect.y, srcRect.w, srcRect.h };
322 return blit(surface, srcRect, dstRect);
325bool SdlWindow::drawRects(SDL_Surface* surface, SDL_Point offset,
326 const std::vector<SDL_Rect>& rects)
330 return drawRect(surface, offset, { 0, 0, surface->w, surface->h });
332 for (
auto& srcRect : rects)
334 if (!drawRect(surface, offset, srcRect))
340bool SdlWindow::drawScaledRect(SDL_Surface* surface,
const SDL_FPoint& scale,
341 const SDL_Rect& srcRect)
343 SDL_Rect dstRect = {};
346 const auto modx = std::modf(
static_cast<float>(srcRect.x) * scale.x, &ix);
347 const auto mody = std::modf(
static_cast<float>(srcRect.y) * scale.y, &iy);
348 auto sw = std::ceil(
static_cast<float>(srcRect.w) * scale.x) + std::ceil(modx);
349 auto sh = std::ceil(
static_cast<float>(srcRect.h) * scale.y) + std::ceil(mody);
350 dstRect.x =
static_cast<Sint32
>(ix);
351 dstRect.w =
static_cast<Sint32
>(sw);
352 dstRect.y =
static_cast<Sint32
>(iy);
353 dstRect.h =
static_cast<Sint32
>(sh);
354 return blit(surface, srcRect, dstRect);
357bool SdlWindow::drawScaledRects(SDL_Surface* surface,
const SDL_FPoint& scale,
358 const std::vector<SDL_Rect>& rects)
362 return drawScaledRect(surface, scale, { 0, 0, surface->w, surface->h });
364 for (
const auto& srcRect : rects)
366 if (!drawScaledRect(surface, scale, srcRect))
372bool SdlWindow::fill(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
376 ensureRenderTarget();
377 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
379 if (!SDL_SetRenderDrawColor(_renderer, r, g, b, a))
381 return SDL_RenderClear(_renderer);
383 return fill(_window, r, g, b, a);
386bool SdlWindow::fill(SDL_Window* window, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
388 auto surface = SDL_GetWindowSurface(window);
391 SDL_Rect rect = { 0, 0, surface->w, surface->h };
392 auto color = SDL_MapSurfaceRGBA(surface, r, g, b, a);
394 return SDL_FillSurfaceRect(surface, &rect, color);
397rdpMonitor SdlWindow::query(SDL_Window* window, SDL_DisplayID
id,
bool forceAsPrimary)
402 const auto& r = rect(window, forceAsPrimary);
403 const float factor = SDL_GetWindowDisplayScale(window);
404 const float dpi = std::roundf(factor * 100.0f);
406 WINPR_ASSERT(r.w > 0);
407 WINPR_ASSERT(r.h > 0);
409 const auto primary = SDL_GetPrimaryDisplay();
410 const auto orientation = SDL_GetCurrentDisplayOrientation(
id);
411 const auto rdp_orientation = sdl::utils::orientaion_to_rdp(orientation);
414 monitor.orig_screen = id;
418 monitor.height = r.h;
419 monitor.is_primary = forceAsPrimary || (
id == primary);
420 monitor.attributes.desktopScaleFactor =
static_cast<UINT32
>(dpi);
421 monitor.attributes.deviceScaleFactor = 100;
422 monitor.attributes.orientation = rdp_orientation;
423 monitor.attributes.physicalWidth = WINPR_ASSERTING_INT_CAST(uint32_t, r.w);
424 monitor.attributes.physicalHeight = WINPR_ASSERTING_INT_CAST(uint32_t, r.h);
426 const auto cat = SDL_LOG_CATEGORY_APPLICATION;
427 SDL_LogDebug(cat,
"monitor.orig_screen %" PRIu32, monitor.orig_screen);
428 SDL_LogDebug(cat,
"monitor.x %" PRId32, monitor.x);
429 SDL_LogDebug(cat,
"monitor.y %" PRId32, monitor.y);
430 SDL_LogDebug(cat,
"monitor.width %" PRId32, monitor.width);
431 SDL_LogDebug(cat,
"monitor.height %" PRId32, monitor.height);
432 SDL_LogDebug(cat,
"monitor.is_primary %" PRIu32, monitor.is_primary);
433 SDL_LogDebug(cat,
"monitor.attributes.desktopScaleFactor %" PRIu32,
434 monitor.attributes.desktopScaleFactor);
435 SDL_LogDebug(cat,
"monitor.attributes.deviceScaleFactor %" PRIu32,
436 monitor.attributes.deviceScaleFactor);
437 SDL_LogDebug(cat,
"monitor.attributes.orientation %s",
438 freerdp_desktop_rotation_flags_to_string(monitor.attributes.orientation));
439 SDL_LogDebug(cat,
"monitor.attributes.physicalWidth %" PRIu32,
440 monitor.attributes.physicalWidth);
441 SDL_LogDebug(cat,
"monitor.attributes.physicalHeight %" PRIu32,
442 monitor.attributes.physicalHeight);
446SDL_Rect SdlWindow::rect(SDL_Window* window,
bool forceAsPrimary)
454 if (!SDL_GetWindowPosition(window, &rect.x, &rect.y))
458 if (!SDL_GetWindowSizeInPixels(window, &rect.w, &rect.h))
461 const auto flags = SDL_GetWindowFlags(window);
462 const auto mask = SDL_WINDOW_FULLSCREEN;
463 const auto fs = (flags & mask) == mask;
472 const auto displayID = SDL_GetDisplayForWindow(window);
473 SDL_Rect displayBounds = {};
474 if (SDL_GetDisplayBounds(displayID, &displayBounds))
485 rect.x = displayBounds.x;
486 rect.y = displayBounds.y;
488 rect.w = displayBounds.w;
489 rect.h = displayBounds.h;
491 const float contentScale = SDL_GetDisplayContentScale(displayID);
492 if (contentScale > 1.0f)
494 const auto fw =
static_cast<float>(rect.w);
495 const auto fh =
static_cast<float>(rect.h);
496 rect.w =
static_cast<int>(std::roundf(fw * contentScale));
497 rect.h =
static_cast<int>(std::roundf(fh * contentScale));
505SdlWindow::HighDPIMode SdlWindow::isHighDPIWindowsMode(SDL_Window* window)
510 const auto id = SDL_GetDisplayForWindow(window);
514 const auto cs = SDL_GetDisplayContentScale(
id);
515 const auto ds = SDL_GetWindowDisplayScale(window);
516 const auto pd = SDL_GetWindowPixelDensity(window);
519 if ((cs == 1.0f) && (ds == 1.0f) && (pd == 1.0f))
523 if ((cs == 1.0f) && (ds > 1.0f) && (pd > 1.0f))
531bool SdlWindow::ensureGdiTexture(SDL_Surface* surface)
533 if (_gdiTexture && (_gdiTextureW == surface->w) && (_gdiTextureH == surface->h))
536 SDL_DestroyTexture(_gdiTexture);
537 _gdiTexture = SDL_CreateTexture(_renderer, surface->format, SDL_TEXTUREACCESS_STREAMING,
538 surface->w, surface->h);
541 SDL_LogError(SDL_LOG_CATEGORY_RENDER,
"SDL_CreateTexture: %s", SDL_GetError());
544 std::ignore = SDL_SetTextureBlendMode(_gdiTexture, SDL_BLENDMODE_NONE);
545 _gdiTextureW = surface->w;
546 _gdiTextureH = surface->h;
550bool SdlWindow::blit(SDL_Surface* surface,
const SDL_Rect& srcRect, SDL_Rect& dstRect)
552 if (!_renderer || !surface)
555 ensureRenderTarget();
557 if (!ensureGdiTexture(surface))
561 const auto* details = SDL_GetPixelFormatDetails(surface->format);
562 const int bpp = details ? details->bytes_per_pixel : 4;
563 const auto* pixels =
static_cast<const uint8_t*
>(surface->pixels) +
564 (1ll * srcRect.y * surface->pitch) + (1ll * srcRect.x * bpp);
565 if (!SDL_UpdateTexture(_gdiTexture, &srcRect, pixels, surface->pitch))
567 SDL_LogError(SDL_LOG_CATEGORY_RENDER,
"SDL_UpdateTexture: %s", SDL_GetError());
572 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
575 SDL_FRect fsrc = {
static_cast<float>(srcRect.x),
static_cast<float>(srcRect.y),
576 static_cast<float>(srcRect.w),
static_cast<float>(srcRect.h) };
577 SDL_FRect fdst = {
static_cast<float>(dstRect.x),
static_cast<float>(dstRect.y),
578 static_cast<float>(dstRect.w),
static_cast<float>(dstRect.h) };
579 if (!SDL_RenderTexture(_renderer, _gdiTexture, &fsrc, &fdst))
581 SDL_LogError(SDL_LOG_CATEGORY_RENDER,
"SDL_RenderTexture: %s", SDL_GetError());
587void SdlWindow::updateSurface()
592 ensureRenderTarget();
595 if (!SDL_SetRenderTarget(_renderer,
nullptr))
597 if (!SDL_RenderTexture(_renderer, _renderTarget,
nullptr,
nullptr))
599 if (!SDL_RenderPresent(_renderer))
603bool SdlWindow::paintResizeFrame(SDL_Surface* surface, SDL_Point off,
bool contentChanged,
604 const SDL_Rect& inset,
bool fillRevealed,
bool dashedBorder)
606 if (!_renderer || !surface)
608 ensureRenderTarget();
610 const int prevW = _gdiTextureW;
611 const int prevH = _gdiTextureH;
612 if (!ensureGdiTexture(surface))
615 const bool recreated = (_gdiTextureW != prevW) || (_gdiTextureH != prevH);
616 if ((contentChanged || recreated) &&
617 !SDL_UpdateTexture(_gdiTexture,
nullptr, surface->pixels, surface->pitch))
620 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
625 SDL_GetWindowSizeInPixels(_window, &ww, &wh);
627 const SDL_FRect frame = {
static_cast<float>(inset.x),
static_cast<float>(inset.y),
628 static_cast<float>(ww - inset.x - inset.w),
629 static_cast<float>(wh - inset.y - inset.h) };
632 constexpr Uint8 kFillAlpha = 0x80;
633 std::ignore = SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);
634 std::ignore = SDL_SetRenderDrawColor(_renderer, 0, 0, 0, 0);
635 std::ignore = SDL_RenderClear(_renderer);
638 std::ignore = SDL_SetRenderDrawColor(_renderer, 0x2B, 0x2B, 0x2B, kFillAlpha);
639 std::ignore = SDL_RenderFillRect(_renderer, &frame);
641 SDL_FRect fdst = {
static_cast<float>(off.x),
static_cast<float>(off.y),
642 static_cast<float>(surface->w),
static_cast<float>(surface->h) };
644 const SDL_Rect clip = { inset.x, inset.y, ww - inset.x - inset.w, wh - inset.y - inset.h };
645 std::ignore = SDL_SetRenderClipRect(_renderer, &clip);
646 std::ignore = SDL_RenderTexture(_renderer, _gdiTexture,
nullptr, &fdst);
647 std::ignore = SDL_SetRenderClipRect(_renderer,
nullptr);
652 std::ignore = SDL_SetRenderDrawColor(_renderer, 0xC8, 0xC8, 0xC8, 0xFF);
653 const float dash = 8.0F;
654 const float gap = 5.0F;
655 const float fx2 = frame.x + frame.w;
656 const float fy2 = frame.y + frame.h;
657 const float lo = frame.y + 0.5F;
658 const float by = fy2 - 0.5F;
659 const float lx = frame.x + 0.5F;
660 const float rx = fx2 - 0.5F;
661 const float step = dash + gap;
662 const auto steps = [step](
float len)
663 {
return (len <= 0.0F) ? 0 :
static_cast<int>(std::ceil(len / step)); };
664 for (
int i = 0; i < steps(fx2 - frame.x); i++)
666 const float x = frame.x + (
static_cast<float>(i) * step);
667 const float x2 = (x + dash < fx2) ? (x + dash) : rx;
668 std::ignore = SDL_RenderLine(_renderer, x, lo, x2, lo);
669 std::ignore = SDL_RenderLine(_renderer, x, by, x2, by);
671 for (
int i = 0; i < steps(fy2 - frame.y); i++)
673 const float y = frame.y + (
static_cast<float>(i) * step);
674 const float y2 = (y + dash < fy2) ? (y + dash) : by;
675 std::ignore = SDL_RenderLine(_renderer, lx, y, lx, y2);
676 std::ignore = SDL_RenderLine(_renderer, rx, y, rx, y2);
680 if (!SDL_SetRenderTarget(_renderer,
nullptr))
682 std::ignore = SDL_RenderTexture(_renderer, _renderTarget,
nullptr,
nullptr);
683 std::ignore = SDL_RenderPresent(_renderer);
687SdlWindow SdlWindow::create(SDL_DisplayID
id,
const std::string& title, Uint32 flags, Uint32 width,
690 flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
692 SDL_Rect rect = {
static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(
id)),
693 static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(
id)),
static_cast<int>(width),
694 static_cast<int>(height) };
696 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
698 std::ignore = SDL_GetDisplayBounds(
id, &rect);
701 SdlWindow window{ id, title, rect, flags };
703 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
705 window.setOffsetX(rect.x);
706 window.setOffsetY(rect.y);
712SdlWindow SdlWindow::create(SDL_DisplayID
id,
const std::string& title, Uint32 flags,
713 const SDL_Rect& rect)
715 return SdlWindow{ id, title, rect, flags };
720 : _initialW(rect.w), _initialH(rect.h)
722 auto props = SDL_CreateProperties();
723 SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, parent);
724 SDL_SetBooleanProperty(props,
725 tooltip ? SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN
726 : SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN,
728 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN,
false);
729 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN,
true);
732 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN,
true);
733 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, rect.x);
734 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, rect.y);
735 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, rect.w);
736 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, rect.h);
738 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN,
true);
740 _window = SDL_CreateWindowWithProperties(props);
741 SDL_DestroyProperties(props);
744 std::ignore = SDL_SyncWindow(_window);
745 _renderer = SDL_CreateRenderer(_window,
nullptr);
746 _displayID = SDL_GetDisplayForWindow(_window);
750SdlWindow SdlWindow::createPopup(SDL_Window* parent,
const SDL_Rect& rect,
bool transparent,
753 return SdlWindow{ parent, rect, transparent, tooltip };
756static SDL_Window* createDummy(SDL_DisplayID
id)
758 const auto x = SDL_WINDOWPOS_CENTERED_DISPLAY(
id);
759 const auto y = SDL_WINDOWPOS_CENTERED_DISPLAY(
id);
763 auto props = SDL_CreateProperties();
764 std::stringstream ss;
765 ss <<
"SdlWindow::query(" <<
id <<
")";
766 SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, ss.str().c_str());
767 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x);
768 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y);
769 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, w);
770 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, h);
772 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN,
true);
773 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN,
false);
774 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN,
true);
775 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN,
false);
777 auto window = SDL_CreateWindowWithProperties(props);
778 SDL_DestroyProperties(props);
786 std::ignore = SDL_GetDisplayBounds(
id, &rect);
787 std::ignore = SDL_SetWindowPosition(window, rect.x, rect.y);
788 std::ignore = SDL_SetWindowFullscreen(window,
true);
793rdpMonitor SdlWindow::query(SDL_DisplayID
id,
bool forceAsPrimary)
795 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(
id), SDL_DestroyWindow);
799 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
800 SDL_CreateRenderer(window.get(),
nullptr), SDL_DestroyRenderer);
802 if (!SDL_SyncWindow(window.get()))
806 while (SDL_PollEvent(&event))
809 return query(window.get(),
id, forceAsPrimary);
812SDL_Rect SdlWindow::rect(SDL_DisplayID
id,
bool forceAsPrimary)
814 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(
id), SDL_DestroyWindow);
818 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
819 SDL_CreateRenderer(window.get(),
nullptr), SDL_DestroyRenderer);
821 if (!SDL_SyncWindow(window.get()))
825 while (SDL_PollEvent(&event))
828 return rect(window.get(), forceAsPrimary);
831bool SdlWindow::tryFallback(
bool isFullscreen)
836 const auto wlroots_hack = SDL_getenv(
"FREERDP_WLROOTS_HACK");
837 if (wlroots_hack !=
nullptr)
839 const auto enabled = strcmp(wlroots_hack,
"0") != 0;
840 if (strcmp(wlroots_hack,
"force") == 0)
842 return enabled && isFullscreen;
845 const auto platform = SDL_GetPlatform();
846 if ((platform ==
nullptr) || (strcmp(platform,
"Linux") != 0))
849 const auto driver = SDL_GetCurrentVideoDriver();
850 if ((driver ==
nullptr) || (strcmp(driver,
"wayland") != 0))
860 auto isWlrootsCompositor = [](
const char* value) ->
bool
864 if (strstr(value,
"sway") || strstr(value,
"Sway") || strstr(value,
"Hyprland") ||
865 strstr(value,
"hyprland") || strstr(value,
"river") || strstr(value,
"wlroots"))
870 const auto xdg_session = SDL_getenv(
"XDG_SESSION_DESKTOP");
871 if (isWlrootsCompositor(xdg_session))
874 const auto xdg_desktop = SDL_getenv(
"XDG_CURRENT_DESKTOP");
875 if (isWlrootsCompositor(xdg_desktop))
SdlWindow(const std::string &title, Sint32 startupX, Sint32 startupY, Sint32 width, Sint32 height, Uint32 flags)