23#include "sdl_window.hpp"
24#include "sdl_utils.hpp"
27 [[maybe_unused]] Uint32 flags)
30 auto props = SDL_CreateProperties();
31 SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title.c_str());
32 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, rect.x);
33 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, rect.y);
34 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, rect.w);
35 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, rect.h);
37 if (flags & SDL_WINDOW_HIGH_PIXEL_DENSITY)
38 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN,
true);
40 if (flags & SDL_WINDOW_FULLSCREEN)
41 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN,
true);
43 if (flags & SDL_WINDOW_BORDERLESS)
44 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN,
true);
46 _window = SDL_CreateWindowWithProperties(props);
47 SDL_DestroyProperties(props);
50 const int iscale =
static_cast<int>(sc * 100.0f);
51 auto w = 100 * rect.w / iscale;
52 auto h = 100 * rect.h / iscale;
53 std::ignore = resize({ w, h });
54 SDL_SetHint(SDL_HINT_APP_NAME,
"");
55 std::ignore = SDL_SyncWindow(_window);
59 : _window(other._window), _displayID(other._displayID), _offset_x(other._offset_x),
60 _offset_y(other._offset_y)
62 other._window =
nullptr;
65SdlWindow::~SdlWindow()
67 SDL_DestroyWindow(_window);
70SDL_WindowID SdlWindow::id()
const
74 return SDL_GetWindowID(_window);
77SDL_DisplayID SdlWindow::displayIndex()
const
81 return SDL_GetDisplayForWindow(_window);
84SDL_Rect SdlWindow::rect()
const
89 SDL_GetWindowPosition(_window, &rect.x, &rect.y);
90 SDL_GetWindowSizeInPixels(_window, &rect.w, &rect.h);
95SDL_Rect SdlWindow::bounds()
const
100 SDL_GetWindowPosition(_window, &rect.x, &rect.y);
101 SDL_GetWindowSize(_window, &rect.w, &rect.h);
106SDL_Window* SdlWindow::window()
const
111Sint32 SdlWindow::offsetX()
const
116void SdlWindow::setOffsetX(Sint32 x)
121void SdlWindow::setOffsetY(Sint32 y)
126Sint32 SdlWindow::offsetY()
const
131rdpMonitor SdlWindow::monitor(
bool isPrimary)
const
135 const auto factor = scale();
136 const auto dsf =
static_cast<UINT32
>(100 * factor);
137 mon.attributes.desktopScaleFactor = dsf;
138 mon.attributes.deviceScaleFactor = 100;
140 const auto r = rect();
144 mon.attributes.physicalWidth = WINPR_ASSERTING_INT_CAST(uint32_t, r.w);
145 mon.attributes.physicalHeight = WINPR_ASSERTING_INT_CAST(uint32_t, r.h);
148 auto did = SDL_GetDisplayForWindow(_window);
149 auto rc = SDL_GetDisplayBounds(did, &rect);
157 const auto orient = orientation();
158 mon.attributes.orientation = sdl::utils::orientaion_to_rdp(orient);
160 auto primary = SDL_GetPrimaryDisplay();
161 mon.is_primary = isPrimary || (SDL_GetWindowID(_window) == primary);
162 mon.orig_screen = did;
171float SdlWindow::scale()
const
173 return SDL_GetWindowDisplayScale(_window);
176SDL_DisplayOrientation SdlWindow::orientation()
const
178 const auto did = displayIndex();
179 return SDL_GetCurrentDisplayOrientation(did);
182bool SdlWindow::grabKeyboard(
bool enable)
186 SDL_SetWindowKeyboardGrab(_window, enable);
190bool SdlWindow::grabMouse(
bool enable)
194 SDL_SetWindowMouseGrab(_window, enable);
198void SdlWindow::setBordered(
bool bordered)
201 SDL_SetWindowBordered(_window, bordered);
202 std::ignore = SDL_SyncWindow(_window);
205void SdlWindow::raise()
207 SDL_RaiseWindow(_window);
208 std::ignore = SDL_SyncWindow(_window);
211void SdlWindow::resizeable(
bool use)
213 SDL_SetWindowResizable(_window, use);
214 std::ignore = SDL_SyncWindow(_window);
217void SdlWindow::fullscreen(
bool enter,
bool forceOriginalDisplay)
219 if (enter && forceOriginalDisplay && _displayID != 0)
226 std::ignore = SDL_GetDisplayBounds(_displayID, &rect);
227 std::ignore = SDL_SetWindowPosition(_window, rect.x, rect.y);
229 std::ignore = SDL_SetWindowFullscreen(_window, enter);
230 std::ignore = SDL_SyncWindow(_window);
233void SdlWindow::minimize()
235 SDL_MinimizeWindow(_window);
236 std::ignore = SDL_SyncWindow(_window);
239bool SdlWindow::resize(
const SDL_Point& size)
241 return SDL_SetWindowSize(_window, size.x, size.y);
244bool SdlWindow::drawRect(SDL_Surface* surface, SDL_Point offset,
const SDL_Rect& srcRect)
246 WINPR_ASSERT(surface);
247 SDL_Rect dstRect = { offset.x + srcRect.x, offset.y + srcRect.y, srcRect.w, srcRect.h };
248 return blit(surface, srcRect, dstRect);
251bool SdlWindow::drawRects(SDL_Surface* surface, SDL_Point offset,
252 const std::vector<SDL_Rect>& rects)
256 return drawRect(surface, offset, { 0, 0, surface->w, surface->h });
258 for (
auto& srcRect : rects)
260 if (!drawRect(surface, offset, srcRect))
266bool SdlWindow::drawScaledRect(SDL_Surface* surface,
const SDL_FPoint& scale,
267 const SDL_Rect& srcRect)
269 SDL_Rect dstRect = srcRect;
270 dstRect.x =
static_cast<Sint32
>(
static_cast<float>(dstRect.x) * scale.x);
271 dstRect.w =
static_cast<Sint32
>(
static_cast<float>(dstRect.w) * scale.x);
272 dstRect.y =
static_cast<Sint32
>(
static_cast<float>(dstRect.y) * scale.y);
273 dstRect.h =
static_cast<Sint32
>(
static_cast<float>(dstRect.h) * scale.y);
274 return blit(surface, srcRect, dstRect);
277bool SdlWindow::drawScaledRects(SDL_Surface* surface,
const SDL_FPoint& scale,
278 const std::vector<SDL_Rect>& rects)
282 return drawScaledRect(surface, scale, { 0, 0, surface->w, surface->h });
284 for (
const auto& srcRect : rects)
286 if (!drawScaledRect(surface, scale, srcRect))
292bool SdlWindow::fill(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
294 auto surface = SDL_GetWindowSurface(_window);
297 SDL_Rect rect = { 0, 0, surface->w, surface->h };
298 auto color = SDL_MapSurfaceRGBA(surface, r, g, b, a);
300 SDL_FillSurfaceRect(surface, &rect, color);
304bool SdlWindow::blit(SDL_Surface* surface,
const SDL_Rect& srcRect, SDL_Rect& dstRect)
306 auto screen = SDL_GetWindowSurface(_window);
307 if (!screen || !surface)
309 if (!SDL_SetSurfaceClipRect(surface, &srcRect))
311 if (!SDL_SetSurfaceClipRect(screen, &dstRect))
313 if (!SDL_BlitSurfaceScaled(surface, &srcRect, screen, &dstRect, SDL_SCALEMODE_LINEAR))
315 SDL_LogError(SDL_LOG_CATEGORY_RENDER,
"SDL_BlitScaled: %s", SDL_GetError());
321void SdlWindow::updateSurface()
323 SDL_UpdateWindowSurface(_window);
326SdlWindow SdlWindow::create(SDL_DisplayID
id,
const std::string& title, Uint32 flags, Uint32 width,
329 flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
331 SDL_Rect rect = {
static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(
id)),
332 static_cast<int>(SDL_WINDOWPOS_CENTERED_DISPLAY(
id)),
static_cast<int>(width),
333 static_cast<int>(height) };
335 if ((flags & SDL_WINDOW_FULLSCREEN) != 0)
337 std::ignore = SDL_GetDisplayBounds(
id, &rect);
340 SdlWindow window{ id, title, rect, flags };
342 if ((flags & (SDL_WINDOW_FULLSCREEN)) != 0)
344 window.setOffsetX(rect.x);
345 window.setOffsetY(rect.y);
SdlWindow(const std::string &title, Sint32 startupX, Sint32 startupY, Sint32 width, Sint32 height, Uint32 flags)