File indexing completed on 2024-11-10 04:56:32
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "events.h" 0010 #include "device.h" 0011 0012 #include <QSize> 0013 0014 namespace KWin 0015 { 0016 namespace LibInput 0017 { 0018 0019 std::unique_ptr<Event> Event::create(libinput_event *event) 0020 { 0021 if (!event) { 0022 return nullptr; 0023 } 0024 const auto t = libinput_event_get_type(event); 0025 // TODO: add touch events 0026 // TODO: add device notify events 0027 switch (t) { 0028 case LIBINPUT_EVENT_KEYBOARD_KEY: 0029 return std::make_unique<KeyEvent>(event); 0030 case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: 0031 case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: 0032 case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: 0033 case LIBINPUT_EVENT_POINTER_BUTTON: 0034 case LIBINPUT_EVENT_POINTER_MOTION: 0035 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: 0036 return std::make_unique<PointerEvent>(event, t); 0037 case LIBINPUT_EVENT_TOUCH_DOWN: 0038 case LIBINPUT_EVENT_TOUCH_UP: 0039 case LIBINPUT_EVENT_TOUCH_MOTION: 0040 case LIBINPUT_EVENT_TOUCH_CANCEL: 0041 case LIBINPUT_EVENT_TOUCH_FRAME: 0042 return std::make_unique<TouchEvent>(event, t); 0043 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: 0044 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: 0045 case LIBINPUT_EVENT_GESTURE_SWIPE_END: 0046 return std::make_unique<SwipeGestureEvent>(event, t); 0047 case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: 0048 case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: 0049 case LIBINPUT_EVENT_GESTURE_PINCH_END: 0050 return std::make_unique<PinchGestureEvent>(event, t); 0051 case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN: 0052 case LIBINPUT_EVENT_GESTURE_HOLD_END: 0053 return std::make_unique<HoldGestureEvent>(event, t); 0054 case LIBINPUT_EVENT_TABLET_TOOL_AXIS: 0055 case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: 0056 case LIBINPUT_EVENT_TABLET_TOOL_TIP: 0057 return std::make_unique<TabletToolEvent>(event, t); 0058 case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: 0059 return std::make_unique<TabletToolButtonEvent>(event, t); 0060 case LIBINPUT_EVENT_TABLET_PAD_RING: 0061 return std::make_unique<TabletPadRingEvent>(event, t); 0062 case LIBINPUT_EVENT_TABLET_PAD_STRIP: 0063 return std::make_unique<TabletPadStripEvent>(event, t); 0064 case LIBINPUT_EVENT_TABLET_PAD_BUTTON: 0065 return std::make_unique<TabletPadButtonEvent>(event, t); 0066 case LIBINPUT_EVENT_SWITCH_TOGGLE: 0067 return std::make_unique<SwitchEvent>(event, t); 0068 default: 0069 return std::unique_ptr<Event>{new Event(event, t)}; 0070 } 0071 } 0072 0073 Event::Event(libinput_event *event, libinput_event_type type) 0074 : m_event(event) 0075 , m_type(type) 0076 , m_device(nullptr) 0077 { 0078 } 0079 0080 Event::~Event() 0081 { 0082 libinput_event_destroy(m_event); 0083 } 0084 0085 Device *Event::device() const 0086 { 0087 if (!m_device) { 0088 m_device = Device::get(libinput_event_get_device(m_event)); 0089 } 0090 return m_device; 0091 } 0092 0093 libinput_device *Event::nativeDevice() const 0094 { 0095 if (m_device) { 0096 return m_device->device(); 0097 } 0098 return libinput_event_get_device(m_event); 0099 } 0100 0101 KeyEvent::KeyEvent(libinput_event *event) 0102 : Event(event, LIBINPUT_EVENT_KEYBOARD_KEY) 0103 , m_keyboardEvent(libinput_event_get_keyboard_event(event)) 0104 { 0105 } 0106 0107 KeyEvent::~KeyEvent() = default; 0108 0109 uint32_t KeyEvent::key() const 0110 { 0111 return libinput_event_keyboard_get_key(m_keyboardEvent); 0112 } 0113 0114 InputRedirection::KeyboardKeyState KeyEvent::state() const 0115 { 0116 switch (libinput_event_keyboard_get_key_state(m_keyboardEvent)) { 0117 case LIBINPUT_KEY_STATE_PRESSED: 0118 return InputRedirection::KeyboardKeyPressed; 0119 case LIBINPUT_KEY_STATE_RELEASED: 0120 return InputRedirection::KeyboardKeyReleased; 0121 default: 0122 Q_UNREACHABLE(); 0123 } 0124 } 0125 0126 std::chrono::microseconds KeyEvent::time() const 0127 { 0128 return std::chrono::microseconds(libinput_event_keyboard_get_time_usec(m_keyboardEvent)); 0129 } 0130 0131 PointerEvent::PointerEvent(libinput_event *event, libinput_event_type type) 0132 : Event(event, type) 0133 , m_pointerEvent(libinput_event_get_pointer_event(event)) 0134 { 0135 } 0136 0137 PointerEvent::~PointerEvent() = default; 0138 0139 QPointF PointerEvent::absolutePos() const 0140 { 0141 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); 0142 return QPointF(libinput_event_pointer_get_absolute_x(m_pointerEvent), 0143 libinput_event_pointer_get_absolute_y(m_pointerEvent)); 0144 } 0145 0146 QPointF PointerEvent::absolutePos(const QSize &size) const 0147 { 0148 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); 0149 return QPointF(libinput_event_pointer_get_absolute_x_transformed(m_pointerEvent, size.width()), 0150 libinput_event_pointer_get_absolute_y_transformed(m_pointerEvent, size.height())); 0151 } 0152 0153 QPointF PointerEvent::delta() const 0154 { 0155 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION); 0156 return QPointF(libinput_event_pointer_get_dx(m_pointerEvent), libinput_event_pointer_get_dy(m_pointerEvent)); 0157 } 0158 0159 QPointF PointerEvent::deltaUnaccelerated() const 0160 { 0161 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION); 0162 return QPointF(libinput_event_pointer_get_dx_unaccelerated(m_pointerEvent), libinput_event_pointer_get_dy_unaccelerated(m_pointerEvent)); 0163 } 0164 0165 std::chrono::microseconds PointerEvent::time() const 0166 { 0167 return std::chrono::microseconds(libinput_event_pointer_get_time_usec(m_pointerEvent)); 0168 } 0169 0170 uint32_t PointerEvent::button() const 0171 { 0172 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON); 0173 return libinput_event_pointer_get_button(m_pointerEvent); 0174 } 0175 0176 InputRedirection::PointerButtonState PointerEvent::buttonState() const 0177 { 0178 Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON); 0179 switch (libinput_event_pointer_get_button_state(m_pointerEvent)) { 0180 case LIBINPUT_BUTTON_STATE_PRESSED: 0181 return InputRedirection::PointerButtonPressed; 0182 case LIBINPUT_BUTTON_STATE_RELEASED: 0183 return InputRedirection::PointerButtonReleased; 0184 default: 0185 Q_UNREACHABLE(); 0186 } 0187 } 0188 0189 QList<InputRedirection::PointerAxis> PointerEvent::axis() const 0190 { 0191 QList<InputRedirection::PointerAxis> a; 0192 if (libinput_event_pointer_has_axis(m_pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { 0193 a << InputRedirection::PointerAxisHorizontal; 0194 } 0195 if (libinput_event_pointer_has_axis(m_pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { 0196 a << InputRedirection::PointerAxisVertical; 0197 } 0198 return a; 0199 } 0200 0201 qreal PointerEvent::scrollValue(InputRedirection::PointerAxis axis) const 0202 { 0203 const libinput_pointer_axis a = axis == InputRedirection::PointerAxisHorizontal 0204 ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL 0205 : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; 0206 return libinput_event_pointer_get_scroll_value(m_pointerEvent, a) * device()->scrollFactor(); 0207 } 0208 0209 qint32 PointerEvent::scrollValueV120(InputRedirection::PointerAxis axis) const 0210 { 0211 const libinput_pointer_axis a = (axis == InputRedirection::PointerAxisHorizontal) 0212 ? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL 0213 : LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; 0214 return libinput_event_pointer_get_scroll_value_v120(m_pointerEvent, a) * device()->scrollFactor(); 0215 } 0216 0217 TouchEvent::TouchEvent(libinput_event *event, libinput_event_type type) 0218 : Event(event, type) 0219 , m_touchEvent(libinput_event_get_touch_event(event)) 0220 { 0221 } 0222 0223 TouchEvent::~TouchEvent() = default; 0224 0225 std::chrono::microseconds TouchEvent::time() const 0226 { 0227 return std::chrono::microseconds(libinput_event_touch_get_time_usec(m_touchEvent)); 0228 } 0229 0230 QPointF TouchEvent::absolutePos() const 0231 { 0232 Q_ASSERT(type() == LIBINPUT_EVENT_TOUCH_DOWN || type() == LIBINPUT_EVENT_TOUCH_MOTION); 0233 return QPointF(libinput_event_touch_get_x(m_touchEvent), 0234 libinput_event_touch_get_y(m_touchEvent)); 0235 } 0236 0237 QPointF TouchEvent::absolutePos(const QSize &size) const 0238 { 0239 Q_ASSERT(type() == LIBINPUT_EVENT_TOUCH_DOWN || type() == LIBINPUT_EVENT_TOUCH_MOTION); 0240 return QPointF(libinput_event_touch_get_x_transformed(m_touchEvent, size.width()), 0241 libinput_event_touch_get_y_transformed(m_touchEvent, size.height())); 0242 } 0243 0244 qint32 TouchEvent::id() const 0245 { 0246 Q_ASSERT(type() != LIBINPUT_EVENT_TOUCH_FRAME); 0247 0248 return libinput_event_touch_get_seat_slot(m_touchEvent); 0249 } 0250 0251 GestureEvent::GestureEvent(libinput_event *event, libinput_event_type type) 0252 : Event(event, type) 0253 , m_gestureEvent(libinput_event_get_gesture_event(event)) 0254 { 0255 } 0256 0257 GestureEvent::~GestureEvent() = default; 0258 0259 std::chrono::microseconds GestureEvent::time() const 0260 { 0261 return std::chrono::microseconds(libinput_event_gesture_get_time_usec(m_gestureEvent)); 0262 } 0263 0264 int GestureEvent::fingerCount() const 0265 { 0266 return libinput_event_gesture_get_finger_count(m_gestureEvent); 0267 } 0268 0269 QPointF GestureEvent::delta() const 0270 { 0271 return QPointF(libinput_event_gesture_get_dx(m_gestureEvent), 0272 libinput_event_gesture_get_dy(m_gestureEvent)); 0273 } 0274 0275 bool GestureEvent::isCancelled() const 0276 { 0277 return libinput_event_gesture_get_cancelled(m_gestureEvent) != 0; 0278 } 0279 0280 PinchGestureEvent::PinchGestureEvent(libinput_event *event, libinput_event_type type) 0281 : GestureEvent(event, type) 0282 { 0283 } 0284 0285 PinchGestureEvent::~PinchGestureEvent() = default; 0286 0287 qreal PinchGestureEvent::scale() const 0288 { 0289 return libinput_event_gesture_get_scale(m_gestureEvent); 0290 } 0291 0292 qreal PinchGestureEvent::angleDelta() const 0293 { 0294 return libinput_event_gesture_get_angle_delta(m_gestureEvent); 0295 } 0296 0297 SwipeGestureEvent::SwipeGestureEvent(libinput_event *event, libinput_event_type type) 0298 : GestureEvent(event, type) 0299 { 0300 } 0301 0302 SwipeGestureEvent::~SwipeGestureEvent() = default; 0303 0304 HoldGestureEvent::HoldGestureEvent(libinput_event *event, libinput_event_type type) 0305 : GestureEvent(event, type) 0306 { 0307 } 0308 0309 HoldGestureEvent::~HoldGestureEvent() = default; 0310 0311 SwitchEvent::SwitchEvent(libinput_event *event, libinput_event_type type) 0312 : Event(event, type) 0313 , m_switchEvent(libinput_event_get_switch_event(event)) 0314 { 0315 } 0316 0317 SwitchEvent::~SwitchEvent() = default; 0318 0319 SwitchEvent::State SwitchEvent::state() const 0320 { 0321 switch (libinput_event_switch_get_switch_state(m_switchEvent)) { 0322 case LIBINPUT_SWITCH_STATE_OFF: 0323 return State::Off; 0324 case LIBINPUT_SWITCH_STATE_ON: 0325 return State::On; 0326 default: 0327 Q_UNREACHABLE(); 0328 } 0329 return State::Off; 0330 } 0331 0332 std::chrono::microseconds SwitchEvent::time() const 0333 { 0334 return std::chrono::microseconds(libinput_event_switch_get_time_usec(m_switchEvent)); 0335 } 0336 0337 TabletToolEvent::TabletToolEvent(libinput_event *event, libinput_event_type type) 0338 : Event(event, type) 0339 , m_tabletToolEvent(libinput_event_get_tablet_tool_event(event)) 0340 { 0341 } 0342 0343 QPointF TabletToolEvent::transformedPosition(const QSize &size) const 0344 { 0345 const QRectF outputArea = device()->outputArea(); 0346 return {size.width() * outputArea.x() + libinput_event_tablet_tool_get_x_transformed(m_tabletToolEvent, size.width() * outputArea.width()), 0347 size.height() * outputArea.y() + libinput_event_tablet_tool_get_y_transformed(m_tabletToolEvent, size.height() * outputArea.height())}; 0348 } 0349 0350 TabletToolButtonEvent::TabletToolButtonEvent(libinput_event *event, libinput_event_type type) 0351 : Event(event, type) 0352 , m_tabletToolEvent(libinput_event_get_tablet_tool_event(event)) 0353 { 0354 } 0355 0356 TabletPadButtonEvent::TabletPadButtonEvent(libinput_event *event, libinput_event_type type) 0357 : Event(event, type) 0358 , m_tabletPadEvent(libinput_event_get_tablet_pad_event(event)) 0359 { 0360 } 0361 0362 TabletPadStripEvent::TabletPadStripEvent(libinput_event *event, libinput_event_type type) 0363 : Event(event, type) 0364 , m_tabletPadEvent(libinput_event_get_tablet_pad_event(event)) 0365 { 0366 } 0367 0368 TabletPadRingEvent::TabletPadRingEvent(libinput_event *event, libinput_event_type type) 0369 : Event(event, type) 0370 , m_tabletPadEvent(libinput_event_get_tablet_pad_event(event)) 0371 { 0372 } 0373 } 0374 }