File indexing completed on 2024-11-10 04:56:34
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "x11_standalone_cursor.h" 0010 #include "input.h" 0011 #include "keyboard_input.h" 0012 #include "utils/common.h" 0013 #include "utils/xcbutils.h" 0014 #include "x11_standalone_xfixes_cursor_event_filter.h" 0015 0016 #include <QAbstractEventDispatcher> 0017 #include <QTimer> 0018 0019 namespace KWin 0020 { 0021 0022 X11Cursor::X11Cursor(bool xInputSupport) 0023 : Cursor() 0024 , m_timeStamp(XCB_TIME_CURRENT_TIME) 0025 , m_buttonMask(0) 0026 , m_hasXInput(xInputSupport) 0027 , m_needsPoll(false) 0028 { 0029 Cursors::self()->setMouse(this); 0030 m_resetTimeStampTimer.setSingleShot(true); 0031 connect(&m_resetTimeStampTimer, &QTimer::timeout, this, &X11Cursor::resetTimeStamp); 0032 // TODO: How often do we really need to poll? 0033 m_mousePollingTimer.setInterval(50); 0034 connect(&m_mousePollingTimer, &QTimer::timeout, this, &X11Cursor::mousePolled); 0035 0036 if (m_hasXInput) { 0037 connect(qApp->eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, &X11Cursor::aboutToBlock); 0038 } 0039 0040 #ifndef KCMRULES 0041 connect(kwinApp(), &Application::workspaceCreated, this, [this]() { 0042 if (Xcb::Extensions::self()->isFixesAvailable()) { 0043 m_xfixesFilter = std::make_unique<XFixesCursorEventFilter>(this); 0044 } 0045 }); 0046 #endif 0047 } 0048 0049 X11Cursor::~X11Cursor() 0050 { 0051 } 0052 0053 void X11Cursor::doSetPos() 0054 { 0055 const QPointF &pos = currentPos(); 0056 xcb_warp_pointer(connection(), XCB_WINDOW_NONE, rootWindow(), 0, 0, 0, 0, pos.x(), pos.y()); 0057 // call default implementation to emit signal 0058 Cursor::doSetPos(); 0059 } 0060 0061 void X11Cursor::doGetPos() 0062 { 0063 if (m_timeStamp != XCB_TIME_CURRENT_TIME && m_timeStamp == xTime()) { 0064 // time stamps did not change, no need to query again 0065 return; 0066 } 0067 m_timeStamp = xTime(); 0068 Xcb::Pointer pointer(rootWindow()); 0069 if (pointer.isNull()) { 0070 return; 0071 } 0072 m_buttonMask = pointer->mask; 0073 updatePos(QPointF(pointer->root_x, pointer->root_y)); 0074 m_resetTimeStampTimer.start(0); 0075 } 0076 0077 void X11Cursor::resetTimeStamp() 0078 { 0079 m_timeStamp = XCB_TIME_CURRENT_TIME; 0080 } 0081 0082 void X11Cursor::aboutToBlock() 0083 { 0084 if (m_needsPoll) { 0085 mousePolled(); 0086 m_needsPoll = false; 0087 } 0088 } 0089 0090 void X11Cursor::doStartMousePolling() 0091 { 0092 if (!m_hasXInput) { 0093 m_mousePollingTimer.start(); 0094 } 0095 } 0096 0097 void X11Cursor::doStopMousePolling() 0098 { 0099 if (!m_hasXInput) { 0100 m_mousePollingTimer.stop(); 0101 } 0102 } 0103 0104 void X11Cursor::doStartCursorTracking() 0105 { 0106 xcb_xfixes_select_cursor_input(connection(), rootWindow(), XCB_XFIXES_CURSOR_NOTIFY_MASK_DISPLAY_CURSOR); 0107 } 0108 0109 void X11Cursor::doStopCursorTracking() 0110 { 0111 xcb_xfixes_select_cursor_input(connection(), rootWindow(), 0); 0112 } 0113 0114 void X11Cursor::mousePolled() 0115 { 0116 static QPointF lastPos = currentPos(); 0117 static uint16_t lastMask = m_buttonMask; 0118 doGetPos(); // Update if needed 0119 if (lastPos != currentPos() || lastMask != m_buttonMask) { 0120 Q_EMIT mouseChanged(currentPos(), lastPos, 0121 x11ToQtMouseButtons(m_buttonMask), x11ToQtMouseButtons(lastMask), 0122 x11ToQtKeyboardModifiers(m_buttonMask), x11ToQtKeyboardModifiers(lastMask)); 0123 lastPos = currentPos(); 0124 lastMask = m_buttonMask; 0125 } 0126 } 0127 0128 void X11Cursor::notifyCursorChanged() 0129 { 0130 if (!isCursorTracking()) { 0131 // cursor change tracking is currently disabled, so don't emit signal 0132 return; 0133 } 0134 Q_EMIT cursorChanged(); 0135 } 0136 0137 } 0138 0139 #include "moc_x11_standalone_cursor.cpp"