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 719 of file SDL3/sdl_window.cpp.

720 : _initialW(rect.w), _initialH(rect.h)
721{
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,
727 true);
728 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, false);
729 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN, true);
730 /* Transparent so menus' genuine per-pixel alpha (corners/shadow) isn't rendered black. */
731 if (transparent)
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);
737 /* Hidden until first paint, like the app constructor. */
738 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, true);
739
740 _window = SDL_CreateWindowWithProperties(props);
741 SDL_DestroyProperties(props);
742 if (_window)
743 {
744 std::ignore = SDL_SyncWindow(_window);
745 _renderer = SDL_CreateRenderer(_window, nullptr);
746 _displayID = SDL_GetDisplayForWindow(_window);
747 }
748}

Member Function Documentation

◆ blit() [1/2]

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

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

551{
552 if (!_renderer || !surface)
553 return false;
554
555 ensureRenderTarget();
556
557 if (!ensureGdiTexture(surface))
558 return false;
559
560 /* Upload only the dirty region */
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))
566 {
567 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_UpdateTexture: %s", SDL_GetError());
568 return false;
569 }
570
571 /* Render onto persistent render target to accumulate dirty rects */
572 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
573 return false;
574
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))
580 {
581 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_RenderTexture: %s", SDL_GetError());
582 return false;
583 }
584 return true;
585}

◆ 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 712 of file SDL3/sdl_window.cpp.

714{
715 return SdlWindow{ id, title, rect, flags };
716}

◆ 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 687 of file SDL3/sdl_window.cpp.

689{
690 flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
691
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) };
695
696 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
697 {
698 std::ignore = SDL_GetDisplayBounds(id, &rect);
699 }
700
701 SdlWindow window{ id, title, rect, flags };
702
703 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
704 {
705 window.setOffsetX(rect.x);
706 window.setOffsetY(rect.y);
707 }
708
709 return window;
710}

◆ createPopup()

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

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

752{
753 return SdlWindow{ parent, rect, transparent, tooltip };
754}

◆ 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 318 of file SDL3/sdl_window.cpp.

319{
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);
323}

◆ drawRects()

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

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

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

◆ drawScaledRect()

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

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

342{
343 SDL_Rect dstRect = {};
344 float ix = 0.0f;
345 float iy = 0.0f;
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);
355}

◆ drawScaledRects()

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

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

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

◆ 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 386 of file SDL3/sdl_window.cpp.

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

◆ 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 224 of file SDL3/sdl_window.cpp.

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

◆ 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 505 of file SDL3/sdl_window.cpp.

506{
507 if (!window)
508 return MODE_INVALID;
509
510 const auto id = SDL_GetDisplayForWindow(window);
511 if (id == 0)
512 return MODE_INVALID;
513
514 const auto cs = SDL_GetDisplayContentScale(id);
515 const auto ds = SDL_GetWindowDisplayScale(window);
516 const auto pd = SDL_GetWindowPixelDensity(window);
517
518 /* mac os x style, but no HighDPI display */
519 if ((cs == 1.0f) && (ds == 1.0f) && (pd == 1.0f))
520 return MODE_NONE;
521
522 /* mac os x style HighDPI */
523 if ((cs == 1.0f) && (ds > 1.0f) && (pd > 1.0f))
524 return MODE_MACOS;
525
526 /* rest is windows style */
527 return MODE_WINDOWS;
528}

◆ 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 603 of file SDL3/sdl_window.cpp.

605{
606 if (!_renderer || !surface)
607 return false;
608 ensureRenderTarget();
609
610 const int prevW = _gdiTextureW;
611 const int prevH = _gdiTextureH;
612 if (!ensureGdiTexture(surface))
613 return false;
614 /* A recreated texture is empty, so upload even when the content did not change. */
615 const bool recreated = (_gdiTextureW != prevW) || (_gdiTextureH != prevH);
616 if ((contentChanged || recreated) &&
617 !SDL_UpdateTexture(_gdiTexture, nullptr, surface->pixels, surface->pitch))
618 return false;
619
620 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
621 return false;
622
623 int ww = 0;
624 int wh = 0;
625 SDL_GetWindowSizeInPixels(_window, &ww, &wh);
626 /* The visible frame; the ring outside it (the resize band) stays fully transparent. */
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) };
630
631 /* Translucent fill in revealed area awaiting server frame. */
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);
636 if (fillRevealed)
637 {
638 std::ignore = SDL_SetRenderDrawColor(_renderer, 0x2B, 0x2B, 0x2B, kFillAlpha);
639 std::ignore = SDL_RenderFillRect(_renderer, &frame);
640 }
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) };
643 /* Anchored frame clipped to visible bounds. */
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);
648
649 /* Dashed border indicating pending resize target. */
650 if (dashedBorder)
651 {
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++)
665 {
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);
670 }
671 for (int i = 0; i < steps(fy2 - frame.y); i++)
672 {
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);
677 }
678 }
679
680 if (!SDL_SetRenderTarget(_renderer, nullptr))
681 return false;
682 std::ignore = SDL_RenderTexture(_renderer, _renderTarget, nullptr, nullptr);
683 std::ignore = SDL_RenderPresent(_renderer);
684 return true;
685}

◆ query() [1/2]

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

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

794{
795 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(id), SDL_DestroyWindow);
796 if (!window)
797 return {};
798
799 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
800 SDL_CreateRenderer(window.get(), nullptr), SDL_DestroyRenderer);
801
802 if (!SDL_SyncWindow(window.get()))
803 return {};
804
805 SDL_Event event{};
806 while (SDL_PollEvent(&event))
807 ;
808
809 return query(window.get(), id, forceAsPrimary);
810}

◆ query() [2/2]

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

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

398{
399 if (!window)
400 return {};
401
402 const auto& r = rect(window, forceAsPrimary);
403 const float factor = SDL_GetWindowDisplayScale(window);
404 const float dpi = std::roundf(factor * 100.0f);
405
406 WINPR_ASSERT(r.w > 0);
407 WINPR_ASSERT(r.h > 0);
408
409 const auto primary = SDL_GetPrimaryDisplay();
410 const auto orientation = SDL_GetCurrentDisplayOrientation(id);
411 const auto rdp_orientation = sdl::utils::orientaion_to_rdp(orientation);
412
413 rdpMonitor monitor{};
414 monitor.orig_screen = id;
415 monitor.x = r.x;
416 monitor.y = r.y;
417 monitor.width = r.w;
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);
425
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);
443 return monitor;
444}

◆ 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 812 of file SDL3/sdl_window.cpp.

813{
814 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(id), SDL_DestroyWindow);
815 if (!window)
816 return {};
817
818 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
819 SDL_CreateRenderer(window.get(), nullptr), SDL_DestroyRenderer);
820
821 if (!SDL_SyncWindow(window.get()))
822 return {};
823
824 SDL_Event event{};
825 while (SDL_PollEvent(&event))
826 ;
827
828 return rect(window.get(), forceAsPrimary);
829}

◆ rect() [3/3]

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

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

447{
448 SDL_Rect rect = {};
449 if (!window)
450 return {};
451
452 if (!forceAsPrimary)
453 {
454 if (!SDL_GetWindowPosition(window, &rect.x, &rect.y))
455 return {};
456 }
457
458 if (!SDL_GetWindowSizeInPixels(window, &rect.w, &rect.h))
459 return {};
460
461 const auto flags = SDL_GetWindowFlags(window);
462 const auto mask = SDL_WINDOW_FULLSCREEN;
463 const auto fs = (flags & mask) == mask;
464 if (tryFallback(fs))
465 {
466 /* On wlroots compositors (Sway, river, etc.), windows that are hidden/unmapped
467 * don't get their actual display dimensions. The dummy window returns its creation size
468 * (64x64) instead of the display size. This causes validation errors since we require >=
469 * 200px. Workaround: If we got dimensions that are too small, query the display directly.
470 */
471
472 const auto displayID = SDL_GetDisplayForWindow(window);
473 SDL_Rect displayBounds = {};
474 if (SDL_GetDisplayBounds(displayID, &displayBounds))
475 {
476 if (forceAsPrimary)
477 {
478 rect.x = 0;
479 rect.y = 0;
480 }
481 else
482 {
483 /* The dummy window is centered on the display by the compositor, so its
484 * position is not the display origin. Use the display bounds as for w/h. */
485 rect.x = displayBounds.x;
486 rect.y = displayBounds.y;
487 }
488 rect.w = displayBounds.w;
489 rect.h = displayBounds.h;
490
491 const float contentScale = SDL_GetDisplayContentScale(displayID);
492 if (contentScale > 1.0f)
493 {
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));
498 }
499 }
500 }
501
502 return rect;
503}

◆ 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 271 of file SDL3/sdl_window.cpp.

272{
273 return SDL_SetWindowSize(_window, size.x, size.y);
274}

◆ 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 246 of file SDL3/sdl_window.cpp.

247{
248 if (!_window || _initialW <= 0 || _initialH <= 0)
249 return false;
250 if ((SDL_GetWindowFlags(_window) & SDL_WINDOW_FULLSCREEN) != 0)
251 return true;
252
253 float pd = SDL_GetWindowPixelDensity(_window);
254 if (pd <= 0.0f)
255 pd = 1.0f;
256
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));
259
260 int curW = 0;
261 int curH = 0;
262 if (!SDL_GetWindowSize(_window, &curW, &curH))
263 return false;
264
265 if (curW == targetW && curH == targetH)
266 return true;
267
268 return resize({ targetW, targetH });
269}

◆ 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 831 of file SDL3/sdl_window.cpp.

832{
833 /* If we define a custom env variable to use the wlroots hack
834 * then enable/disable according to this setting only.
835 */
836 const auto wlroots_hack = SDL_getenv("FREERDP_WLROOTS_HACK");
837 if (wlroots_hack != nullptr)
838 {
839 const auto enabled = strcmp(wlroots_hack, "0") != 0;
840 if (strcmp(wlroots_hack, "force") == 0)
841 isFullscreen = true;
842 return enabled && isFullscreen;
843 }
844
845 const auto platform = SDL_GetPlatform();
846 if ((platform == nullptr) || (strcmp(platform, "Linux") != 0))
847 return false;
848
849 const auto driver = SDL_GetCurrentVideoDriver();
850 if ((driver == nullptr) || (strcmp(driver, "wayland") != 0))
851 return false;
852
853 /* Check XDG_SESSION_DESKTOP and XDG_CURRENT_DESKTOP for wlroots-based
854 * compositors. The original check only matched Sway, but other wlroots
855 * compositors (Hyprland, river, etc.) have the same dummy-window sizing
856 * behavior where hidden/unmapped windows return 64x64 instead of the
857 * display size. Use strstr for substring matching since XDG_CURRENT_DESKTOP
858 * can be a colon-separated list (e.g. "sway:wlroots", "Hyprland").
859 */
860 auto isWlrootsCompositor = [](const char* value) -> bool
861 {
862 if (!value)
863 return false;
864 if (strstr(value, "sway") || strstr(value, "Sway") || strstr(value, "Hyprland") ||
865 strstr(value, "hyprland") || strstr(value, "river") || strstr(value, "wlroots"))
866 return true;
867 return false;
868 };
869
870 const auto xdg_session = SDL_getenv("XDG_SESSION_DESKTOP");
871 if (isWlrootsCompositor(xdg_session))
872 return isFullscreen;
873
874 const auto xdg_desktop = SDL_getenv("XDG_CURRENT_DESKTOP");
875 if (isWlrootsCompositor(xdg_desktop))
876 return isFullscreen;
877
878 return false;
879}

◆ 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: