FreeRDP
Loading...
Searching...
No Matches
SDL3/sdl_touch.cpp
1
20#include <freerdp/config.h>
21
22#include "sdl_touch.hpp"
23#include "sdl_context.hpp"
24
25#include <winpr/wtypes.h>
26#include <winpr/assert.h>
27
28#include <freerdp/freerdp.h>
29#include <freerdp/gdi/gdi.h>
30
31#include <SDL3/SDL.h>
32
33[[nodiscard]] static bool send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue)
34{
35 WINPR_ASSERT(sdl);
36 if (avalue < 0)
37 {
38 flags |= PTR_FLAGS_WHEEL_NEGATIVE;
39 avalue = -avalue;
40 }
41
42 while (avalue > 0)
43 {
44 const UINT16 cval = (avalue > 0xFF) ? 0xFF : static_cast<UINT16>(avalue);
45 UINT16 cflags = flags | cval;
46 /* Convert negative values to 9bit twos complement */
47 if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
48 cflags = (flags & 0xFF00) | (0x100 - cval);
49 if (!freerdp_client_send_wheel_event(sdl->common(), cflags))
50 return FALSE;
51
52 avalue -= cval;
53 }
54 return TRUE;
55}
56
57[[nodiscard]] static UINT32 sdl_scale_pressure(const float pressure)
58{
59 const float val = pressure * 0x400; /* [MS-RDPEI] 2.2.3.3.1.1 RDPINPUT_TOUCH_CONTACT */
60 if (val < 0.0f)
61 return 0;
62 if (val > 0x400)
63 return 0x400;
64 return static_cast<UINT32>(val);
65}
66
67bool SdlTouch::touchUp(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
68{
69 WINPR_ASSERT(sdl);
70
71 return freerdp_client_handle_touch(sdl->common(), FREERDP_TOUCH_UP | FREERDP_TOUCH_HAS_PRESSURE,
72 static_cast<INT32>(ev.fingerID),
73 sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
74 static_cast<Sint32>(ev.y));
75}
76
77bool SdlTouch::touchCancel(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
78{
79 WINPR_ASSERT(sdl);
80
81 return freerdp_client_handle_touch(
82 sdl->common(), FREERDP_TOUCH_CANCEL | FREERDP_TOUCH_HAS_PRESSURE,
83 static_cast<INT32>(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
84 static_cast<Sint32>(ev.y));
85}
86
87bool SdlTouch::touchDown(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
88{
89 WINPR_ASSERT(sdl);
90
91 return freerdp_client_handle_touch(
92 sdl->common(), FREERDP_TOUCH_DOWN | FREERDP_TOUCH_HAS_PRESSURE,
93 static_cast<INT32>(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
94 static_cast<Sint32>(ev.y));
95}
96
97bool SdlTouch::touchMotion(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
98{
99 WINPR_ASSERT(sdl);
100
101 return freerdp_client_handle_touch(
102 sdl->common(), FREERDP_TOUCH_MOTION | FREERDP_TOUCH_HAS_PRESSURE,
103 static_cast<INT32>(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast<Sint32>(ev.x),
104 static_cast<Sint32>(ev.y));
105}
106
107bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseMotionEvent& ev)
108{
109 WINPR_ASSERT(sdl);
110
111 if (!sdl->getInputChannelContext().mouse_focus(ev.windowID))
112 return FALSE;
113
114 const BOOL relative =
115 freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor();
116 auto x = static_cast<INT32>(relative ? ev.xrel : ev.x);
117 auto y = static_cast<INT32>(relative ? ev.yrel : ev.y);
118 return freerdp_client_send_button_event(sdl->common(), relative, PTR_FLAGS_MOVE, x, y);
119}
120
121bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseWheelEvent& ev)
122{
123 WINPR_ASSERT(sdl);
124
125 const BOOL flipped = (ev.direction == SDL_MOUSEWHEEL_FLIPPED);
126 const auto x = static_cast<INT32>(ev.x * (flipped ? -1.0f : 1.0f) * 120.0f);
127 const auto y = static_cast<INT32>(ev.y * (flipped ? -1.0f : 1.0f) * 120.0f);
128 UINT16 flags = 0;
129
130 if (y != 0)
131 {
132 flags |= PTR_FLAGS_WHEEL;
133 if (!send_mouse_wheel(sdl, flags, y))
134 return false;
135 }
136
137 if (x != 0)
138 {
139 flags |= PTR_FLAGS_HWHEEL;
140 if (!send_mouse_wheel(sdl, flags, x))
141 return false;
142 }
143 return TRUE;
144}
145
146bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseButtonEvent& ev)
147{
148 UINT16 flags = 0;
149 UINT16 xflags = 0;
150
151 WINPR_ASSERT(sdl);
152
153 if (ev.type == SDL_EVENT_MOUSE_BUTTON_DOWN)
154 {
155 flags |= PTR_FLAGS_DOWN;
156 xflags |= PTR_XFLAGS_DOWN;
157 }
158
159 switch (ev.button)
160 {
161 case 1:
162 flags |= PTR_FLAGS_BUTTON1;
163 break;
164 case 2:
165 flags |= PTR_FLAGS_BUTTON3;
166 break;
167 case 3:
168 flags |= PTR_FLAGS_BUTTON2;
169 break;
170 case 4:
171 xflags |= PTR_XFLAGS_BUTTON1;
172 break;
173 case 5:
174 xflags |= PTR_XFLAGS_BUTTON2;
175 break;
176 default:
177 break;
178 }
179
180 const BOOL relative =
181 freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor();
182 auto x = static_cast<INT32>(relative ? 0 : ev.x);
183 auto y = static_cast<INT32>(relative ? 0 : ev.y);
184
185 if ((flags & (~PTR_FLAGS_DOWN)) != 0)
186 return freerdp_client_send_button_event(sdl->common(), relative, flags, x, y);
187 else if ((xflags & (~PTR_XFLAGS_DOWN)) != 0)
188 return freerdp_client_send_extended_button_event(sdl->common(), relative, xflags, x, y);
189 else
190 return FALSE;
191}
192
193bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_TouchFingerEvent& ev)
194{
195 switch (ev.type)
196 {
197 case SDL_EVENT_FINGER_CANCELED:
198 return SdlTouch::touchCancel(sdl, ev);
199 case SDL_EVENT_FINGER_UP:
200 return SdlTouch::touchUp(sdl, ev);
201 case SDL_EVENT_FINGER_DOWN:
202 return SdlTouch::touchDown(sdl, ev);
203 case SDL_EVENT_FINGER_MOTION:
204 return SdlTouch::touchMotion(sdl, ev);
205 default:
206 return false;
207 }
208}