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
 
SdlWindowoperator= (const SdlWindow &other)=delete
 
SdlWindowoperator= (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
 
SdlWindowoperator= (const SdlWindow &other)=delete
 
SdlWindowoperator= (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 712 of file SDL3/sdl_window.cpp.

713 : _initialW(rect.w), _initialH(rect.h)
714{
715 auto props = SDL_CreateProperties();
716 SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, parent);
717 SDL_SetBooleanProperty(props,
718 tooltip ? SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN
719 : SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN,
720 true);
721 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, false);
722 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN, true);
723 /* Transparent so menus' genuine per-pixel alpha (corners/shadow) isn't rendered black. */
724 if (transparent)
725 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN, true);
726 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, rect.x);
727 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, rect.y);
728 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, rect.w);
729 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, rect.h);
730 /* Hidden until first paint, like the app constructor. */
731 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, true);
732
733 _window = SDL_CreateWindowWithProperties(props);
734 SDL_DestroyProperties(props);
735 if (_window)
736 {
737 std::ignore = SDL_SyncWindow(_window);
738 _renderer = SDL_CreateRenderer(_window, nullptr);
739 _displayID = SDL_GetDisplayForWindow(_window);
740 }
741}

Member Function Documentation

◆ blit() [1/2]

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

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

544{
545 if (!_renderer || !surface)
546 return false;
547
548 ensureRenderTarget();
549
550 if (!ensureGdiTexture(surface))
551 return false;
552
553 /* Upload only the dirty region */
554 const auto* details = SDL_GetPixelFormatDetails(surface->format);
555 const int bpp = details ? details->bytes_per_pixel : 4;
556 const auto* pixels = static_cast<const uint8_t*>(surface->pixels) +
557 (1ll * srcRect.y * surface->pitch) + (1ll * srcRect.x * bpp);
558 if (!SDL_UpdateTexture(_gdiTexture, &srcRect, pixels, surface->pitch))
559 {
560 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_UpdateTexture: %s", SDL_GetError());
561 return false;
562 }
563
564 /* Render onto persistent render target to accumulate dirty rects */
565 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
566 return false;
567
568 SDL_FRect fsrc = { static_cast<float>(srcRect.x), static_cast<float>(srcRect.y),
569 static_cast<float>(srcRect.w), static_cast<float>(srcRect.h) };
570 SDL_FRect fdst = { static_cast<float>(dstRect.x), static_cast<float>(dstRect.y),
571 static_cast<float>(dstRect.w), static_cast<float>(dstRect.h) };
572 if (!SDL_RenderTexture(_renderer, _gdiTexture, &fsrc, &fdst))
573 {
574 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_RenderTexture: %s", SDL_GetError());
575 return false;
576 }
577 return true;
578}

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

707{
708 return SdlWindow{ id, title, rect, flags };
709}

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

682{
683 flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
684
685 SDL_Rect rect = { static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)),
686 static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)), static_cast<int>(width),
687 static_cast<int>(height) };
688
689 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
690 {
691 std::ignore = SDL_GetDisplayBounds(id, &rect);
692 }
693
694 SdlWindow window{ id, title, rect, flags };
695
696 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
697 {
698 window.setOffsetX(rect.x);
699 window.setOffsetY(rect.y);
700 }
701
702 return window;
703}

◆ createPopup()

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

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

745{
746 return SdlWindow{ parent, rect, transparent, tooltip };
747}

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

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

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

598{
599 if (!_renderer || !surface)
600 return false;
601 ensureRenderTarget();
602
603 const int prevW = _gdiTextureW;
604 const int prevH = _gdiTextureH;
605 if (!ensureGdiTexture(surface))
606 return false;
607 /* A recreated texture is empty, so upload even when the content did not change. */
608 const bool recreated = (_gdiTextureW != prevW) || (_gdiTextureH != prevH);
609 if ((contentChanged || recreated) &&
610 !SDL_UpdateTexture(_gdiTexture, nullptr, surface->pixels, surface->pitch))
611 return false;
612
613 if (!SDL_SetRenderTarget(_renderer, _renderTarget))
614 return false;
615
616 int ww = 0;
617 int wh = 0;
618 SDL_GetWindowSizeInPixels(_window, &ww, &wh);
619 /* The visible frame; the ring outside it (the resize band) stays fully transparent. */
620 const SDL_FRect frame = { static_cast<float>(inset.x), static_cast<float>(inset.y),
621 static_cast<float>(ww - inset.x - inset.w),
622 static_cast<float>(wh - inset.y - inset.h) };
623
624 /* Translucent fill in revealed area awaiting server frame. */
625 constexpr Uint8 kFillAlpha = 0x80;
626 std::ignore = SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);
627 std::ignore = SDL_SetRenderDrawColor(_renderer, 0, 0, 0, 0);
628 std::ignore = SDL_RenderClear(_renderer);
629 if (fillRevealed)
630 {
631 std::ignore = SDL_SetRenderDrawColor(_renderer, 0x2B, 0x2B, 0x2B, kFillAlpha);
632 std::ignore = SDL_RenderFillRect(_renderer, &frame);
633 }
634 SDL_FRect fdst = { static_cast<float>(off.x), static_cast<float>(off.y),
635 static_cast<float>(surface->w), static_cast<float>(surface->h) };
636 /* Anchored frame clipped to visible bounds. */
637 const SDL_Rect clip = { inset.x, inset.y, ww - inset.x - inset.w, wh - inset.y - inset.h };
638 std::ignore = SDL_SetRenderClipRect(_renderer, &clip);
639 std::ignore = SDL_RenderTexture(_renderer, _gdiTexture, nullptr, &fdst);
640 std::ignore = SDL_SetRenderClipRect(_renderer, nullptr);
641
642 /* Dashed border indicating pending resize target. */
643 if (dashedBorder)
644 {
645 std::ignore = SDL_SetRenderDrawColor(_renderer, 0xC8, 0xC8, 0xC8, 0xFF);
646 const float dash = 8.0F;
647 const float gap = 5.0F;
648 const float fx2 = frame.x + frame.w;
649 const float fy2 = frame.y + frame.h;
650 const float lo = frame.y + 0.5F;
651 const float by = fy2 - 0.5F;
652 const float lx = frame.x + 0.5F;
653 const float rx = fx2 - 0.5F;
654 const float step = dash + gap;
655 const auto steps = [step](float len)
656 { return (len <= 0.0F) ? 0 : static_cast<int>(std::ceil(len / step)); };
657 for (int i = 0; i < steps(fx2 - frame.x); i++)
658 {
659 const float x = frame.x + (static_cast<float>(i) * step);
660 const float x2 = (x + dash < fx2) ? (x + dash) : rx;
661 std::ignore = SDL_RenderLine(_renderer, x, lo, x2, lo);
662 std::ignore = SDL_RenderLine(_renderer, x, by, x2, by);
663 }
664 for (int i = 0; i < steps(fy2 - frame.y); i++)
665 {
666 const float y = frame.y + (static_cast<float>(i) * step);
667 const float y2 = (y + dash < fy2) ? (y + dash) : by;
668 std::ignore = SDL_RenderLine(_renderer, lx, y, lx, y2);
669 std::ignore = SDL_RenderLine(_renderer, rx, y, rx, y2);
670 }
671 }
672
673 if (!SDL_SetRenderTarget(_renderer, nullptr))
674 return false;
675 std::ignore = SDL_RenderTexture(_renderer, _renderTarget, nullptr, nullptr);
676 std::ignore = SDL_RenderPresent(_renderer);
677 return true;
678}

◆ query() [1/2]

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

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

787{
788 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(id), SDL_DestroyWindow);
789 if (!window)
790 return {};
791
792 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
793 SDL_CreateRenderer(window.get(), nullptr), SDL_DestroyRenderer);
794
795 if (!SDL_SyncWindow(window.get()))
796 return {};
797
798 SDL_Event event{};
799 while (SDL_PollEvent(&event))
800 ;
801
802 return query(window.get(), id, forceAsPrimary);
803}

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

806{
807 std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window(createDummy(id), SDL_DestroyWindow);
808 if (!window)
809 return {};
810
811 std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer(
812 SDL_CreateRenderer(window.get(), nullptr), SDL_DestroyRenderer);
813
814 if (!SDL_SyncWindow(window.get()))
815 return {};
816
817 SDL_Event event{};
818 while (SDL_PollEvent(&event))
819 ;
820
821 return rect(window.get(), forceAsPrimary);
822}

◆ 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 rect.w = displayBounds.w;
482 rect.h = displayBounds.h;
483
484 const float contentScale = SDL_GetDisplayContentScale(displayID);
485 if (contentScale > 1.0f)
486 {
487 const auto fw = static_cast<float>(rect.w);
488 const auto fh = static_cast<float>(rect.h);
489 rect.w = static_cast<int>(std::roundf(fw * contentScale));
490 rect.h = static_cast<int>(std::roundf(fh * contentScale));
491 }
492 }
493 }
494
495 return rect;
496}

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

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

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