1 /*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8 */
9 #include "events.h"
10 #include "device.h"
11
12 #include <QSize>
13
14 namespace KWin
15 {
16 namespace LibInput
17 {
18
create(libinput_event * event)19 Event *Event::create(libinput_event *event)
20 {
21 if (!event) {
22 return nullptr;
23 }
24 const auto t = libinput_event_get_type(event);
25 // TODO: add touch events
26 // TODO: add device notify events
27 switch (t) {
28 case LIBINPUT_EVENT_KEYBOARD_KEY:
29 return new KeyEvent(event);
30 case LIBINPUT_EVENT_POINTER_AXIS:
31 case LIBINPUT_EVENT_POINTER_BUTTON:
32 case LIBINPUT_EVENT_POINTER_MOTION:
33 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
34 return new PointerEvent(event, t);
35 case LIBINPUT_EVENT_TOUCH_DOWN:
36 case LIBINPUT_EVENT_TOUCH_UP:
37 case LIBINPUT_EVENT_TOUCH_MOTION:
38 case LIBINPUT_EVENT_TOUCH_CANCEL:
39 case LIBINPUT_EVENT_TOUCH_FRAME:
40 return new TouchEvent(event, t);
41 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
42 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
43 case LIBINPUT_EVENT_GESTURE_SWIPE_END:
44 return new SwipeGestureEvent(event, t);
45 case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
46 case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
47 case LIBINPUT_EVENT_GESTURE_PINCH_END:
48 return new PinchGestureEvent(event, t);
49 case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
50 case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
51 case LIBINPUT_EVENT_TABLET_TOOL_TIP:
52 return new TabletToolEvent(event, t);
53 case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
54 return new TabletToolButtonEvent(event, t);
55 case LIBINPUT_EVENT_TABLET_PAD_RING:
56 return new TabletPadRingEvent(event, t);
57 case LIBINPUT_EVENT_TABLET_PAD_STRIP:
58 return new TabletPadStripEvent(event, t);
59 case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
60 return new TabletPadButtonEvent(event, t);
61 case LIBINPUT_EVENT_SWITCH_TOGGLE:
62 return new SwitchEvent(event, t);
63 default:
64 return new Event(event, t);
65 }
66 }
67
Event(libinput_event * event,libinput_event_type type)68 Event::Event(libinput_event *event, libinput_event_type type)
69 : m_event(event)
70 , m_type(type)
71 , m_device(nullptr)
72 {
73 }
74
~Event()75 Event::~Event()
76 {
77 libinput_event_destroy(m_event);
78 }
79
device() const80 Device *Event::device() const
81 {
82 if (!m_device) {
83 m_device = Device::getDevice(libinput_event_get_device(m_event));
84 }
85 return m_device;
86 }
87
nativeDevice() const88 libinput_device *Event::nativeDevice() const
89 {
90 if (m_device) {
91 return m_device->device();
92 }
93 return libinput_event_get_device(m_event);
94 }
95
KeyEvent(libinput_event * event)96 KeyEvent::KeyEvent(libinput_event *event)
97 : Event(event, LIBINPUT_EVENT_KEYBOARD_KEY)
98 , m_keyboardEvent(libinput_event_get_keyboard_event(event))
99 {
100 }
101
102 KeyEvent::~KeyEvent() = default;
103
key() const104 uint32_t KeyEvent::key() const
105 {
106 return libinput_event_keyboard_get_key(m_keyboardEvent);
107 }
108
state() const109 InputRedirection::KeyboardKeyState KeyEvent::state() const
110 {
111 switch (libinput_event_keyboard_get_key_state(m_keyboardEvent)) {
112 case LIBINPUT_KEY_STATE_PRESSED:
113 return InputRedirection::KeyboardKeyPressed;
114 case LIBINPUT_KEY_STATE_RELEASED:
115 return InputRedirection::KeyboardKeyReleased;
116 }
117 abort();
118 }
119
time() const120 uint32_t KeyEvent::time() const
121 {
122 return libinput_event_keyboard_get_time(m_keyboardEvent);
123 }
124
PointerEvent(libinput_event * event,libinput_event_type type)125 PointerEvent::PointerEvent(libinput_event *event, libinput_event_type type)
126 : Event(event, type)
127 , m_pointerEvent(libinput_event_get_pointer_event(event))
128 {
129 }
130
131 PointerEvent::~PointerEvent() = default;
132
absolutePos() const133 QPointF PointerEvent::absolutePos() const
134 {
135 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
136 return QPointF(libinput_event_pointer_get_absolute_x(m_pointerEvent),
137 libinput_event_pointer_get_absolute_y(m_pointerEvent));
138 }
139
absolutePos(const QSize & size) const140 QPointF PointerEvent::absolutePos(const QSize &size) const
141 {
142 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
143 return QPointF(libinput_event_pointer_get_absolute_x_transformed(m_pointerEvent, size.width()),
144 libinput_event_pointer_get_absolute_y_transformed(m_pointerEvent, size.height()));
145 }
146
delta() const147 QSizeF PointerEvent::delta() const
148 {
149 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION);
150 return QSizeF(libinput_event_pointer_get_dx(m_pointerEvent), libinput_event_pointer_get_dy(m_pointerEvent));
151 }
152
deltaUnaccelerated() const153 QSizeF PointerEvent::deltaUnaccelerated() const
154 {
155 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION);
156 return QSizeF(libinput_event_pointer_get_dx_unaccelerated(m_pointerEvent), libinput_event_pointer_get_dy_unaccelerated(m_pointerEvent));
157 }
158
time() const159 uint32_t PointerEvent::time() const
160 {
161 return libinput_event_pointer_get_time(m_pointerEvent);
162 }
163
timeMicroseconds() const164 quint64 PointerEvent::timeMicroseconds() const
165 {
166 return libinput_event_pointer_get_time_usec(m_pointerEvent);
167 }
168
button() const169 uint32_t PointerEvent::button() const
170 {
171 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON);
172 return libinput_event_pointer_get_button(m_pointerEvent);
173 }
174
buttonState() const175 InputRedirection::PointerButtonState PointerEvent::buttonState() const
176 {
177 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON);
178 switch (libinput_event_pointer_get_button_state(m_pointerEvent)) {
179 case LIBINPUT_BUTTON_STATE_PRESSED:
180 return InputRedirection::PointerButtonPressed;
181 case LIBINPUT_BUTTON_STATE_RELEASED:
182 return InputRedirection::PointerButtonReleased;
183 }
184 abort();
185 }
186
axis() const187 QVector<InputRedirection::PointerAxis> PointerEvent::axis() const
188 {
189 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
190 QVector<InputRedirection::PointerAxis> a;
191 if (libinput_event_pointer_has_axis(m_pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
192 a << InputRedirection::PointerAxisHorizontal;
193 }
194 if (libinput_event_pointer_has_axis(m_pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
195 a << InputRedirection::PointerAxisVertical;
196 }
197 return a;
198 }
199
axisValue(InputRedirection::PointerAxis axis) const200 qreal PointerEvent::axisValue(InputRedirection::PointerAxis axis) const
201 {
202 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
203 const libinput_pointer_axis a = axis == InputRedirection::PointerAxisHorizontal
204 ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL
205 : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
206 return libinput_event_pointer_get_axis_value(m_pointerEvent, a) * device()->scrollFactor();
207 }
208
discreteAxisValue(InputRedirection::PointerAxis axis) const209 qint32 PointerEvent::discreteAxisValue(InputRedirection::PointerAxis axis) const
210 {
211 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
212 const libinput_pointer_axis a = (axis == InputRedirection::PointerAxisHorizontal)
213 ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL
214 : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
215 return libinput_event_pointer_get_axis_value_discrete(m_pointerEvent, a) * device()->scrollFactor();
216 }
217
axisSource() const218 InputRedirection::PointerAxisSource PointerEvent::axisSource() const
219 {
220 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
221 switch (libinput_event_pointer_get_axis_source(m_pointerEvent)) {
222 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
223 return InputRedirection::PointerAxisSourceWheel;
224 case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
225 return InputRedirection::PointerAxisSourceFinger;
226 case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
227 return InputRedirection::PointerAxisSourceContinuous;
228 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
229 return InputRedirection::PointerAxisSourceWheelTilt;
230 default:
231 return InputRedirection::PointerAxisSourceUnknown;
232 }
233 }
234
TouchEvent(libinput_event * event,libinput_event_type type)235 TouchEvent::TouchEvent(libinput_event *event, libinput_event_type type)
236 : Event(event, type)
237 , m_touchEvent(libinput_event_get_touch_event(event))
238 {
239 }
240
241 TouchEvent::~TouchEvent() = default;
242
time() const243 quint32 TouchEvent::time() const
244 {
245 return libinput_event_touch_get_time(m_touchEvent);
246 }
247
absolutePos() const248 QPointF TouchEvent::absolutePos() const
249 {
250 Q_ASSERT(type() == LIBINPUT_EVENT_TOUCH_DOWN || type() == LIBINPUT_EVENT_TOUCH_MOTION);
251 return QPointF(libinput_event_touch_get_x(m_touchEvent),
252 libinput_event_touch_get_y(m_touchEvent));
253 }
254
absolutePos(const QSize & size) const255 QPointF TouchEvent::absolutePos(const QSize &size) const
256 {
257 Q_ASSERT(type() == LIBINPUT_EVENT_TOUCH_DOWN || type() == LIBINPUT_EVENT_TOUCH_MOTION);
258 return QPointF(libinput_event_touch_get_x_transformed(m_touchEvent, size.width()),
259 libinput_event_touch_get_y_transformed(m_touchEvent, size.height()));
260 }
261
id() const262 qint32 TouchEvent::id() const
263 {
264 Q_ASSERT(type() != LIBINPUT_EVENT_TOUCH_FRAME);
265
266 return libinput_event_touch_get_seat_slot(m_touchEvent);
267 }
268
GestureEvent(libinput_event * event,libinput_event_type type)269 GestureEvent::GestureEvent(libinput_event *event, libinput_event_type type)
270 : Event(event, type)
271 , m_gestureEvent(libinput_event_get_gesture_event(event))
272 {
273 }
274
275 GestureEvent::~GestureEvent() = default;
276
time() const277 quint32 GestureEvent::time() const
278 {
279 return libinput_event_gesture_get_time(m_gestureEvent);
280 }
281
fingerCount() const282 int GestureEvent::fingerCount() const
283 {
284 return libinput_event_gesture_get_finger_count(m_gestureEvent);
285 }
286
delta() const287 QSizeF GestureEvent::delta() const
288 {
289 return QSizeF(libinput_event_gesture_get_dx(m_gestureEvent),
290 libinput_event_gesture_get_dy(m_gestureEvent));
291 }
292
isCancelled() const293 bool GestureEvent::isCancelled() const
294 {
295 return libinput_event_gesture_get_cancelled(m_gestureEvent) != 0;
296 }
297
PinchGestureEvent(libinput_event * event,libinput_event_type type)298 PinchGestureEvent::PinchGestureEvent(libinput_event *event, libinput_event_type type)
299 : GestureEvent(event, type)
300 {
301 }
302
303 PinchGestureEvent::~PinchGestureEvent() = default;
304
scale() const305 qreal PinchGestureEvent::scale() const
306 {
307 return libinput_event_gesture_get_scale(m_gestureEvent);
308 }
309
angleDelta() const310 qreal PinchGestureEvent::angleDelta() const
311 {
312 return libinput_event_gesture_get_angle_delta(m_gestureEvent);
313 }
314
SwipeGestureEvent(libinput_event * event,libinput_event_type type)315 SwipeGestureEvent::SwipeGestureEvent(libinput_event *event, libinput_event_type type)
316 : GestureEvent(event, type)
317 {
318 }
319
320 SwipeGestureEvent::~SwipeGestureEvent() = default;
321
SwitchEvent(libinput_event * event,libinput_event_type type)322 SwitchEvent::SwitchEvent(libinput_event *event, libinput_event_type type)
323 : Event(event, type)
324 , m_switchEvent(libinput_event_get_switch_event(event))
325 {
326 }
327
328 SwitchEvent::~SwitchEvent() = default;
329
state() const330 SwitchEvent::State SwitchEvent::state() const
331 {
332 switch (libinput_event_switch_get_switch_state(m_switchEvent))
333 {
334 case LIBINPUT_SWITCH_STATE_OFF:
335 return State::Off;
336 case LIBINPUT_SWITCH_STATE_ON:
337 return State::On;
338 default:
339 Q_UNREACHABLE();
340 }
341 return State::Off;
342 }
343
time() const344 quint32 SwitchEvent::time() const
345 {
346 return libinput_event_switch_get_time(m_switchEvent);
347 }
348
timeMicroseconds() const349 quint64 SwitchEvent::timeMicroseconds() const
350 {
351 return libinput_event_switch_get_time_usec(m_switchEvent);
352 }
353
TabletToolEvent(libinput_event * event,libinput_event_type type)354 TabletToolEvent::TabletToolEvent(libinput_event *event, libinput_event_type type)
355 : Event(event, type)
356 , m_tabletToolEvent(libinput_event_get_tablet_tool_event(event))
357 {
358 }
359
TabletToolButtonEvent(libinput_event * event,libinput_event_type type)360 TabletToolButtonEvent::TabletToolButtonEvent(libinput_event *event, libinput_event_type type)
361 : Event(event, type)
362 , m_tabletToolEvent(libinput_event_get_tablet_tool_event(event))
363 {
364 }
365
TabletPadButtonEvent(libinput_event * event,libinput_event_type type)366 TabletPadButtonEvent::TabletPadButtonEvent(libinput_event *event, libinput_event_type type)
367 : Event(event, type)
368 , m_tabletPadEvent(libinput_event_get_tablet_pad_event(event))
369 {
370 }
371
TabletPadStripEvent(libinput_event * event,libinput_event_type type)372 TabletPadStripEvent::TabletPadStripEvent(libinput_event *event, libinput_event_type type)
373 : Event(event, type)
374 , m_tabletPadEvent(libinput_event_get_tablet_pad_event(event))
375 {
376 }
377
TabletPadRingEvent(libinput_event * event,libinput_event_type type)378 TabletPadRingEvent::TabletPadRingEvent(libinput_event *event, libinput_event_type type)
379 : Event(event, type)
380 , m_tabletPadEvent(libinput_event_get_tablet_pad_event(event))
381 {
382 }
383 }
384 }
385