FreeRDP
Loading...
Searching...
No Matches
SDL3/sdl_window.cpp
1
20#include <limits>
21#include <sstream>
22
23#include "sdl_window.hpp"
24#include "sdl_utils.hpp"
25
26SdlWindow::SdlWindow(const std::string& title, const SDL_Rect& rect, [[maybe_unused]] Uint32 flags)
27{
28 auto props = SDL_CreateProperties();
29 SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title.c_str());
30 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, rect.x);
31 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, rect.y);
32 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, rect.w);
33 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, rect.h);
34
35 if (flags & SDL_WINDOW_HIGH_PIXEL_DENSITY)
36 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, true);
37
38 if (flags & SDL_WINDOW_FULLSCREEN)
39 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, true);
40
41 if (flags & SDL_WINDOW_BORDERLESS)
42 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN, true);
43
44 _window = SDL_CreateWindowWithProperties(props);
45 SDL_DestroyProperties(props);
46
47 auto sc = scale();
48 const int iscale = static_cast<int>(sc * 100.0f);
49 auto w = 100 * rect.w / iscale;
50 auto h = 100 * rect.h / iscale;
51 std::ignore = resize({ w, h });
52 SDL_SetHint(SDL_HINT_APP_NAME, "");
53 std::ignore = SDL_SyncWindow(_window);
54}
55
56SdlWindow::SdlWindow(SdlWindow&& other) noexcept
57 : _window(other._window), _offset_x(other._offset_x), _offset_y(other._offset_y)
58{
59 other._window = nullptr;
60}
61
62SdlWindow::~SdlWindow()
63{
64 SDL_DestroyWindow(_window);
65}
66
67SDL_WindowID SdlWindow::id() const
68{
69 if (!_window)
70 return 0;
71 return SDL_GetWindowID(_window);
72}
73
74SDL_DisplayID SdlWindow::displayIndex() const
75{
76 if (!_window)
77 return 0;
78 return SDL_GetDisplayForWindow(_window);
79}
80
81SDL_Rect SdlWindow::rect() const
82{
83 SDL_Rect rect = {};
84 if (_window)
85 {
86 SDL_GetWindowPosition(_window, &rect.x, &rect.y);
87 SDL_GetWindowSizeInPixels(_window, &rect.w, &rect.h);
88 }
89 return rect;
90}
91
92SDL_Rect SdlWindow::bounds() const
93{
94 SDL_Rect rect = {};
95 if (_window)
96 {
97 SDL_GetWindowPosition(_window, &rect.x, &rect.y);
98 SDL_GetWindowSize(_window, &rect.w, &rect.h);
99 }
100 return rect;
101}
102
103SDL_Window* SdlWindow::window() const
104{
105 return _window;
106}
107
108Sint32 SdlWindow::offsetX() const
109{
110 return _offset_x;
111}
112
113void SdlWindow::setOffsetX(Sint32 x)
114{
115 _offset_x = x;
116}
117
118void SdlWindow::setOffsetY(Sint32 y)
119{
120 _offset_y = y;
121}
122
123Sint32 SdlWindow::offsetY() const
124{
125 return _offset_y;
126}
127
128rdpMonitor SdlWindow::monitor(bool isPrimary) const
129{
130 rdpMonitor mon{};
131
132 const auto factor = scale();
133 const auto dsf = static_cast<UINT32>(100 * factor);
134 mon.attributes.desktopScaleFactor = dsf;
135 mon.attributes.deviceScaleFactor = 100;
136
137 const auto r = rect();
138 mon.width = r.w;
139 mon.height = r.h;
140
141 mon.attributes.physicalWidth = WINPR_ASSERTING_INT_CAST(uint32_t, r.w);
142 mon.attributes.physicalHeight = WINPR_ASSERTING_INT_CAST(uint32_t, r.h);
143
144 SDL_Rect rect = {};
145 auto did = SDL_GetDisplayForWindow(_window);
146 auto rc = SDL_GetDisplayBounds(did, &rect);
147
148 if (rc)
149 {
150 mon.x = rect.x;
151 mon.y = rect.y;
152 }
153
154 const auto orient = orientation();
155 mon.attributes.orientation = sdl::utils::orientaion_to_rdp(orient);
156
157 auto primary = SDL_GetPrimaryDisplay();
158 mon.is_primary = isPrimary || (SDL_GetWindowID(_window) == primary);
159 mon.orig_screen = did;
160 if (mon.is_primary)
161 {
162 mon.x = 0;
163 mon.y = 0;
164 }
165 return mon;
166}
167
168float SdlWindow::scale() const
169{
170 return SDL_GetWindowDisplayScale(_window);
171}
172
173SDL_DisplayOrientation SdlWindow::orientation() const
174{
175 const auto did = displayIndex();
176 return SDL_GetCurrentDisplayOrientation(did);
177}
178
179bool SdlWindow::grabKeyboard(bool enable)
180{
181 if (!_window)
182 return false;
183 SDL_SetWindowKeyboardGrab(_window, enable);
184 return true;
185}
186
187bool SdlWindow::grabMouse(bool enable)
188{
189 if (!_window)
190 return false;
191 SDL_SetWindowMouseGrab(_window, enable);
192 return true;
193}
194
195void SdlWindow::setBordered(bool bordered)
196{
197 if (_window)
198 SDL_SetWindowBordered(_window, bordered);
199 std::ignore = SDL_SyncWindow(_window);
200}
201
202void SdlWindow::raise()
203{
204 SDL_RaiseWindow(_window);
205 std::ignore = SDL_SyncWindow(_window);
206}
207
208void SdlWindow::resizeable(bool use)
209{
210 SDL_SetWindowResizable(_window, use);
211 std::ignore = SDL_SyncWindow(_window);
212}
213
214void SdlWindow::fullscreen(bool enter)
215{
216 std::ignore = SDL_SetWindowFullscreen(_window, enter);
217 std::ignore = SDL_SyncWindow(_window);
218}
219
220void SdlWindow::minimize()
221{
222 SDL_MinimizeWindow(_window);
223 std::ignore = SDL_SyncWindow(_window);
224}
225
226bool SdlWindow::resize(const SDL_Point& size)
227{
228 return SDL_SetWindowSize(_window, size.x, size.y);
229}
230
231bool SdlWindow::drawRect(SDL_Surface* surface, SDL_Point offset, const SDL_Rect& srcRect)
232{
233 WINPR_ASSERT(surface);
234 SDL_Rect dstRect = { offset.x + srcRect.x, offset.y + srcRect.y, srcRect.w, srcRect.h };
235 return blit(surface, srcRect, dstRect);
236}
237
238bool SdlWindow::drawRects(SDL_Surface* surface, SDL_Point offset,
239 const std::vector<SDL_Rect>& rects)
240{
241 if (rects.empty())
242 {
243 return drawRect(surface, offset, { 0, 0, surface->w, surface->h });
244 }
245 for (auto& srcRect : rects)
246 {
247 if (!drawRect(surface, offset, srcRect))
248 return false;
249 }
250 return true;
251}
252
253bool SdlWindow::drawScaledRect(SDL_Surface* surface, const SDL_FPoint& scale,
254 const SDL_Rect& srcRect)
255{
256 SDL_Rect dstRect = srcRect;
257 dstRect.x = static_cast<Sint32>(static_cast<float>(dstRect.x) * scale.x);
258 dstRect.w = static_cast<Sint32>(static_cast<float>(dstRect.w) * scale.x);
259 dstRect.y = static_cast<Sint32>(static_cast<float>(dstRect.y) * scale.y);
260 dstRect.h = static_cast<Sint32>(static_cast<float>(dstRect.h) * scale.y);
261 return blit(surface, srcRect, dstRect);
262}
263
264bool SdlWindow::drawScaledRects(SDL_Surface* surface, const SDL_FPoint& scale,
265 const std::vector<SDL_Rect>& rects)
266{
267 if (rects.empty())
268 {
269 return drawScaledRect(surface, scale, { 0, 0, surface->w, surface->h });
270 }
271 for (const auto& srcRect : rects)
272 {
273 if (!drawScaledRect(surface, scale, srcRect))
274 return false;
275 }
276 return true;
277}
278
279bool SdlWindow::fill(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
280{
281 auto surface = SDL_GetWindowSurface(_window);
282 if (!surface)
283 return false;
284 SDL_Rect rect = { 0, 0, surface->w, surface->h };
285 auto color = SDL_MapSurfaceRGBA(surface, r, g, b, a);
286
287 SDL_FillSurfaceRect(surface, &rect, color);
288 return true;
289}
290
291bool SdlWindow::blit(SDL_Surface* surface, const SDL_Rect& srcRect, SDL_Rect& dstRect)
292{
293 auto screen = SDL_GetWindowSurface(_window);
294 if (!screen || !surface)
295 return false;
296 if (!SDL_SetSurfaceClipRect(surface, &srcRect))
297 return true;
298 if (!SDL_SetSurfaceClipRect(screen, &dstRect))
299 return true;
300 if (!SDL_BlitSurfaceScaled(surface, &srcRect, screen, &dstRect, SDL_SCALEMODE_LINEAR))
301 {
302 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL_BlitScaled: %s", SDL_GetError());
303 return false;
304 }
305 return true;
306}
307
308void SdlWindow::updateSurface()
309{
310 SDL_UpdateWindowSurface(_window);
311}
312
313SdlWindow SdlWindow::create(SDL_DisplayID id, const std::string& title, Uint32 flags, Uint32 width,
314 Uint32 height)
315{
316 flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
317
318 SDL_Rect rect = { static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)),
319 static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(id)), static_cast<int>(width),
320 static_cast<int>(height) };
321
322 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
323 {
324 std::ignore = SDL_GetDisplayBounds(id, &rect);
325 }
326
327 SdlWindow window{ title, rect, flags };
328
329 if ((flags & (SDL_WINDOW_FULLSCREEN)) != 0)
330 {
331 window.setOffsetX(rect.x);
332 window.setOffsetY(rect.y);
333 }
334
335 return window;
336}
SdlWindow(const std::string &title, Sint32 startupX, Sint32 startupY, Sint32 width, Sint32 height, Uint32 flags)