f12cf0efba
With Qt5 QCursor does no longer provide ::handle() which was used to set a cursor on a native XWindow for which we do not have a QWidget. Also KWin has had for quite some time an optimized version to get the cursor position without doing XQueryPointer each time ::pos() is called. These two features are merged into a new class Cursor providing more or less the same API as QCursor. In addition the new class provides a facility to perform mouse polling replacing the implementations in Compositor and ScreenEdges. For more information about the new class see the documentation for the new class in cursor.h.
183 lines
5.9 KiB
C++
183 lines
5.9 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*********************************************************************/
|
|
#ifndef KWIN_CURSOR_H
|
|
#define KWIN_CURSOR_H
|
|
// Qt
|
|
#include <QHash>
|
|
#include <QObject>
|
|
#include <QPoint>
|
|
// xcb
|
|
#include <xcb/xcb.h>
|
|
|
|
class QTimer;
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
/**
|
|
* @short Replacement for QCursor.
|
|
*
|
|
* This class provides a similar API to QCursor and should be preferred inside KWin. It allows to
|
|
* get the position and warp the mouse cursor with static methods just like QCursor. It also provides
|
|
* the possibility to get an X11 cursor for a Qt::CursorShape - a functionality lost in Qt 5's QCursor
|
|
* implementation.
|
|
*
|
|
* In addition the class provides a mouse polling facility as required by e.g. Effects and ScreenEdges
|
|
* and emits signals when the mouse position changes. In opposite to QCursor this class is a QObject
|
|
* and cannot be constructed. Instead it provides a singleton getter, though the most important
|
|
* methods are wrapped in a static method, just like QCursor.
|
|
*
|
|
* The actual implementation is split into two parts: a system independent interface and a windowing
|
|
* system specific subclass. So far only an X11 backend is implemented which uses query pointer to
|
|
* fetch the position and warp pointer to set the position. It uses a timer based mouse polling and
|
|
* can provide X11 cursors through the XCursor library.
|
|
**/
|
|
class Cursor : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
virtual ~Cursor();
|
|
void startMousePolling();
|
|
void stopMousePolling();
|
|
|
|
/**
|
|
* Returns the current cursor position. This method does an update of the mouse position if
|
|
* needed. It's save to call it multiple times.
|
|
*
|
|
* Implementing subclasses should prefer to use @link currentPos which is not performing a check
|
|
* for update.
|
|
**/
|
|
static QPoint pos();
|
|
/**
|
|
* Warps the mouse cursor to new @p pos.
|
|
**/
|
|
static void setPos(const QPoint &pos);
|
|
static void setPos(int x, int y);
|
|
static Cursor *self();
|
|
static xcb_cursor_t x11Cursor(Qt::CursorShape shape);
|
|
|
|
/**
|
|
* @internal
|
|
* Factory method
|
|
**/
|
|
static Cursor *create(QObject *parent);
|
|
Q_SIGNALS:
|
|
void posChanged(QPoint pos);
|
|
void mouseChanged(const QPoint& pos, const QPoint& oldpos,
|
|
Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
|
|
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers);
|
|
|
|
protected:
|
|
Cursor(QObject *parent);
|
|
/**
|
|
* Called from @link x11Cursor to actually retrieve the X11 cursor. Base implementation returns
|
|
* a null cursor, an implementing subclass should implement this method if it can provide X11
|
|
* mouse cursors.
|
|
**/
|
|
virtual xcb_cursor_t getX11Cursor(Qt::CursorShape shape);
|
|
/**
|
|
* Performs the actual warping of the cursor.
|
|
**/
|
|
virtual void doSetPos();
|
|
/**
|
|
* Called from @link pos() to allow syncing the internal position with the underlying
|
|
* system's cursor position.
|
|
**/
|
|
virtual void doGetPos();
|
|
/**
|
|
* Called from @link startMousePolling when the mouse polling gets activated. Base implementation
|
|
* does nothing, inheriting classes can overwrite to e.g. start a timer.
|
|
**/
|
|
virtual void doStartMousePolling();
|
|
/**
|
|
* Called from @link stopMousePolling when the mouse polling gets deactivated. Base implementation
|
|
* does nothing, inheriting classes can overwrite to e.g. stop a timer.
|
|
**/
|
|
virtual void doStopMousePolling();
|
|
/**
|
|
* Provides the actual internal cursor position to inheriting classes. If an inheriting class needs
|
|
* access to the cursor position this method should be used instead of the static @link pos, as
|
|
* the static method syncs with the underlying system's cursor.
|
|
**/
|
|
const QPoint ¤tPos() const;
|
|
/**
|
|
* Updates the internal position to @p pos without warping the pointer as
|
|
* @link setPos does.
|
|
**/
|
|
void updatePos(const QPoint &pos);
|
|
void updatePos(int x, int y);
|
|
|
|
private:
|
|
QPoint m_pos;
|
|
int m_mousePollingCounter;
|
|
|
|
static Cursor *s_self;
|
|
};
|
|
|
|
class X11Cursor : public Cursor
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
virtual ~X11Cursor();
|
|
protected:
|
|
virtual xcb_cursor_t getX11Cursor(Qt::CursorShape shape);
|
|
virtual void doSetPos();
|
|
virtual void doGetPos();
|
|
virtual void doStartMousePolling();
|
|
virtual void doStopMousePolling();
|
|
|
|
private slots:
|
|
/**
|
|
* Because of QTimer's and the impossibility to get events for all mouse
|
|
* movements (at least I haven't figured out how) the position needs
|
|
* to be also refetched after each return to the event loop.
|
|
*/
|
|
void resetTimeStamp();
|
|
void mousePolled();
|
|
private:
|
|
X11Cursor(QObject *parent);
|
|
xcb_cursor_t createCursor(Qt::CursorShape shape);
|
|
QByteArray cursorName(Qt::CursorShape shape) const;
|
|
QHash<Qt::CursorShape, xcb_cursor_t > m_cursors;
|
|
xcb_timestamp_t m_timeStamp;
|
|
uint16_t m_buttonMask;
|
|
QTimer *m_resetTimeStampTimer;
|
|
QTimer *m_mousePollingTimer;
|
|
friend class Cursor;
|
|
};
|
|
|
|
inline Cursor *Cursor::self()
|
|
{
|
|
return s_self;
|
|
}
|
|
|
|
inline const QPoint &Cursor::currentPos() const
|
|
{
|
|
return m_pos;
|
|
}
|
|
|
|
inline void Cursor::updatePos(int x, int y)
|
|
{
|
|
updatePos(QPoint(x, y));
|
|
}
|
|
|
|
}
|
|
|
|
#endif // KWIN_CURSOR_H
|