[client,sdl] simplify event handling

pass on events to SdlContext and let the class handle it internally
This commit is contained in:
akallabeth
2026-01-25 12:28:38 +01:00
parent 9468720d93
commit 947427a911
7 changed files with 251 additions and 307 deletions

View File

@@ -21,6 +21,7 @@
#include "sdl_channels.hpp"
#include "sdl_monitor.hpp"
#include "sdl_pointer.hpp"
#include "sdl_touch.hpp"
#include <sdl_common_utils.hpp>
#include <scoped_guard.hpp>
@@ -519,7 +520,7 @@ void SdlContext::sdl_client_cleanup(int exit_code, const std::string& error_msg)
getDialog().show(false);
_exitCode = exit_code;
(void)sdl_push_user_event(SDL_EVENT_USER_QUIT);
std::ignore = sdl_push_user_event(SDL_EVENT_USER_QUIT);
SDL_CleanupTLS();
}
@@ -852,13 +853,34 @@ bool SdlContext::moveMouseTo(const SDL_FPoint& pos)
return true;
}
bool SdlContext::handleEvent(const SDL_WindowEvent* ev)
bool SdlContext::handleEvent(const SDL_MouseMotionEvent& ev)
{
SDL_Event copy{};
copy.motion = ev;
if (!eventToPixelCoordinates(ev.windowID, copy))
return false;
removeLocalScaling(copy.motion.x, copy.motion.y);
removeLocalScaling(copy.motion.xrel, copy.motion.yrel);
return SdlTouch::handleEvent(this, copy.motion);
}
bool SdlContext::handleEvent(const SDL_MouseWheelEvent& ev)
{
SDL_Event copy{};
copy.wheel = ev;
if (!eventToPixelCoordinates(ev.windowID, copy))
return false;
removeLocalScaling(copy.wheel.mouse_x, copy.wheel.mouse_y);
return SdlTouch::handleEvent(this, copy.wheel);
}
bool SdlContext::handleEvent(const SDL_WindowEvent& ev)
{
if (!getDisplayChannelContext().handleEvent(ev))
return false;
auto window = getWindowForId(ev->windowID);
auto window = getWindowForId(ev.windowID);
if (!window)
return true;
@@ -869,30 +891,31 @@ bool SdlContext::handleEvent(const SDL_WindowEvent* ev)
const auto& orientation = window->orientation();
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION,
"%s: [%u] %dx%d-%dx%d {%dx%d-%dx%d}{scale=%f,orientation=%s}",
sdl::utils::toString(ev->type).c_str(), ev->windowID, r.x, r.y, r.w, r.h, b.x,
b.y, b.w, b.h, scale, sdl::utils::toString(orientation).c_str());
sdl::utils::toString(ev.type).c_str(), ev.windowID, r.x, r.y, r.w, r.h, b.x,
b.y, b.w, b.h, static_cast<double>(scale),
sdl::utils::toString(orientation).c_str());
}
switch (ev->type)
switch (ev.type)
{
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
if (isConnected())
{
if (!window->fill())
return -1;
return false;
if (!drawToWindow(*window))
return -1;
return false;
if (!sdl_Pointer_Set_Process(this))
return -1;
return false;
}
break;
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
if (!window->fill())
return -1;
return false;
if (!drawToWindow(*window))
return -1;
return false;
if (!sdl_Pointer_Set_Process(this))
return -1;
return false;
break;
case SDL_EVENT_WINDOW_MOVED:
{
@@ -913,32 +936,61 @@ bool SdlContext::handleEvent(const SDL_WindowEvent* ev)
return true;
}
bool SdlContext::handleEvent(const SDL_DisplayEvent* ev)
bool SdlContext::handleEvent(const SDL_DisplayEvent& ev)
{
if (!getDisplayChannelContext().handleEvent(ev))
return false;
{
SDL_Rect r = {};
if (!SDL_GetDisplayBounds(ev->displayID, &r))
return false;
const auto name = SDL_GetDisplayName(ev->displayID);
if (!name)
return false;
const auto orientation = SDL_GetCurrentDisplayOrientation(ev->displayID);
const auto scale = SDL_GetDisplayContentScale(ev->displayID);
const auto mode = SDL_GetCurrentDisplayMode(ev->displayID);
if (!mode)
return false;
SDL_LogDebug(
SDL_LOG_CATEGORY_APPLICATION, "%s: [%u, %s] %dx%d-%dx%d {orientation=%s, scale=%f}%s",
sdl::utils::toString(ev->type).c_str(), ev->displayID, name, r.x, r.y, r.w, r.h,
sdl::utils::toString(orientation).c_str(), scale, sdl::utils::toString(mode).c_str());
switch (ev.type)
{
case SDL_EVENT_DISPLAY_REMOVED: // Can't show details for this one...
break;
default:
{
SDL_Rect r = {};
if (!SDL_GetDisplayBounds(ev.displayID, &r))
return false;
const auto name = SDL_GetDisplayName(ev.displayID);
if (!name)
return false;
const auto orientation = SDL_GetCurrentDisplayOrientation(ev.displayID);
const auto scale = SDL_GetDisplayContentScale(ev.displayID);
const auto mode = SDL_GetCurrentDisplayMode(ev.displayID);
if (!mode)
return false;
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION,
"%s: [%u, %s] %dx%d-%dx%d {orientation=%s, scale=%f}%s",
sdl::utils::toString(ev.type).c_str(), ev.displayID, name, r.x, r.y, r.w,
r.h, sdl::utils::toString(orientation).c_str(), static_cast<double>(scale),
sdl::utils::toString(mode).c_str());
}
break;
}
return true;
}
bool SdlContext::handleEvent(const SDL_MouseButtonEvent& ev)
{
SDL_Event copy = {};
copy.button = ev;
if (!eventToPixelCoordinates(ev.windowID, copy))
return false;
removeLocalScaling(copy.button.x, copy.button.y);
return SdlTouch::handleEvent(this, copy.button);
}
bool SdlContext::handleEvent(const SDL_TouchFingerEvent& ev)
{
SDL_Event copy{};
copy.tfinger = ev;
if (!eventToPixelCoordinates(ev.windowID, copy))
return false;
removeLocalScaling(copy.tfinger.dx, copy.tfinger.dy);
removeLocalScaling(copy.tfinger.x, copy.tfinger.y);
return SdlTouch::handleEvent(this, copy.tfinger);
}
bool SdlContext::eventToPixelCoordinates(SDL_WindowID id, SDL_Event& ev)
{
auto w = getWindowForId(id);
@@ -1007,6 +1059,49 @@ SDL_FRect SdlContext::pixelToScreen(SDL_WindowID id, const SDL_FRect& pos)
return { fpos.x, fpos.y, size.x, size.y };
}
bool SdlContext::handleEvent(const SDL_Event& windowEvent)
{
if ((windowEvent.type >= SDL_EVENT_DISPLAY_FIRST) &&
(windowEvent.type <= SDL_EVENT_DISPLAY_LAST))
{
const auto& ev = windowEvent.display;
return handleEvent(ev);
}
if ((windowEvent.type >= SDL_EVENT_WINDOW_FIRST) && (windowEvent.type <= SDL_EVENT_WINDOW_LAST))
{
const auto& ev = windowEvent.window;
return handleEvent(ev);
}
switch (windowEvent.type)
{
case SDL_EVENT_FINGER_DOWN:
case SDL_EVENT_FINGER_UP:
case SDL_EVENT_FINGER_MOTION:
{
const auto& ev = windowEvent.tfinger;
return handleEvent(ev);
}
case SDL_EVENT_MOUSE_MOTION:
{
const auto& ev = windowEvent.motion;
return handleEvent(ev);
}
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
{
const auto& ev = windowEvent.button;
return handleEvent(ev);
}
case SDL_EVENT_MOUSE_WHEEL:
{
const auto& ev = windowEvent.wheel;
return handleEvent(ev);
}
default:
return true;
}
}
bool SdlContext::drawToWindows(const std::vector<SDL_Rect>& rects)
{
for (auto& window : _windows)

View File

@@ -127,8 +127,7 @@ class SdlContext
[[nodiscard]] SDL_FPoint pixelToScreen(SDL_WindowID id, const SDL_FPoint& pos);
[[nodiscard]] SDL_FRect pixelToScreen(SDL_WindowID id, const SDL_FRect& pos);
[[nodiscard]] bool handleEvent(const SDL_WindowEvent* ev);
[[nodiscard]] bool handleEvent(const SDL_DisplayEvent* ev);
[[nodiscard]] bool handleEvent(const SDL_Event& ev);
private:
[[nodiscard]] static BOOL preConnect(freerdp* instance);
@@ -146,6 +145,13 @@ class SdlContext
[[nodiscard]] SDL_FPoint applyLocalScaling(const SDL_FPoint& val) const;
void removeLocalScaling(float& x, float& y);
[[nodiscard]] bool handleEvent(const SDL_WindowEvent& ev);
[[nodiscard]] bool handleEvent(const SDL_DisplayEvent& ev);
[[nodiscard]] bool handleEvent(const SDL_MouseButtonEvent& ev);
[[nodiscard]] bool handleEvent(const SDL_MouseMotionEvent& ev);
[[nodiscard]] bool handleEvent(const SDL_MouseWheelEvent& ev);
[[nodiscard]] bool handleEvent(const SDL_TouchFingerEvent& ev);
[[nodiscard]] bool createPrimary();
[[nodiscard]] std::string windowTitle() const;
[[nodiscard]] bool waitForWindowsCreated();

View File

@@ -27,7 +27,6 @@
#include "sdl_disp.hpp"
#include "sdl_input.hpp"
#include "sdl_utils.hpp"
#include "sdl_context.hpp"
#include <freerdp/log.h>
@@ -85,7 +84,7 @@ bool sdlDispContext::sendResize()
const UINT32 mcount = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
auto monitors = static_cast<const rdpMonitor*>(
freerdp_settings_get_pointer(settings, FreeRDP_MonitorDefArray));
return sendLayout(monitors, mcount) != CHANNEL_RC_OK;
return sendLayout(monitors, mcount);
}
bool sdlDispContext::setWindowResizeable()
@@ -131,7 +130,7 @@ void sdlDispContext::OnActivated(void* context, const ActivatedEventArgs* e)
if (e->firstActivation)
return;
(void)sdlDisp->addTimer();
std::ignore = sdlDisp->addTimer();
}
}
@@ -150,7 +149,7 @@ void sdlDispContext::OnGraphicsReset(void* context, const GraphicsResetEventArgs
if (sdlDisp->_activated && !freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))
{
if (sdlDisp->setWindowResizeable())
(void)sdlDisp->addTimer();
std::ignore = sdlDisp->addTimer();
}
}
@@ -186,10 +185,8 @@ Uint32 sdlDispContext::OnTimer(void* param, [[maybe_unused]] SDL_TimerID timerID
return interval;
}
UINT sdlDispContext::sendLayout(const rdpMonitor* monitors, size_t nmonitors)
bool sdlDispContext::sendLayout(const rdpMonitor* monitors, size_t nmonitors)
{
UINT ret = CHANNEL_RC_OK;
WINPR_ASSERT(monitors);
WINPR_ASSERT(nmonitors > 0);
@@ -261,12 +258,12 @@ UINT sdlDispContext::sendLayout(const rdpMonitor* monitors, size_t nmonitors)
WINPR_ASSERT(_disp);
const size_t len = layouts.size();
WINPR_ASSERT(len <= UINT32_MAX);
ret = IFCALLRESULT(CHANNEL_RC_OK, _disp->SendMonitorLayout, _disp, static_cast<UINT32>(len),
layouts.data());
const auto ret = IFCALLRESULT(CHANNEL_RC_OK, _disp->SendMonitorLayout, _disp,
static_cast<UINT32>(len), layouts.data());
if (ret != CHANNEL_RC_OK)
return ret;
return false;
_last_sent_layout = layouts;
return ret;
return true;
}
bool sdlDispContext::addTimer()
@@ -284,12 +281,8 @@ bool sdlDispContext::addTimer()
return true;
}
bool sdlDispContext::updateMonitor(SDL_WindowID id)
bool sdlDispContext::updateMonitor([[maybe_unused]] SDL_WindowID id)
{
auto settings = _sdl->context()->settings;
if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon))
return updateMonitors(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, id);
if (!freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_DynamicResolutionUpdate))
return true;
@@ -327,58 +320,54 @@ bool sdlDispContext::updateMonitors(SDL_EventType type, SDL_DisplayID displayID)
return addTimer();
}
bool sdlDispContext::handleEvent(const SDL_DisplayEvent* ev)
bool sdlDispContext::handleEvent(const SDL_DisplayEvent& ev)
{
WINPR_ASSERT(ev);
switch (ev->type)
switch (ev.type)
{
case SDL_EVENT_DISPLAY_ADDED:
SDL_Log("A new display with id %u was connected", ev->displayID);
return updateMonitors(ev->type, ev->displayID);
SDL_Log("A new display with id %u was connected", ev.displayID);
return updateMonitors(ev.type, ev.displayID);
case SDL_EVENT_DISPLAY_REMOVED:
SDL_Log("The display with id %u was disconnected", ev->displayID);
return updateMonitors(ev->type, ev->displayID);
SDL_Log("The display with id %u was disconnected", ev.displayID);
return updateMonitors(ev.type, ev.displayID);
case SDL_EVENT_DISPLAY_ORIENTATION:
SDL_Log("The orientation of display with id %u was changed", ev->displayID);
return updateMonitors(ev->type, ev->displayID);
SDL_Log("The orientation of display with id %u was changed", ev.displayID);
return updateMonitors(ev.type, ev.displayID);
case SDL_EVENT_DISPLAY_MOVED:
SDL_Log("The display with id %u was moved", ev->displayID);
return updateMonitors(ev->type, ev->displayID);
SDL_Log("The display with id %u was moved", ev.displayID);
return updateMonitors(ev.type, ev.displayID);
case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
SDL_Log("The display with id %u changed scale", ev->displayID);
return updateMonitors(ev->type, ev->displayID);
SDL_Log("The display with id %u changed scale", ev.displayID);
return updateMonitors(ev.type, ev.displayID);
case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED:
SDL_Log("The display with id %u changed mode", ev->displayID);
return updateMonitors(ev->type, ev->displayID);
SDL_Log("The display with id %u changed mode", ev.displayID);
return updateMonitors(ev.type, ev.displayID);
case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED:
SDL_Log("The display with id %u changed desktop mode", ev->displayID);
return updateMonitors(ev->type, ev->displayID);
SDL_Log("The display with id %u changed desktop mode", ev.displayID);
return updateMonitors(ev.type, ev.displayID);
default:
return true;
}
}
bool sdlDispContext::handleEvent(const SDL_WindowEvent* ev)
bool sdlDispContext::handleEvent(const SDL_WindowEvent& ev)
{
WINPR_ASSERT(ev);
auto window = _sdl->getWindowForId(ev->windowID);
auto window = _sdl->getWindowForId(ev.windowID);
if (!window)
return true;
auto bordered = freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_Decorations);
window->setBordered(bordered);
switch (ev->type)
switch (ev.type)
{
case SDL_EVENT_WINDOW_HIDDEN:
case SDL_EVENT_WINDOW_MINIMIZED:
return _sdl->redraw(true);
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
return updateMonitor(ev->windowID);
return updateMonitor(ev.windowID);
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
return updateMonitor(ev->windowID);
return updateMonitor(ev.windowID);
case SDL_EVENT_WINDOW_EXPOSED:
case SDL_EVENT_WINDOW_SHOWN:
@@ -392,13 +381,13 @@ bool sdlDispContext::handleEvent(const SDL_WindowEvent* ev)
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
case SDL_EVENT_WINDOW_RESIZED:
return updateMonitor(ev->windowID);
return updateMonitor(ev.windowID);
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
WINPR_ASSERT(_sdl);
return _sdl->getInputChannelContext().keyboard_grab(ev->windowID, false);
return _sdl->getInputChannelContext().keyboard_grab(ev.windowID, false);
case SDL_EVENT_WINDOW_MOUSE_ENTER:
WINPR_ASSERT(_sdl);
if (!_sdl->getInputChannelContext().keyboard_grab(ev->windowID, true))
if (!_sdl->getInputChannelContext().keyboard_grab(ev.windowID, true))
return false;
return _sdl->getInputChannelContext().keyboard_focus_in();
case SDL_EVENT_WINDOW_FOCUS_GAINED:
@@ -479,7 +468,7 @@ sdlDispContext::sdlDispContext(SdlContext* sdl) : _sdl(sdl)
PubSub_SubscribeActivated(pubSub, sdlDispContext::OnActivated);
PubSub_SubscribeGraphicsReset(pubSub, sdlDispContext::OnGraphicsReset);
(void)addTimer();
std::ignore = addTimer();
}
sdlDispContext::~sdlDispContext()

View File

@@ -43,8 +43,8 @@ class sdlDispContext
[[nodiscard]] bool init(DispClientContext* disp);
[[nodiscard]] bool uninit(DispClientContext* disp);
[[nodiscard]] bool handleEvent(const SDL_DisplayEvent* ev);
[[nodiscard]] bool handleEvent(const SDL_WindowEvent* ev);
[[nodiscard]] bool handleEvent(const SDL_DisplayEvent& ev);
[[nodiscard]] bool handleEvent(const SDL_WindowEvent& ev);
private:
[[nodiscard]] UINT DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA,
@@ -53,7 +53,7 @@ class sdlDispContext
[[nodiscard]] bool sendResize();
[[nodiscard]] bool settings_changed(const std::vector<DISPLAY_CONTROL_MONITOR_LAYOUT>& layout);
[[nodiscard]] UINT sendLayout(const rdpMonitor* monitors, size_t nmonitors);
[[nodiscard]] bool sendLayout(const rdpMonitor* monitors, size_t nmonitors);
[[nodiscard]] bool addTimer();

View File

@@ -59,14 +59,11 @@
#include "dialogs/sdl_dialogs.hpp"
#include "scoped_guard.hpp"
#include "sdl_channels.hpp"
#include "sdl_disp.hpp"
#include "sdl_freerdp.hpp"
#include "sdl_context.hpp"
#include "sdl_input.hpp"
#include "sdl_monitor.hpp"
#include "sdl_pointer.hpp"
#include "sdl_prefs.hpp"
#include "sdl_touch.hpp"
#include "sdl_utils.hpp"
#if defined(_WIN32)
@@ -76,10 +73,10 @@
static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const char* signame,
[[maybe_unused]] void* context)
{
(void)sdl_push_quit();
std::ignore = sdl_push_quit();
}
static int sdl_run(SdlContext* sdl)
[[nodiscard]] static int sdl_run(SdlContext* sdl)
{
int rc = -1;
WINPR_ASSERT(sdl);
@@ -110,17 +107,8 @@ static int sdl_run(SdlContext* sdl)
if (sdl->getDialog().handleEvent(windowEvent))
continue;
auto point2pix = [](Uint32 win_id, float& x, float& y)
{
auto win = SDL_GetWindowFromID(win_id);
if (win)
{
auto scale = SDL_GetWindowDisplayScale(win);
assert(scale);
x *= scale;
y *= scale;
}
};
if (!sdl->handleEvent(windowEvent))
return -1;
switch (windowEvent.type)
{
@@ -135,65 +123,14 @@ static int sdl_run(SdlContext* sdl)
return -1;
}
break;
case SDL_EVENT_KEYMAP_CHANGED:
{
}
break; // TODO: Switch keyboard layout
case SDL_EVENT_MOUSE_MOTION:
{
SDL_MouseMotionEvent& ev = windowEvent.motion;
point2pix(ev.windowID, ev.x, ev.y);
point2pix(ev.windowID, ev.xrel, ev.yrel);
if (!sdl_handle_mouse_motion(sdl, &ev))
return -1;
}
break;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
{
SDL_MouseButtonEvent& ev = windowEvent.button;
point2pix(ev.windowID, ev.x, ev.y);
if (!sdl_handle_mouse_button(sdl, &ev))
return -1;
}
break;
case SDL_EVENT_MOUSE_WHEEL:
{
const SDL_MouseWheelEvent* ev = &windowEvent.wheel;
if (!sdl_handle_mouse_wheel(sdl, ev))
return -1;
}
break;
case SDL_EVENT_FINGER_DOWN:
{
const SDL_TouchFingerEvent* ev = &windowEvent.tfinger;
if (!sdl_handle_touch_down(sdl, ev))
return -1;
}
break;
case SDL_EVENT_FINGER_UP:
{
const SDL_TouchFingerEvent* ev = &windowEvent.tfinger;
if (!sdl_handle_touch_up(sdl, ev))
return -1;
}
break;
case SDL_EVENT_FINGER_MOTION:
{
const SDL_TouchFingerEvent* ev = &windowEvent.tfinger;
if (!sdl_handle_touch_motion(sdl, ev))
return -1;
}
break;
case SDL_EVENT_RENDER_TARGETS_RESET:
(void)sdl->redraw();
std::ignore = sdl->redraw();
break;
case SDL_EVENT_RENDER_DEVICE_RESET:
(void)sdl->redraw();
std::ignore = sdl->redraw();
break;
case SDL_EVENT_WILL_ENTER_FOREGROUND:
(void)sdl->redraw();
std::ignore = sdl->redraw();
break;
case SDL_EVENT_USER_CERT_DIALOG:
{
@@ -304,20 +241,6 @@ static int sdl_run(SdlContext* sdl)
break;
case SDL_EVENT_USER_QUIT:
default:
if ((windowEvent.type >= SDL_EVENT_DISPLAY_FIRST) &&
(windowEvent.type <= SDL_EVENT_DISPLAY_LAST))
{
const SDL_DisplayEvent* ev = &windowEvent.display;
if (!sdl->handleEvent(ev))
return -1;
}
else if ((windowEvent.type >= SDL_EVENT_WINDOW_FIRST) &&
(windowEvent.type <= SDL_EVENT_WINDOW_LAST))
{
const SDL_WindowEvent* ev = &windowEvent.window;
if (!sdl->handleEvent(ev))
return -1;
}
break;
}
}
@@ -331,7 +254,7 @@ static int sdl_run(SdlContext* sdl)
/* Optional global initializer.
* Here we just register a signal handler to print out stack traces
* if available. */
static BOOL sdl_client_global_init()
[[nodiscard]] static BOOL sdl_client_global_init()
{
#if defined(_WIN32)
WSADATA wsaData = {};
@@ -355,7 +278,7 @@ static void sdl_client_global_uninit()
#endif
}
static BOOL sdl_client_new(freerdp* instance, rdpContext* context)
[[nodiscard]] static BOOL sdl_client_new(freerdp* instance, rdpContext* context)
{
auto sdl = reinterpret_cast<sdl_rdp_context*>(context);
@@ -376,21 +299,21 @@ static void sdl_client_free([[maybe_unused]] freerdp* instance, rdpContext* cont
delete sdl->sdl;
}
static int sdl_client_start(rdpContext* context)
[[nodiscard]] static int sdl_client_start(rdpContext* context)
{
auto sdl = get_context(context);
WINPR_ASSERT(sdl);
return sdl->start();
}
static int sdl_client_stop(rdpContext* context)
[[nodiscard]] static int sdl_client_stop(rdpContext* context)
{
auto sdl = get_context(context);
WINPR_ASSERT(sdl);
return sdl->join();
}
static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
static void RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
{
WINPR_ASSERT(pEntryPoints);
@@ -404,7 +327,6 @@ static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
pEntryPoints->ClientFree = sdl_client_free;
pEntryPoints->ClientStart = sdl_client_start;
pEntryPoints->ClientStop = sdl_client_stop;
return 0;
}
static void context_free(sdl_rdp_context* sdl)
@@ -413,7 +335,7 @@ static void context_free(sdl_rdp_context* sdl)
freerdp_client_context_free(&sdl->common.context);
}
static const char* category2str(int category)
[[nodiscard]] static const char* category2str(int category)
{
switch (category)
{
@@ -461,7 +383,7 @@ static const char* category2str(int category)
}
}
static SDL_LogPriority wloglevel2dl(DWORD level)
[[nodiscard]] static SDL_LogPriority wloglevel2dl(DWORD level)
{
switch (level)
{
@@ -483,7 +405,7 @@ static SDL_LogPriority wloglevel2dl(DWORD level)
}
}
static DWORD sdlpriority2wlog(SDL_LogPriority priority)
[[nodiscard]] static DWORD sdlpriority2wlog(SDL_LogPriority priority)
{
DWORD level = WLOG_OFF;
switch (priority)
@@ -567,7 +489,7 @@ static void SDLCALL rdp_file_cb(void* userdata, const char* const* filelist,
sdl_quit();
}
static std::string getRdpFile()
[[nodiscard]] static std::string getRdpFile()
{
const auto flags = SDL_INIT_VIDEO | SDL_INIT_EVENTS;
SDL_DialogFileFilter filters[] = { { "RDP files", "rdp;rdpw" } };
@@ -589,7 +511,7 @@ static std::string getRdpFile()
do
{
SDL_Event event = {};
(void)SDL_PollEvent(&event);
std::ignore = SDL_PollEvent(&event);
switch (event.type)
{

View File

@@ -30,88 +30,7 @@
#include <SDL3/SDL.h>
BOOL sdl_scale_coordinates(SdlContext* sdl, Uint32 windowId, INT32* px, INT32* py,
BOOL fromLocalToRDP, BOOL applyOffset)
{
rdpGdi* gdi = nullptr;
double sx = 1.0;
double sy = 1.0;
if (!sdl || !px || !py || !sdl->context()->gdi)
return FALSE;
WINPR_ASSERT(sdl->context()->gdi);
WINPR_ASSERT(sdl->context()->settings);
gdi = sdl->context()->gdi;
// TODO: Make this multimonitor ready!
// TODO: Need to find the primary monitor, get the scale
// TODO: Need to find the destination monitor, get the scale
// TODO: All intermediate monitors, get the scale
int offset_x = 0;
int offset_y = 0;
auto window = sdl->getWindowForId(windowId);
if (window)
{
auto size = window->rect();
sx = size.w / static_cast<double>(gdi->width);
sy = size.h / static_cast<double>(gdi->height);
offset_x = window->offsetX();
offset_y = window->offsetY();
}
if (freerdp_settings_get_bool(sdl->context()->settings, FreeRDP_SmartSizing))
{
if (!fromLocalToRDP)
{
*px = static_cast<INT32>(*px * sx);
*py = static_cast<INT32>(*py * sy);
}
else
{
*px = static_cast<INT32>(*px / sx);
*py = static_cast<INT32>(*py / sy);
}
}
else if (applyOffset)
{
*px -= offset_x;
*py -= offset_y;
}
return TRUE;
}
static BOOL sdl_get_touch_scaled(SdlContext* sdl, const SDL_TouchFingerEvent* ev, INT32* px,
INT32* py, BOOL local)
{
Uint32 windowID = 0;
WINPR_ASSERT(sdl);
WINPR_ASSERT(ev);
WINPR_ASSERT(px);
WINPR_ASSERT(py);
SDL_Window* window = SDL_GetWindowFromID(ev->windowID);
if (!window)
return FALSE;
windowID = SDL_GetWindowID(window);
SDL_Surface* surface = SDL_GetWindowSurface(window);
if (!surface)
return FALSE;
// TODO: Add the offset of the surface in the global coordinates
*px = static_cast<INT32>(ev->x * static_cast<float>(surface->w));
*py = static_cast<INT32>(ev->y * static_cast<float>(surface->h));
return sdl_scale_coordinates(sdl, windowID, px, py, local, TRUE);
}
static BOOL send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue)
static bool send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue)
{
WINPR_ASSERT(sdl);
if (avalue < 0)
@@ -145,73 +64,67 @@ static UINT32 sdl_scale_pressure(const float pressure)
return static_cast<UINT32>(val);
}
BOOL sdl_handle_touch_up(SdlContext* sdl, const SDL_TouchFingerEvent* ev)
bool SdlTouch::touchUp(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
{
WINPR_ASSERT(sdl);
WINPR_ASSERT(ev);
INT32 x = 0;
INT32 y = 0;
if (!sdl_get_touch_scaled(sdl, ev, &x, &y, TRUE))
return FALSE;
return freerdp_client_handle_touch(sdl->common(), FREERDP_TOUCH_UP | FREERDP_TOUCH_HAS_PRESSURE,
static_cast<INT32>(ev->fingerID),
sdl_scale_pressure(ev->pressure), x, y);
static_cast<INT32>(ev.fingerID),
sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
static_cast<Sint32>(ev.y));
}
BOOL sdl_handle_touch_down(SdlContext* sdl, const SDL_TouchFingerEvent* ev)
bool SdlTouch::touchCancel(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
{
WINPR_ASSERT(sdl);
return freerdp_client_handle_touch(
sdl->common(), FREERDP_TOUCH_CANCEL | FREERDP_TOUCH_HAS_PRESSURE,
static_cast<INT32>(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
static_cast<Sint32>(ev.y));
}
bool SdlTouch::touchDown(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
{
WINPR_ASSERT(sdl);
WINPR_ASSERT(ev);
INT32 x = 0;
INT32 y = 0;
if (!sdl_get_touch_scaled(sdl, ev, &x, &y, TRUE))
return FALSE;
return freerdp_client_handle_touch(
sdl->common(), FREERDP_TOUCH_DOWN | FREERDP_TOUCH_HAS_PRESSURE,
static_cast<INT32>(ev->fingerID), sdl_scale_pressure(ev->pressure), x, y);
static_cast<INT32>(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
static_cast<Sint32>(ev.y));
}
BOOL sdl_handle_touch_motion(SdlContext* sdl, const SDL_TouchFingerEvent* ev)
bool SdlTouch::touchMotion(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
{
WINPR_ASSERT(sdl);
WINPR_ASSERT(ev);
INT32 x = 0;
INT32 y = 0;
if (!sdl_get_touch_scaled(sdl, ev, &x, &y, TRUE))
return FALSE;
return freerdp_client_handle_touch(
sdl->common(), FREERDP_TOUCH_MOTION | FREERDP_TOUCH_HAS_PRESSURE,
static_cast<INT32>(ev->fingerID), sdl_scale_pressure(ev->pressure), x, y);
static_cast<INT32>(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
static_cast<Sint32>(ev.y));
}
BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev)
bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseMotionEvent& ev)
{
WINPR_ASSERT(sdl);
WINPR_ASSERT(ev);
if (!sdl->getInputChannelContext().mouse_focus(ev->windowID))
if (!sdl->getInputChannelContext().mouse_focus(ev.windowID))
return FALSE;
const BOOL relative =
freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor();
auto x = static_cast<INT32>(relative ? ev->xrel : ev->x);
auto y = static_cast<INT32>(relative ? ev->yrel : ev->y);
if (!sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE))
return FALSE;
auto x = static_cast<INT32>(relative ? ev.xrel : ev.x);
auto y = static_cast<INT32>(relative ? ev.yrel : ev.y);
return freerdp_client_send_button_event(sdl->common(), relative, PTR_FLAGS_MOVE, x, y);
}
BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev)
bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseWheelEvent& ev)
{
WINPR_ASSERT(sdl);
WINPR_ASSERT(ev);
const BOOL flipped = (ev->direction == SDL_MOUSEWHEEL_FLIPPED);
const auto x = static_cast<INT32>(ev->x * (flipped ? -1.0f : 1.0f) * 120.0f);
const auto y = static_cast<INT32>(ev->y * (flipped ? -1.0f : 1.0f) * 120.0f);
const BOOL flipped = (ev.direction == SDL_MOUSEWHEEL_FLIPPED);
const auto x = static_cast<INT32>(ev.x * (flipped ? -1.0f : 1.0f) * 120.0f);
const auto y = static_cast<INT32>(ev.y * (flipped ? -1.0f : 1.0f) * 120.0f);
UINT16 flags = 0;
if (y != 0)
@@ -228,21 +141,20 @@ BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev)
return TRUE;
}
BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev)
bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseButtonEvent& ev)
{
UINT16 flags = 0;
UINT16 xflags = 0;
WINPR_ASSERT(sdl);
WINPR_ASSERT(ev);
if (ev->type == SDL_EVENT_MOUSE_BUTTON_DOWN)
if (ev.type == SDL_EVENT_MOUSE_BUTTON_DOWN)
{
flags |= PTR_FLAGS_DOWN;
xflags |= PTR_XFLAGS_DOWN;
}
switch (ev->button)
switch (ev.button)
{
case 1:
flags |= PTR_FLAGS_BUTTON1;
@@ -265,10 +177,8 @@ BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev)
const BOOL relative =
freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor();
auto x = static_cast<INT32>(relative ? 0 : ev->x);
auto y = static_cast<INT32>(relative ? 0 : ev->y);
if (!sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE))
return FALSE;
auto x = static_cast<INT32>(relative ? 0 : ev.x);
auto y = static_cast<INT32>(relative ? 0 : ev.y);
if ((flags & (~PTR_FLAGS_DOWN)) != 0)
return freerdp_client_send_button_event(sdl->common(), relative, flags, x, y);
@@ -277,3 +187,20 @@ BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev)
else
return FALSE;
}
bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
{
switch (ev.type)
{
case SDL_EVENT_FINGER_CANCELED:
return SdlTouch::touchCancel(sdl, ev);
case SDL_EVENT_FINGER_UP:
return SdlTouch::touchUp(sdl, ev);
case SDL_EVENT_FINGER_DOWN:
return SdlTouch::touchDown(sdl, ev);
case SDL_EVENT_FINGER_MOTION:
return SdlTouch::touchMotion(sdl, ev);
default:
return false;
}
}

View File

@@ -24,13 +24,18 @@
#include <SDL3/SDL.h>
#include "sdl_types.hpp"
[[nodiscard]] BOOL sdl_scale_coordinates(SdlContext* sdl, Uint32 windowId, INT32* px, INT32* py,
BOOL fromLocalToRDP, BOOL applyOffset);
class SdlTouch
{
public:
[[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_MouseMotionEvent& ev);
[[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_MouseWheelEvent& ev);
[[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_MouseButtonEvent& ev);
[[nodiscard]] BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev);
[[nodiscard]] BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev);
[[nodiscard]] BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev);
[[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_TouchFingerEvent& ev);
[[nodiscard]] BOOL sdl_handle_touch_down(SdlContext* sdl, const SDL_TouchFingerEvent* ev);
[[nodiscard]] BOOL sdl_handle_touch_up(SdlContext* sdl, const SDL_TouchFingerEvent* ev);
[[nodiscard]] BOOL sdl_handle_touch_motion(SdlContext* sdl, const SDL_TouchFingerEvent* ev);
private:
[[nodiscard]] static bool touchDown(SdlContext* sdl, const SDL_TouchFingerEvent& ev);
[[nodiscard]] static bool touchUp(SdlContext* sdl, const SDL_TouchFingerEvent& ev);
[[nodiscard]] static bool touchCancel(SdlContext* sdl, const SDL_TouchFingerEvent& ev);
[[nodiscard]] static bool touchMotion(SdlContext* sdl, const SDL_TouchFingerEvent& ev);
};