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 }