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