File indexing completed on 2025-04-27 11:32:59
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2017 Martin Flöser <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "x11_standalone_effects_mouse_interception_filter.h" 0010 #include "effects.h" 0011 #include "utils/common.h" 0012 0013 #include <QMouseEvent> 0014 0015 namespace KWin 0016 { 0017 0018 EffectsMouseInterceptionX11Filter::EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandlerImpl *effects) 0019 : X11EventFilter(QVector<int>{XCB_BUTTON_PRESS, XCB_BUTTON_RELEASE, XCB_MOTION_NOTIFY}) 0020 , m_effects(effects) 0021 , m_window(window) 0022 { 0023 } 0024 0025 bool EffectsMouseInterceptionX11Filter::event(xcb_generic_event_t *event) 0026 { 0027 const uint8_t eventType = event->response_type & ~0x80; 0028 if (eventType == XCB_BUTTON_PRESS || eventType == XCB_BUTTON_RELEASE) { 0029 auto *me = reinterpret_cast<xcb_button_press_event_t *>(event); 0030 if (m_window == me->event) { 0031 const bool isWheel = me->detail >= 4 && me->detail <= 7; 0032 if (isWheel) { 0033 if (eventType != XCB_BUTTON_PRESS) { 0034 return false; 0035 } 0036 QPoint angleDelta; 0037 switch (me->detail) { 0038 case 4: 0039 angleDelta.setY(120); 0040 break; 0041 case 5: 0042 angleDelta.setY(-120); 0043 break; 0044 case 6: 0045 angleDelta.setX(120); 0046 break; 0047 case 7: 0048 angleDelta.setX(-120); 0049 break; 0050 } 0051 0052 const Qt::MouseButtons buttons = x11ToQtMouseButtons(me->state); 0053 const Qt::KeyboardModifiers modifiers = x11ToQtKeyboardModifiers(me->state); 0054 0055 if (modifiers & Qt::AltModifier) { 0056 int x = angleDelta.x(); 0057 int y = angleDelta.y(); 0058 0059 angleDelta.setX(y); 0060 angleDelta.setY(x); 0061 // After Qt > 5.14 simplify to 0062 // angleDelta = angleDelta.transposed(); 0063 } 0064 0065 QWheelEvent ev(QPoint(me->event_x, me->event_y), QCursor::pos(), QPoint(), angleDelta, buttons, modifiers, Qt::NoScrollPhase, false); 0066 ev.setTimestamp(me->time); 0067 return m_effects->checkInputWindowEvent(&ev); 0068 } 0069 const Qt::MouseButton button = x11ToQtMouseButton(me->detail); 0070 Qt::MouseButtons buttons = x11ToQtMouseButtons(me->state); 0071 const QEvent::Type type = (eventType == XCB_BUTTON_PRESS) ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; 0072 if (type == QEvent::MouseButtonPress) { 0073 buttons |= button; 0074 } else { 0075 buttons &= ~button; 0076 } 0077 QMouseEvent ev(type, QPoint(me->event_x, me->event_y), QPoint(me->root_x, me->root_y), 0078 button, buttons, x11ToQtKeyboardModifiers(me->state)); 0079 ev.setTimestamp(me->time); 0080 return m_effects->checkInputWindowEvent(&ev); 0081 } 0082 } else if (eventType == XCB_MOTION_NOTIFY) { 0083 const auto *me = reinterpret_cast<xcb_motion_notify_event_t *>(event); 0084 if (m_window == me->event) { 0085 QMouseEvent ev(QEvent::MouseMove, QPoint(me->event_x, me->event_y), QPoint(me->root_x, me->root_y), 0086 Qt::NoButton, x11ToQtMouseButtons(me->state), x11ToQtKeyboardModifiers(me->state)); 0087 ev.setTimestamp(me->time); 0088 return m_effects->checkInputWindowEvent(&ev); 0089 } 0090 } 0091 return false; 0092 } 0093 0094 }