FreeRDP
Loading...
Searching...
No Matches
SdlWindow Class Reference

#include <sdl_window.hpp>

Public Member Functions

 SdlWindow (const std::string &title, Sint32 startupX, Sint32 startupY, Sint32 width, Sint32 height, Uint32 flags)
 
 SdlWindow (const SdlWindow &other)=delete
 
 SdlWindow (SdlWindow &&other) noexcept
 
SdlWindow & operator= (const SdlWindow &other)=delete
 
SdlWindow & operator= (SdlWindow &&other)=delete
 
Uint32 id () const
 
int displayIndex () const
 
SDL_Rect rect () const
 
SDL_Window * window () const
 
Sint32 offsetX () const
 
void setOffsetX (Sint32 x)
 
void setOffsetY (Sint32 y)
 
Sint32 offsetY () const
 
bool grabKeyboard (bool enable)
 
bool grabMouse (bool enable)
 
void setBordered (bool bordered)
 
void raise ()
 
void resizeable (bool use)
 
void fullscreen (bool enter)
 
void minimize ()
 
bool fill (Uint8 r=0x00, Uint8 g=0x00, Uint8 b=0x00, Uint8 a=0xff)
 
bool blit (SDL_Surface *surface, SDL_Rect src, SDL_Rect &dst)
 
void updateSurface ()
 
 SdlWindow (SdlWindow &&other) noexcept
 
 SdlWindow (const SdlWindow &other)=delete
 
SdlWindow & operator= (const SdlWindow &other)=delete
 
SdlWindow & operator= (SdlWindow &&other)=delete
 
SDL_WindowID id () const
 
SDL_DisplayID displayIndex () const
 
SDL_Rect rect () const
 
SDL_Rect bounds () const
 
SDL_Window * window () const
 
SDL_Renderer * renderer () const
 
Sint32 offsetX () const
 
void setOffsetX (Sint32 x)
 
void setOffsetY (Sint32 y)
 
Sint32 offsetY () const
 
rdpMonitor monitor (bool isPrimary) const
 
void setMonitor (rdpMonitor monitor)
 
float scale () const
 
SDL_DisplayOrientation orientation () const
 
bool grabKeyboard (bool enable)
 
bool grabMouse (bool enable)
 
void setBordered (bool bordered)
 
void raise ()
 
void resizeable (bool use)
 
void fullscreen (bool enter, bool forceOriginalDisplay)
 
void minimize ()
 
bool resizeToScale ()
 
bool resize (const SDL_Point &size)
 
bool drawRect (SDL_Surface *surface, SDL_Point offset, const SDL_Rect &srcRect)
 
bool drawRects (SDL_Surface *surface, SDL_Point offset, const std::vector< SDL_Rect > &rects={})
 
bool drawScaledRect (SDL_Surface *surface, const SDL_FPoint &scale, const SDL_Rect &srcRect)
 
bool drawScaledRects (SDL_Surface *surface, const SDL_FPoint &scale, const std::vector< SDL_Rect > &rects={})
 
bool fill (Uint8 r=0x00, Uint8 g=0x00, Uint8 b=0x00, Uint8 a=0xff)
 
bool blit (SDL_Surface *surface, const SDL_Rect &src, SDL_Rect &dst)
 
bool paintResizeFrame (SDL_Surface *surface, SDL_Point off, bool contentChanged, const SDL_Rect &inset={ 0, 0, 0, 0 }, bool fillRevealed=true, bool dashedBorder=true)
 
void updateSurface ()
 

Static Public Member Functions

static SdlWindow create (SDL_DisplayID id, const std::string &title, Uint32 flags, Uint32 width=0, Uint32 height=0)
 
static SdlWindow create (SDL_DisplayID id, const std::string &title, Uint32 flags, const SDL_Rect &rect)
 
static SdlWindow createPopup (SDL_Window *parent, const SDL_Rect &rect, bool transparent, bool tooltip=false)
 
static rdpMonitor query (SDL_DisplayID id, bool forceAsPrimary=false)
 

Protected Types

enum  HighDPIMode { MODE_INVALID , MODE_NONE , MODE_WINDOWS , MODE_MACOS }
 

Protected Member Functions

 SdlWindow (SDL_DisplayID id, const std::string &title, const SDL_Rect &rect, Uint32 flags)
 
 SdlWindow (SDL_Window *parent, const SDL_Rect &rect, bool transparent, bool tooltip)
 

Static Protected Member Functions

static bool fill (SDL_Window *window, Uint8 r=0x00, Uint8 g=0x00, Uint8 b=0x00, Uint8 a=0xff)
 
static rdpMonitor query (SDL_Window *window, SDL_DisplayID id, bool forceAsPrimary=false)
 
static SDL_Rect rect (SDL_Window *window, bool forceAsPrimary=false)
 
static SDL_Rect rect (SDL_DisplayID id, bool forceAsPrimary=false)
 
static bool tryFallback (bool isFullscreen)
 
static enum HighDPIMode isHighDPIWindowsMode (SDL_Window *window)
 

Detailed Description

FreeRDP: A Remote Desktop Protocol Implementation SDL Client

Copyright 2023 Armin Novak armin.nosp@m..nov.nosp@m.ak@th.nosp@m.inca.nosp@m.st.co.nosp@m.m Copyright 2023 Thincast Technologies GmbH

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Definition at line 25 of file SDL2/sdl_window.hpp.

Member Enumeration Documentation

◆ HighDPIMode

enum SdlWindow::HighDPIMode
protected

Definition at line 110 of file SDL3/sdl_window.hpp.

111 {
112 MODE_INVALID,
113 MODE_NONE,
114 MODE_WINDOWS,
115 MODE_MACOS
116 };

Constructor & Destructor Documentation

◆ SdlWindow() [1/4]

SdlWindow::SdlWindow ( const std::string &  title,
Sint32  startupX,
Sint32  startupY,
Sint32  width,
Sint32  height,
Uint32  flags 
)

FreeRDP: A Remote Desktop Protocol Implementation SDL Client

Copyright 2023 Armin Novak armin.nosp@m..nov.nosp@m.ak@th.nosp@m.inca.nosp@m.st.co.nosp@m.m Copyright 2023 Thincast Technologies GmbH

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Definition at line 23 of file SDL2/sdl_window.cpp.

25 : _window(SDL_CreateWindow(title.c_str(), startupX, startupY, width, height, flags))
26{
27}

◆ SdlWindow() [2/4]

SdlWindow::SdlWindow ( SdlWindow &&  other)
noexcept

Definition at line 29 of file SDL2/sdl_window.cpp.

30 : _window(other._window), _offset_x(other._offset_x), _offset_y(other._offset_y)
31{
32 other._window = nullptr;
33}

◆ ~SdlWindow()

SdlWindow::~SdlWindow ( )

Definition at line 35 of file SDL2/sdl_window.cpp.

36{
37 SDL_DestroyWindow(_window);
38}

◆ SdlWindow() [3/4]

SdlWindow::SdlWindow ( SDL_DisplayID  id,
const std::string &  title,
const SDL_Rect &  rect,
Uint32  flags 
)
protected

FreeRDP: A Remote Desktop Protocol Implementation SDL Client

Copyright 2023 Armin Novak armin.nosp@m..nov.nosp@m.ak@th.nosp@m.inca.nosp@m.st.co.nosp@m.m Copyright 2023 Thincast Technologies GmbH

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Definition at line 29 of file SDL3/sdl_window.cpp.

31 : _initialW(rect.w), _initialH(rect.h), _displayID(id)
32{
33 float pd = SDL_GetDisplayContentScale(id);
34 if (pd <= 0.0f)
35 pd = 1.0f;
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));
38
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);
46
47 if (flags & SDL_WINDOW_HIGH_PIXEL_DENSITY)
48 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, true);
49
50 if (flags & SDL_WINDOW_FULLSCREEN)
51 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, true);
52
53 if (flags & SDL_WINDOW_BORDERLESS)
54 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN, true);
55
56 if (flags & SDL_WINDOW_TRANSPARENT)
57 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN, true);
58
59 /* RAIL windows are created hidden until first paint to avoid black flash. */
60 if (flags & SDL_WINDOW_HIDDEN)
61 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, true);
62
63 _window = SDL_CreateWindowWithProperties(props);
64 SDL_DestroyProperties(props);
65 SDL_SetHint(SDL_HINT_APP_NAME, "");
66 std::ignore = SDL_SyncWindow(_window);
67
68 _renderer = SDL_CreateRenderer(_window, nullptr);
69
70 std::ignore = resizeToScale();
71
72 _monitor = query(_window, id, true);
73}

◆ SdlWindow() [4/4]

SdlWindow::SdlWindow ( SDL_Window *  parent,
const SDL_Rect &  rect,
bool  transparent,
bool  tooltip 
)
protected

Definition at line 748 of file SDL3/sdl_window.cpp.

749 : _initialW(rect.w), _initialH(rect.h)
750{
751 auto props = SDL_CreateProperties();
752 SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, parent);
753 SDL_SetBooleanProperty(props,
754 tooltip ? SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN
755 : SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN,
756 true);
757 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, false);
758#if defined(SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN)
759 /* The server places RemoteApp popups; a moved one would map clicks to other points. */
760 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN, false);
761#endif
762 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN, true);
763 /* Transparent so menus' genuine per-pixel alpha (corners/shadow) isn't rendered black. */
764 if (transparent)
765 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN, true);
766 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, rect.x);
767 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, rect.y);
768 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, rect.w);
769 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, rect.h);
770 /* Hidden until first paint, like the app constructor. */
771 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, true);
772
773 _window = SDL_CreateWindowWithProperties(props);
774 SDL_DestroyProperties(props);
775 if (_window)
776 {
777 std::ignore = SDL_SyncWindow(_window);
778 _renderer = SDL_CreateRenderer(_window, nullptr);
779 _displayID = SDL_GetDisplayForWindow(_window);
780 }
781}

Member Function Documentation

◆ blit() [1/2]

bool SdlWindow::blit ( SDL_Surface *  surface,
const SDL_Rect &  src,
SDL_Rect &  dst 
)

Definition at line 579 of file SDL3/sdl_window.cpp.

580{
581 if (!_renderer || !surface)
582 return false;
583
584 ensureRenderTarget();
585
586 if (!ensureGdiTexture(surface))
587 return false;
588
589 /* Upload only the dirty region */
590 const auto* details = SDL_GetPixelFormatDetails(surface->format);
591 const int bpp = details ? details->bytes_per_pixel : 4;
592 const auto* pixels = static_cast<const uint8_t*>(surface->pixels) +
593 (1ll * srcRect.y * surface->pitch) + (1ll * srcRect.x * bpp);
594 if (!SDL_UpdateTexture(_gdiTexture, &srcRect, pixels, surface->pitch))
595 {
596 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_UpdateTexture: %s", SDL_GetError());
597 return false;
598 }
599
600 /* Render onto persistent render target to accumulate dirty rects */
601 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
602 return false;
603
604 SDL_FRect fsrc = { static_cast<float>(srcRect.x), static_cast<float>(srcRect.y),
605 static_cast<float>(srcRect.w), static_cast<float>(srcRect.h) };
606 SDL_FRect fdst = { static_cast<float>(dstRect.x), static_cast<float>(dstRect.y),
607 static_cast<float>(dstRect.w), static_cast<float>(dstRect.h) };
608 if (!SDL_RenderTexture(_renderer, _gdiTexture, &fsrc, &fdst))
609 {
610 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_RenderTexture: %s", SDL_GetError());
611 return false;
612 }
613 return true;
614}

◆ blit() [2/2]

bool SdlWindow::blit ( SDL_Surface *  surface,
SDL_Rect  src,
SDL_Rect &  dst 
)

Definition at line 187 of file SDL2/sdl_window.cpp.

188{
189 auto screen = SDL_GetWindowSurface(_window);
190 if (!screen || !surface)
191 return false;
192 if (!SDL_SetClipRect(surface, &srcRect))
193 return true;
194 if (!SDL_SetClipRect(screen, &dstRect))
195 return true;
196 auto rc = SDL_BlitScaled(surface, &srcRect, screen, &dstRect);
197 if (rc != 0)
198 {
199 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_BlitScaled: %s [%d]", sdl_error_string(rc), rc);
200 }
201 return rc == 0;
202}

◆ bounds()

SDL_Rect SdlWindow::bounds ( ) const

Definition at line 119 of file SDL3/sdl_window.cpp.

120{
121 SDL_Rect rect = {};
122 if (_window)
123 {
124 if (!SDL_GetWindowPosition(_window, &rect.x, &rect.y))
125 return {};
126 if (!SDL_GetWindowSize(_window, &rect.w, &rect.h))
127 return {};
128 }
129 return rect;
130}

◆ create() [1/2]

SdlWindow SdlWindow::create ( SDL_DisplayID  id,
const std::string &  title,
Uint32  flags,
const SDL_Rect &  rect 
)
static

Definition at line 741 of file SDL3/sdl_window.cpp.

743{
744 return SdlWindow{ id, title, rect, flags };
745}

◆ create() [2/2]

SdlWindow SdlWindow::create ( SDL_DisplayID  id,
const std::string &  title,
Uint32  flags,
Uint32  width = 0,
Uint32  height = 0 
)
static

Definition at line 716 of file SDL3/sdl_window.cpp.

718{
719 flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
720
721 SDL_Rect rect = { static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)),
722 static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)), static_cast<int>(width),
723 static_cast<int>(height) };
724
725 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
726 {
727 std::ignore = SDL_GetDisplayBounds(id, &rect);
728 }
729
730 SdlWindow window{ id, title, rect, flags };
731
732 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
733 {
734 window.setOffsetX(rect.x);
735 window.setOffsetY(rect.y);
736 }
737
738 return window;
739}

◆ createPopup()

SdlWindow SdlWindow::createPopup ( SDL_Window *  parent,
const SDL_Rect &  rect,
bool  transparent,
bool  tooltip = false 
)
static

Definition at line 783 of file SDL3/sdl_window.cpp.

785{
786 return SdlWindow{ parent, rect, transparent, tooltip };
787}

◆ displayIndex()

SDL_DisplayID SdlWindow::displayIndex ( ) const

Definition at line 47 of file SDL2/sdl_window.cpp.

48{
49 if (!_window)
50 return 0;
51 return SDL_GetWindowDisplayIndex(_window);
52}

◆ drawRect()

bool SdlWindow::drawRect ( SDL_Surface *  surface,
SDL_Point  offset,
const SDL_Rect &  srcRect 
)

Definition at line 320 of file SDL3/sdl_window.cpp.

321{
322 WINPR_ASSERT(surface);
323 SDL_Rect dstRect = { offset.x + srcRect.x, offset.y + srcRect.y, srcRect.w, srcRect.h };
324 return blit(surface, srcRect, dstRect);
325}

◆ drawRects()

bool SdlWindow::drawRects ( SDL_Surface *  surface,
SDL_Point  offset,
const std::vector< SDL_Rect > &  rects = {} 
)

Definition at line 327 of file SDL3/sdl_window.cpp.

329{
330 if (rects.empty())
331 {
332 return drawRect(surface, offset, { 0, 0, surface->w, surface->h });
333 }
334 for (auto& srcRect : rects)
335 {
336 if (!drawRect(surface, offset, srcRect))
337 return false;
338 }
339 return true;
340}

◆ drawScaledRect()

bool SdlWindow::drawScaledRect ( SDL_Surface *  surface,
const SDL_FPoint &  scale,
const SDL_Rect &  srcRect 
)

Definition at line 342 of file SDL3/sdl_window.cpp.

344{
345 SDL_Rect dstRect = {};
346 float ix = 0.0f;
347 float iy = 0.0f;
348 const auto modx = std::modf(static_cast<float>(srcRect.x) * scale.x, &ix);
349 const auto mody = std::modf(static_cast<float>(srcRect.y) * scale.y, &iy);
350 auto sw = std::ceil(static_cast<float>(srcRect.w) * scale.x) + std::ceil(modx);
351 auto sh = std::ceil(static_cast<float>(srcRect.h) * scale.y) + std::ceil(mody);
352 dstRect.x = static_cast<Sint32>(ix);
353 dstRect.w = static_cast<Sint32>(sw);
354 dstRect.y = static_cast<Sint32>(iy);
355 dstRect.h = static_cast<Sint32>(sh);
356 return blit(surface, srcRect, dstRect);
357}

◆ drawScaledRects()

bool SdlWindow::drawScaledRects ( SDL_Surface *  surface,
const SDL_FPoint &  scale,
const std::vector< SDL_Rect > &  rects = {} 
)

Definition at line 359 of file SDL3/sdl_window.cpp.

361{
362 if (rects.empty())
363 {
364 return drawScaledRect(surface, scale, { 0, 0, surface->w, surface->h });
365 }
366 for (const auto& srcRect : rects)
367 {
368 if (!drawScaledRect(surface, scale, srcRect))
369 return false;
370 }
371 return true;
372}

◆ fill() [1/2]

bool SdlWindow::fill ( SDL_Window *  window,
Uint8  r = 0x00,
Uint8  g = 0x00,
Uint8  b = 0x00,
Uint8  a = 0xff 
)
staticprotected

Definition at line 388 of file SDL3/sdl_window.cpp.

389{
390 auto surface = SDL_GetWindowSurface(window);
391 if (!surface)
392 return false;
393 SDL_Rect rect = { 0, 0, surface->w, surface->h };
394 auto color = SDL_MapSurfaceRGBA(surface, r, g, b, a);
395
396 return SDL_FillSurfaceRect(surface, &rect, color);
397}

◆ fill() [2/2]

bool SdlWindow::fill ( Uint8  r = 0x00,
Uint8  g = 0x00,
Uint8  b = 0x00,
Uint8  a = 0xff 
)

Definition at line 175 of file SDL2/sdl_window.cpp.

176{
177 auto surface = SDL_GetWindowSurface(_window);
178 if (!surface)
179 return false;
180 SDL_Rect rect = { 0, 0, surface->w, surface->h };
181 auto color = SDL_MapRGBA(surface->format, r, g, b, a);
182
183 SDL_FillRect(surface, &rect, color);
184 return true;
185}

◆ fullscreen() [1/2]

void SdlWindow::fullscreen ( bool  enter)

Definition at line 131 of file SDL2/sdl_window.cpp.

132{
133 auto curFlags = SDL_GetWindowFlags(_window);
134
135 if (enter)
136 {
137 if (!(curFlags & SDL_WINDOW_BORDERLESS))
138 {
139 auto idx = SDL_GetWindowDisplayIndex(_window);
140 SDL_DisplayMode mode = {};
141 SDL_GetCurrentDisplayMode(idx, &mode);
142
143 SDL_RestoreWindow(_window); // Maximize so we can see the caption and
144 // bits
145 SDL_SetWindowBordered(_window, SDL_FALSE);
146 SDL_SetWindowPosition(_window, 0, 0);
147#if SDL_VERSION_ATLEAST(2, 0, 16)
148 SDL_SetWindowAlwaysOnTop(_window, SDL_TRUE);
149#endif
150 SDL_RaiseWindow(_window);
151 SDL_SetWindowSize(_window, mode.w, mode.h);
152 }
153 }
154 else
155 {
156 if (curFlags & SDL_WINDOW_BORDERLESS)
157 {
158
159 SDL_SetWindowBordered(_window, SDL_TRUE);
160#if SDL_VERSION_ATLEAST(2, 0, 16)
161 SDL_SetWindowAlwaysOnTop(_window, SDL_FALSE);
162#endif
163 SDL_RaiseWindow(_window);
164 SDL_MinimizeWindow(_window); // Maximize so we can see the caption and bits
165 SDL_MaximizeWindow(_window); // Maximize so we can see the caption and bits
166 }
167 }
168}

◆ fullscreen() [2/2]

void SdlWindow::fullscreen ( bool  enter,
bool  forceOriginalDisplay 
)

Definition at line 226 of file SDL3/sdl_window.cpp.

227{
228 if (enter && forceOriginalDisplay && _displayID != 0)
229 {
230 /* Move the window to the desired display. We should not wait
231 * for the window to be moved, because some backends can refuse
232 * the move. The intent of moving the window is enough for SDL
233 * to decide which display will be used for fullscreen. */
234 SDL_Rect rect = {};
235 std::ignore = SDL_GetDisplayBounds(_displayID, &rect);
236 std::ignore = SDL_SetWindowPosition(_window, rect.x, rect.y);
237 }
238 std::ignore = SDL_SetWindowFullscreen(_window, enter);
239 std::ignore = SDL_SyncWindow(_window);
240}

◆ grabKeyboard()

bool SdlWindow::grabKeyboard ( bool  enable)

Definition at line 90 of file SDL2/sdl_window.cpp.

91{
92 if (!_window)
93 return false;
94#if SDL_VERSION_ATLEAST(2, 0, 16)
95 SDL_SetWindowKeyboardGrab(_window, enable ? SDL_TRUE : SDL_FALSE);
96 return true;
97#else
98 SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Keyboard grabbing not supported by SDL2 < 2.0.16");
99 return false;
100#endif
101}

◆ grabMouse()

bool SdlWindow::grabMouse ( bool  enable)

Definition at line 103 of file SDL2/sdl_window.cpp.

104{
105 if (!_window)
106 return false;
107#if SDL_VERSION_ATLEAST(2, 0, 16)
108 SDL_SetWindowMouseGrab(_window, enable ? SDL_TRUE : SDL_FALSE);
109#else
110 SDL_SetWindowGrab(_window, enable ? SDL_TRUE : SDL_FALSE);
111#endif
112 return true;
113}

◆ id()

SDL_WindowID SdlWindow::id ( ) const

Definition at line 40 of file SDL2/sdl_window.cpp.

41{
42 if (!_window)
43 return 0;
44 return SDL_GetWindowID(_window);
45}

◆ isHighDPIWindowsMode()

SdlWindow::HighDPIMode SdlWindow::isHighDPIWindowsMode ( SDL_Window *  window)
staticprotected

Definition at line 534 of file SDL3/sdl_window.cpp.

535{
536 if (!window)
537 return MODE_INVALID;
538
539 const auto id = SDL_GetDisplayForWindow(window);
540 if (id == 0)
541 return MODE_INVALID;
542
543 const auto cs = SDL_GetDisplayContentScale(id);
544 const auto ds = SDL_GetWindowDisplayScale(window);
545 const auto pd = SDL_GetWindowPixelDensity(window);
546
547 /* mac os x style, but no HighDPI display */
548 if ((cs == 1.0f) && (ds == 1.0f) && (pd == 1.0f))
549 return MODE_NONE;
550
551 /* mac os x style HighDPI */
552 if ((cs == 1.0f) && (ds > 1.0f) && (pd > 1.0f))
553 return MODE_MACOS;
554
555 /* rest is windows style */
556 return MODE_WINDOWS;
557}

◆ minimize()

void SdlWindow::minimize ( )

Definition at line 170 of file SDL2/sdl_window.cpp.

171{
172 SDL_MinimizeWindow(_window);
173}

◆ monitor()

rdpMonitor SdlWindow::monitor ( bool  isPrimary) const

Definition at line 162 of file SDL3/sdl_window.cpp.

163{
164 auto m = _monitor;
165 if (isPrimary)
166 {
167 m.x = 0;
168 m.y = 0;
169 }
170 return m;
171}

◆ offsetX()

Sint32 SdlWindow::offsetX ( ) const

Definition at line 70 of file SDL2/sdl_window.cpp.

71{
72 return _offset_x;
73}

◆ offsetY()

Sint32 SdlWindow::offsetY ( ) const

Definition at line 85 of file SDL2/sdl_window.cpp.

86{
87 return _offset_y;
88}

◆ orientation()

SDL_DisplayOrientation SdlWindow::orientation ( ) const

Definition at line 183 of file SDL3/sdl_window.cpp.

184{
185 const auto did = displayIndex();
186 return SDL_GetCurrentDisplayOrientation(did);
187}

◆ paintResizeFrame()

bool SdlWindow::paintResizeFrame ( SDL_Surface *  surface,
SDL_Point  off,
bool  contentChanged,
const SDL_Rect &  inset = { 0, 0, 0, 0 },
bool  fillRevealed = true,
bool  dashedBorder = true 
)

Definition at line 632 of file SDL3/sdl_window.cpp.

634{
635 if (!_renderer || !surface)
636 return false;
637 ensureRenderTarget();
638
639 const int prevW = _gdiTextureW;
640 const int prevH = _gdiTextureH;
641 if (!ensureGdiTexture(surface))
642 return false;
643 /* A recreated texture is empty, so upload even when the content did not change. */
644 const bool recreated = (_gdiTextureW != prevW) || (_gdiTextureH != prevH);
645 if ((contentChanged || recreated) &&
646 !SDL_UpdateTexture(_gdiTexture, nullptr, surface->pixels, surface->pitch))
647 return false;
648
649 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
650 return false;
651
652 int ww = 0;
653 int wh = 0;
654 SDL_GetWindowSizeInPixels(_window, &ww, &wh);
655 /* The visible frame; the ring outside it (the resize band) stays fully transparent. */
656 const SDL_FRect frame = { static_cast<float>(inset.x), static_cast<float>(inset.y),
657 static_cast<float>(ww - inset.x - inset.w),
658 static_cast<float>(wh - inset.y - inset.h) };
659
660 /* Translucent fill in revealed area awaiting server frame. */
661 constexpr Uint8 kFillAlpha = 0x80;
662 std::ignore = SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);
663 std::ignore = SDL_SetRenderDrawColor(_renderer, 0, 0, 0, 0);
664 std::ignore = SDL_RenderClear(_renderer);
665 if (fillRevealed)
666 {
667 std::ignore = SDL_SetRenderDrawColor(_renderer, 0x2B, 0x2B, 0x2B, kFillAlpha);
668 std::ignore = SDL_RenderFillRect(_renderer, &frame);
669 }
670 SDL_FRect fdst = { static_cast<float>(off.x), static_cast<float>(off.y),
671 static_cast<float>(surface->w), static_cast<float>(surface->h) };
672 /* Anchored frame clipped to visible bounds. */
673 const SDL_Rect clip = { inset.x, inset.y, ww - inset.x - inset.w, wh - inset.y - inset.h };
674 std::ignore = SDL_SetRenderClipRect(_renderer, &clip);
675 std::ignore = SDL_RenderTexture(_renderer, _gdiTexture, nullptr, &fdst);
676 std::ignore = SDL_SetRenderClipRect(_renderer, nullptr);
677
678 /* Dashed border indicating pending resize target. */
679 if (dashedBorder)
680 {
681 std::ignore = SDL_SetRenderDrawColor(_renderer, 0xC8, 0xC8, 0xC8, 0xFF);
682 const float dash = 8.0F;
683 const float gap = 5.0F;
684 const float fx2 = frame.x + frame.w;
685 const float fy2 = frame.y + frame.h;
686 const float lo = frame.y + 0.5F;
687 const float by = fy2 - 0.5F;
688 const float lx = frame.x + 0.5F;
689 const float rx = fx2 - 0.5F;
690 const float step = dash + gap;
691 const auto steps = [step](float len)
692 { return (len <= 0.0F) ? 0 : static_cast<int>(std::ceil(len / step)); };
693 for (int i = 0; i < steps(fx2 - frame.x); i++)
694 {
695 const float x = frame.x + (static_cast<float>(i) * step);
696 const float x2 = (x + dash < fx2) ? (x + dash) : rx;
697 std::ignore = SDL_RenderLine(_renderer, x, lo, x2, lo);
698 std::ignore = SDL_RenderLine(_renderer, x, by, x2, by);
699 }
700 for (int i = 0; i < steps(fy2 - frame.y); i++)
701 {
702 const float y = frame.y + (static_cast<float>(i) * step);
703 const float y2 = (y + dash < fy2) ? (y + dash) : by;
704 std::ignore = SDL_RenderLine(_renderer, lx, y, lx, y2);
705 std::ignore = SDL_RenderLine(_renderer, rx, y, rx, y2);
706 }
707 }
708
709 if (!SDL_SetRenderTarget(_renderer, nullptr))
710 return false;
711 std::ignore = SDL_RenderTexture(_renderer, _renderTarget, nullptr, nullptr);
712 std::ignore = SDL_RenderPresent(_renderer);
713 return true;
714}

◆ query() [1/2]

rdpMonitor SdlWindow::query ( SDL_DisplayID  id,
bool  forceAsPrimary = false 
)
static

Definition at line 826 of file SDL3/sdl_window.cpp.

827{
828 if (sdl::utils::isWaylandDriver() || sdl::utils::isX11Driver())
829 return queryDisplay(id, forceAsPrimary);
830
831 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(id), SDL_DestroyWindow);
832 if (!window)
833 return {};
834
835 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
836 SDL_CreateRenderer(window.get(), nullptr), SDL_DestroyRenderer);
837
838 if (!SDL_SyncWindow(window.get()))
839 return {};
840
841 SDL_Event event{};
842 while (SDL_PollEvent(&event))
843 ;
844
845 return query(window.get(), id, forceAsPrimary);
846}

◆ query() [2/2]

rdpMonitor SdlWindow::query ( SDL_Window *  window,
SDL_DisplayID  id,
bool  forceAsPrimary = false 
)
staticprotected

Definition at line 447 of file SDL3/sdl_window.cpp.

448{
449 if (!window)
450 return {};
451 return makeMonitor(id, rect(window, forceAsPrimary), SDL_GetWindowDisplayScale(window),
452 forceAsPrimary);
453}

◆ raise()

void SdlWindow::raise ( )

Definition at line 121 of file SDL2/sdl_window.cpp.

122{
123 SDL_RaiseWindow(_window);
124}

◆ rect() [1/3]

SDL_Rect SdlWindow::rect ( ) const

Definition at line 54 of file SDL2/sdl_window.cpp.

55{
56 SDL_Rect rect = {};
57 if (_window)
58 {
59 SDL_GetWindowPosition(_window, &rect.x, &rect.y);
60 SDL_GetWindowSize(_window, &rect.w, &rect.h);
61 }
62 return rect;
63}

◆ rect() [2/3]

SDL_Rect SdlWindow::rect ( SDL_DisplayID  id,
bool  forceAsPrimary = false 
)
staticprotected

Definition at line 848 of file SDL3/sdl_window.cpp.

849{
850 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(id), SDL_DestroyWindow);
851 if (!window)
852 return {};
853
854 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
855 SDL_CreateRenderer(window.get(), nullptr), SDL_DestroyRenderer);
856
857 if (!SDL_SyncWindow(window.get()))
858 return {};
859
860 SDL_Event event{};
861 while (SDL_PollEvent(&event))
862 ;
863
864 return rect(window.get(), forceAsPrimary);
865}

◆ rect() [3/3]

SDL_Rect SdlWindow::rect ( SDL_Window *  window,
bool  forceAsPrimary = false 
)
staticprotected

Definition at line 475 of file SDL3/sdl_window.cpp.

476{
477 SDL_Rect rect = {};
478 if (!window)
479 return {};
480
481 if (!forceAsPrimary)
482 {
483 if (!SDL_GetWindowPosition(window, &rect.x, &rect.y))
484 return {};
485 }
486
487 if (!SDL_GetWindowSizeInPixels(window, &rect.w, &rect.h))
488 return {};
489
490 const auto flags = SDL_GetWindowFlags(window);
491 const auto mask = SDL_WINDOW_FULLSCREEN;
492 const auto fs = (flags & mask) == mask;
493 if (tryFallback(fs))
494 {
495 /* On wlroots compositors (Sway, river, etc.), windows that are hidden/unmapped
496 * don't get their actual display dimensions. The dummy window returns its creation size
497 * (64x64) instead of the display size. This causes validation errors since we require >=
498 * 200px. Workaround: If we got dimensions that are too small, query the display directly.
499 */
500
501 const auto displayID = SDL_GetDisplayForWindow(window);
502 SDL_Rect displayBounds = {};
503 if (SDL_GetDisplayBounds(displayID, &displayBounds))
504 {
505 if (forceAsPrimary)
506 {
507 rect.x = 0;
508 rect.y = 0;
509 }
510 else
511 {
512 /* The dummy window is centered on the display by the compositor, so its
513 * position is not the display origin. Use the display bounds as for w/h. */
514 rect.x = displayBounds.x;
515 rect.y = displayBounds.y;
516 }
517 rect.w = displayBounds.w;
518 rect.h = displayBounds.h;
519
520 const float contentScale = SDL_GetDisplayContentScale(displayID);
521 if (contentScale > 1.0f)
522 {
523 const auto fw = static_cast<float>(rect.w);
524 const auto fh = static_cast<float>(rect.h);
525 rect.w = static_cast<int>(std::roundf(fw * contentScale));
526 rect.h = static_cast<int>(std::roundf(fh * contentScale));
527 }
528 }
529 }
530
531 return rect;
532}

◆ renderer()

SDL_Renderer * SdlWindow::renderer ( ) const

Definition at line 137 of file SDL3/sdl_window.cpp.

138{
139 return _renderer;
140}

◆ resize()

bool SdlWindow::resize ( const SDL_Point &  size)

Definition at line 273 of file SDL3/sdl_window.cpp.

274{
275 return SDL_SetWindowSize(_window, size.x, size.y);
276}

◆ resizeable()

void SdlWindow::resizeable ( bool  use)

Definition at line 126 of file SDL2/sdl_window.cpp.

127{
128 SDL_SetWindowResizable(_window, use ? SDL_TRUE : SDL_FALSE);
129}

◆ resizeToScale()

bool SdlWindow::resizeToScale ( )

Definition at line 248 of file SDL3/sdl_window.cpp.

249{
250 if (!_window || _initialW <= 0 || _initialH <= 0)
251 return false;
252 if ((SDL_GetWindowFlags(_window) & SDL_WINDOW_FULLSCREEN) != 0)
253 return true;
254
255 float pd = SDL_GetWindowPixelDensity(_window);
256 if (pd <= 0.0f)
257 pd = 1.0f;
258
259 const int targetW = static_cast<int>(std::ceil(static_cast<float>(_initialW) / pd));
260 const int targetH = static_cast<int>(std::ceil(static_cast<float>(_initialH) / pd));
261
262 int curW = 0;
263 int curH = 0;
264 if (!SDL_GetWindowSize(_window, &curW, &curH))
265 return false;
266
267 if (curW == targetW && curH == targetH)
268 return true;
269
270 return resize({ targetW, targetH });
271}

◆ scale()

float SdlWindow::scale ( ) const

Definition at line 178 of file SDL3/sdl_window.cpp.

179{
180 return SDL_GetWindowDisplayScale(_window);
181}

◆ setBordered()

void SdlWindow::setBordered ( bool  bordered)

Definition at line 115 of file SDL2/sdl_window.cpp.

116{
117 if (_window)
118 SDL_SetWindowBordered(_window, bordered ? SDL_TRUE : SDL_FALSE);
119}

◆ setMonitor()

void SdlWindow::setMonitor ( rdpMonitor  monitor)

Definition at line 173 of file SDL3/sdl_window.cpp.

174{
175 _monitor = monitor;
176}

◆ setOffsetX()

void SdlWindow::setOffsetX ( Sint32  x)

Definition at line 75 of file SDL2/sdl_window.cpp.

76{
77 _offset_x = x;
78}

◆ setOffsetY()

void SdlWindow::setOffsetY ( Sint32  y)

Definition at line 80 of file SDL2/sdl_window.cpp.

81{
82 _offset_y = y;
83}

◆ tryFallback()

bool SdlWindow::tryFallback ( bool  isFullscreen)
staticprotected

Definition at line 867 of file SDL3/sdl_window.cpp.

868{
869 /* If we define a custom env variable to use the wlroots hack
870 * then enable/disable according to this setting only.
871 */
872 const auto wlroots_hack = SDL_getenv("FREERDP_WLROOTS_HACK");
873 if (wlroots_hack != nullptr)
874 {
875 const auto enabled = strcmp(wlroots_hack, "0") != 0;
876 if (strcmp(wlroots_hack, "force") == 0)
877 isFullscreen = true;
878 return enabled && isFullscreen;
879 }
880
881 const auto platform = SDL_GetPlatform();
882 if ((platform == nullptr) || (strcmp(platform, "Linux") != 0))
883 return false;
884
885 const auto driver = SDL_GetCurrentVideoDriver();
886 if ((driver == nullptr) || (strcmp(driver, "wayland") != 0))
887 return false;
888
889 /* Check XDG_SESSION_DESKTOP and XDG_CURRENT_DESKTOP for wlroots-based
890 * compositors. The original check only matched Sway, but other wlroots
891 * compositors (Hyprland, river, etc.) have the same dummy-window sizing
892 * behavior where hidden/unmapped windows return 64x64 instead of the
893 * display size. Use strstr for substring matching since XDG_CURRENT_DESKTOP
894 * can be a colon-separated list (e.g. "sway:wlroots", "Hyprland").
895 */
896 auto isWlrootsCompositor = [](const char* value) -> bool
897 {
898 if (!value)
899 return false;
900 if (strstr(value, "sway") || strstr(value, "Sway") || strstr(value, "Hyprland") ||
901 strstr(value, "hyprland") || strstr(value, "river") || strstr(value, "wlroots"))
902 return true;
903 return false;
904 };
905
906 const auto xdg_session = SDL_getenv("XDG_SESSION_DESKTOP");
907 if (isWlrootsCompositor(xdg_session))
908 return isFullscreen;
909
910 const auto xdg_desktop = SDL_getenv("XDG_CURRENT_DESKTOP");
911 if (isWlrootsCompositor(xdg_desktop))
912 return isFullscreen;
913
914 return false;
915}

◆ updateSurface()

void SdlWindow::updateSurface ( )

Definition at line 204 of file SDL2/sdl_window.cpp.

205{
206 SDL_UpdateWindowSurface(_window);
207}

◆ window()

SDL_Window * SdlWindow::window ( ) const

Definition at line 65 of file SDL2/sdl_window.cpp.

66{
67 return _window;
68}

The documentation for this class was generated from the following files: