Merge pull request #10982 from jpy794/sdl3-hidpi

Fix sdl3-freerdp blurry scaling on wayland when scale factor > 1
This commit is contained in:
akallabeth
2025-03-24 18:30:34 +01:00
committed by GitHub
5 changed files with 85 additions and 20 deletions

View File

@@ -51,8 +51,7 @@ BOOL sdlDispContext::settings_changed()
freerdp_settings_get_uint16(settings, FreeRDP_DesktopOrientation))
return TRUE;
if (_lastSentDesktopScaleFactor !=
freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor))
if (_lastSentDesktopScaleFactor != _targetDesktopScaleFactor)
return TRUE;
if (_lastSentDeviceScaleFactor !=
@@ -75,7 +74,7 @@ BOOL sdlDispContext::update_last_sent()
_lastSentWidth = _targetWidth;
_lastSentHeight = _targetHeight;
_lastSentDesktopOrientation = freerdp_settings_get_uint16(settings, FreeRDP_DesktopOrientation);
_lastSentDesktopScaleFactor = freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor);
_lastSentDesktopScaleFactor = _targetDesktopScaleFactor;
_lastSentDeviceScaleFactor = freerdp_settings_get_uint32(settings, FreeRDP_DeviceScaleFactor);
// TODO _fullscreen = _sdl->fullscreen;
return TRUE;
@@ -116,8 +115,7 @@ BOOL sdlDispContext::sendResize()
layout.Width = WINPR_ASSERTING_INT_CAST(uint32_t, _targetWidth);
layout.Height = WINPR_ASSERTING_INT_CAST(uint32_t, _targetHeight);
layout.Orientation = freerdp_settings_get_uint16(settings, FreeRDP_DesktopOrientation);
layout.DesktopScaleFactor =
freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor);
layout.DesktopScaleFactor = _targetDesktopScaleFactor;
layout.DeviceScaleFactor = freerdp_settings_get_uint32(settings, FreeRDP_DeviceScaleFactor);
layout.PhysicalWidth = WINPR_ASSERTING_INT_CAST(uint32_t, _targetWidth);
layout.PhysicalHeight = WINPR_ASSERTING_INT_CAST(uint32_t, _targetHeight);
@@ -356,13 +354,19 @@ BOOL sdlDispContext::handle_window_event(const SDL_WindowEvent* ev)
case SDL_EVENT_WINDOW_RESTORED:
gdi_send_suppress_output(_sdl->context()->gdi, FALSE);
return TRUE;
case SDL_EVENT_WINDOW_RESIZED:
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
_targetWidth = ev->data1;
_targetHeight = ev->data2;
{
if (freerdp_settings_get_bool(_sdl->context()->settings,
FreeRDP_DynamicResolutionUpdate))
{
const auto& window = _sdl->windows.at(ev->windowID);
const auto factor = SDL_GetWindowDisplayScale(window.window());
_targetDesktopScaleFactor = static_cast<UINT32>(100 * factor);
}
assert(SDL_GetWindowSizeInPixels(it->second.window(), &_targetWidth, &_targetHeight));
return addTimer();
}
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
WINPR_ASSERT(_sdl);
_sdl->input.keyboard_grab(ev->windowID, false);
@@ -456,6 +460,8 @@ sdlDispContext::sdlDispContext(SdlContext* sdl) : _sdl(sdl)
int32_t, freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth));
_lastSentHeight = _targetHeight = WINPR_ASSERTING_INT_CAST(
int32_t, freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight));
_lastSentDesktopScaleFactor = _targetDesktopScaleFactor =
freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor);
PubSub_SubscribeActivated(pubSub, sdlDispContext::OnActivated);
PubSub_SubscribeGraphicsReset(pubSub, sdlDispContext::OnGraphicsReset);
addTimer();

View File

@@ -45,6 +45,11 @@ class sdlDispContext
BOOL handle_window_event(const SDL_WindowEvent* ev);
[[nodiscard]] UINT32 scale_factor() const
{
return _lastSentDesktopScaleFactor;
}
private:
UINT DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA,
UINT32 maxMonitorAreaFactorB);
@@ -75,6 +80,7 @@ class sdlDispContext
UINT16 _lastSentDesktopOrientation = 0;
UINT32 _lastSentDesktopScaleFactor = 0;
UINT32 _lastSentDeviceScaleFactor = 0;
UINT32 _targetDesktopScaleFactor = 0;
SDL_TimerID _timer = 0;
unsigned _timer_retries = 0;
};

View File

@@ -403,6 +403,8 @@ static BOOL sdl_draw_to_window(SdlContext* sdl, SdlWindow& window,
if (!freerdp_settings_get_bool(context->settings, FreeRDP_SmartSizing))
{
window.setOffsetX(0);
window.setOffsetY(0);
if (gdi->width < size.w)
{
window.setOffsetX((size.w - gdi->width) / 2);
@@ -775,12 +777,13 @@ static BOOL sdl_create_windows(SdlContext* sdl)
static BOOL sdl_wait_create_windows(SdlContext* sdl)
{
std::lock_guard<CriticalSection> lock(sdl->critical);
std::unique_lock<CriticalSection> lock(sdl->critical);
sdl->windows_created.clear();
if (!sdl_push_user_event(SDL_EVENT_USER_CREATE_WINDOWS, sdl))
return FALSE;
lock.unlock();
HANDLE handles[] = { sdl->initialized.handle(), freerdp_abort_event(sdl->context()) };
HANDLE handles[] = { sdl->windows_created.handle(), freerdp_abort_event(sdl->context()) };
const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, INFINITE);
switch (rc)
@@ -864,6 +867,16 @@ static int sdl_run(SdlContext* sdl)
}
}
auto point2pix = [](Uint32 win_id, float& x, float& y)
{
auto win = SDL_GetWindowFromID(win_id);
assert(win);
auto scale = SDL_GetWindowDisplayScale(win);
assert(scale);
x *= scale;
y *= scale;
};
switch (windowEvent.type)
{
case SDL_EVENT_QUIT:
@@ -882,15 +895,18 @@ static int sdl_run(SdlContext* sdl)
break; // TODO: Switch keyboard layout
case SDL_EVENT_MOUSE_MOTION:
{
const SDL_MouseMotionEvent* ev = &windowEvent.motion;
sdl_handle_mouse_motion(sdl, ev);
SDL_MouseMotionEvent& ev = windowEvent.motion;
point2pix(ev.windowID, ev.x, ev.y);
point2pix(ev.windowID, ev.xrel, ev.yrel);
sdl_handle_mouse_motion(sdl, &ev);
}
break;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
{
const SDL_MouseButtonEvent* ev = &windowEvent.button;
sdl_handle_mouse_button(sdl, ev);
SDL_MouseButtonEvent& ev = windowEvent.button;
point2pix(ev.windowID, ev.x, ev.y);
sdl_handle_mouse_button(sdl, &ev);
}
break;
case SDL_EVENT_MOUSE_WHEEL:
@@ -1017,6 +1033,7 @@ static int sdl_run(SdlContext* sdl)
}
break;
case SDL_EVENT_USER_POINTER_SET:
windowEvent.user.code = static_cast<Sint32>(sdl->disp.scale_factor());
sdl_Pointer_Set_Process(&windowEvent.user);
break;
case SDL_EVENT_CLIPBOARD_UPDATE:
@@ -1041,10 +1058,32 @@ static int sdl_run(SdlContext* sdl)
switch (ev->type)
{
case SDL_EVENT_WINDOW_RESIZED:
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
{
if (freerdp_settings_get_bool(sdl->context()->settings,
FreeRDP_DynamicResolutionUpdate))
{
break;
}
auto win = window->second.window();
int w_pix{};
int h_pix{};
assert(SDL_GetWindowSizeInPixels(win, &w_pix, &h_pix));
auto scale = SDL_GetWindowDisplayScale(win);
assert(scale != 0);
auto w_gdi = sdl->context()->gdi->width;
auto h_gdi = sdl->context()->gdi->height;
auto pix2point = [=](int pix)
{ return static_cast<int>(static_cast<float>(pix) / scale); };
if (w_pix != w_gdi || h_pix != h_gdi)
{
SDL_SetWindowSize(win, pix2point(w_gdi), pix2point(h_gdi));
}
}
break;
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
window->second.fill();
window->second.updateSurface();
sdl_draw_to_window(sdl, window->second);
break;
case SDL_EVENT_WINDOW_MOVED:
{

View File

@@ -158,10 +158,23 @@ BOOL sdl_Pointer_Set_Process(SDL_UserEvent* uptr)
if (!rc)
return FALSE;
ptr->cursor = SDL_CreateColorCursor(ptr->image, x, y);
// create a cursor image in 100% display scale to trick SDL into creating the cursor with the
// correct size
const auto hidpi_scale = static_cast<float>(uptr->code) / 100;
auto normal = SDL_CreateSurface(
static_cast<int>(static_cast<float>(ptr->image->w) / hidpi_scale),
static_cast<int>(static_cast<float>(ptr->image->h) / hidpi_scale), ptr->image->format);
assert(normal);
SDL_BlitSurfaceScaled(ptr->image, nullptr, normal, nullptr,
SDL_ScaleMode::SDL_SCALEMODE_NEAREST);
SDL_AddSurfaceAlternateImage(normal, ptr->image);
ptr->cursor = SDL_CreateColorCursor(normal, x, y);
if (!ptr->cursor)
return FALSE;
SDL_DestroySurface(normal);
SDL_SetCursor(ptr->cursor);
SDL_ShowCursor();
return TRUE;

View File

@@ -29,6 +29,7 @@ SdlWindow::SdlWindow(const std::string& title, Sint32 startupX, Sint32 startupY,
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, startupY);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, true);
// SDL_SetProperty(props, SDL_PROP_WINDOW_CREATE_FL);
_window = SDL_CreateWindowWithProperties(props);
SDL_DestroyProperties(props);
@@ -65,7 +66,7 @@ SDL_Rect SdlWindow::rect() const
if (_window)
{
SDL_GetWindowPosition(_window, &rect.x, &rect.y);
SDL_GetWindowSize(_window, &rect.w, &rect.h);
SDL_GetWindowSizeInPixels(_window, &rect.w, &rect.h);
}
return rect;
}