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"