You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
9.8 KiB
306 lines
9.8 KiB
/******************************************************************** |
|
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 |
|
// kwin |
|
#include <kwinglobals.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 KWIN_EXPORT Cursor : public QObject |
|
{ |
|
Q_OBJECT |
|
public: |
|
virtual ~Cursor(); |
|
void startMousePolling(); |
|
void stopMousePolling(); |
|
/** |
|
* @brief Enables tracking changes of cursor images. |
|
* |
|
* After enabling cursor change tracking the signal @link cursorChanged will be emitted |
|
* whenever a change to the cursor image is recognized. |
|
* |
|
* Use @link stopCursorTracking to no longer emit this signal. Note: the signal will be |
|
* emitted until each call of this method has been matched with a call to stopCursorTracking. |
|
* |
|
* This tracking is not about pointer position tracking. |
|
* @see stopCursorTracking |
|
* @see cursorChanged |
|
*/ |
|
void startCursorTracking(); |
|
/** |
|
* @brief Disables tracking changes of cursor images. |
|
* |
|
* Only call after using @link startCursorTracking. |
|
* |
|
* @see startCursorTracking |
|
*/ |
|
void stopCursorTracking(); |
|
/** |
|
* @internal |
|
* |
|
* Called from X11 event handler. |
|
*/ |
|
void notifyCursorChanged(uint32_t serial); |
|
|
|
/** |
|
* @brief The name of the currently used Cursor theme. |
|
* |
|
* @return const QString& |
|
*/ |
|
const QString &themeName() const; |
|
/** |
|
* @brief The size of the currently used Cursor theme. |
|
* |
|
* @return int |
|
*/ |
|
int themeSize() const; |
|
/** |
|
* @brief The name of a cursor shape in the theme. |
|
* |
|
* @param shape The cursor for which the name needs to be known. |
|
* @return QByteArray |
|
*/ |
|
QByteArray cursorName(Qt::CursorShape shape) const; |
|
|
|
/** |
|
* 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 xcb_cursor_t x11Cursor(Qt::CursorShape shape); |
|
/** |
|
* Notice: if available always use the Qt::CursorShape variant to avoid cache duplicates for |
|
* ambiguous cursor names in the non existing cursor name spcification |
|
**/ |
|
static xcb_cursor_t x11Cursor(const QByteArray &name); |
|
|
|
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); |
|
/** |
|
* @brief Signal emitted when the cursor image changes. |
|
* |
|
* To enable these signals use @link startCursorTracking. |
|
* |
|
* @param serial The serial number of the new selected cursor. |
|
* @see startCursorTracking |
|
* @see stopCursorTracking |
|
*/ |
|
void cursorChanged(uint32_t serial); |
|
void themeChanged(); |
|
|
|
protected: |
|
/** |
|
* 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); |
|
/** |
|
* 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(const QByteArray &name); |
|
/** |
|
* 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(); |
|
/** |
|
* Called from @link startCursorTracking when cursor image tracking gets activated. Inheriting class needs |
|
* to overwrite to enable platform specific code for the tracking. |
|
*/ |
|
virtual void doStartCursorTracking(); |
|
/** |
|
* Called from @link stopCursorTracking when cursor image tracking gets deactivated. Inheriting class needs |
|
* to overwrite to disable platform specific code for the tracking. |
|
*/ |
|
virtual void doStopCursorTracking(); |
|
bool isCursorTracking() const; |
|
/** |
|
* 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 Q_SLOTS: |
|
void loadThemeSettings(); |
|
void slotKGlobalSettingsNotifyChange(int type, int arg); |
|
|
|
private: |
|
void updateTheme(const QString &name, int size); |
|
void loadThemeFromKConfig(); |
|
QPoint m_pos; |
|
int m_mousePollingCounter; |
|
int m_cursorTrackingCounter; |
|
QString m_themeName; |
|
int m_themeSize; |
|
|
|
KWIN_SINGLETON(Cursor) |
|
}; |
|
|
|
class X11Cursor : public Cursor |
|
{ |
|
Q_OBJECT |
|
public: |
|
virtual ~X11Cursor(); |
|
protected: |
|
virtual xcb_cursor_t getX11Cursor(Qt::CursorShape shape); |
|
xcb_cursor_t getX11Cursor(const QByteArray &name) override; |
|
virtual void doSetPos(); |
|
virtual void doGetPos(); |
|
virtual void doStartMousePolling(); |
|
virtual void doStopMousePolling(); |
|
virtual void doStartCursorTracking(); |
|
virtual void doStopCursorTracking(); |
|
|
|
private Q_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(const QByteArray &name); |
|
QHash<QByteArray, xcb_cursor_t > m_cursors; |
|
xcb_timestamp_t m_timeStamp; |
|
uint16_t m_buttonMask; |
|
QTimer *m_resetTimeStampTimer; |
|
QTimer *m_mousePollingTimer; |
|
friend class Cursor; |
|
}; |
|
|
|
/** |
|
* @brief Implementation using the InputRedirection framework to get pointer positions. |
|
* |
|
* Does not support warping of cursor. |
|
* |
|
*/ |
|
class InputRedirectionCursor : public Cursor |
|
{ |
|
Q_OBJECT |
|
public: |
|
virtual ~InputRedirectionCursor(); |
|
protected: |
|
virtual void doSetPos(); |
|
virtual void doStartCursorTracking(); |
|
virtual void doStopCursorTracking(); |
|
private Q_SLOTS: |
|
void slotPosChanged(const QPointF &pos); |
|
void slotPointerButtonChanged(); |
|
void slotModifiersChanged(Qt::KeyboardModifiers mods, Qt::KeyboardModifiers oldMods); |
|
private: |
|
explicit InputRedirectionCursor(QObject *parent); |
|
Qt::MouseButtons m_oldButtons; |
|
Qt::MouseButtons m_currentButtons; |
|
friend class Cursor; |
|
}; |
|
|
|
inline const QPoint &Cursor::currentPos() const |
|
{ |
|
return m_pos; |
|
} |
|
|
|
inline void Cursor::updatePos(int x, int y) |
|
{ |
|
updatePos(QPoint(x, y)); |
|
} |
|
|
|
inline const QString& Cursor::themeName() const |
|
{ |
|
return m_themeName; |
|
} |
|
|
|
inline int Cursor::themeSize() const |
|
{ |
|
return m_themeSize; |
|
} |
|
|
|
inline bool Cursor::isCursorTracking() const |
|
{ |
|
return m_cursorTrackingCounter > 0; |
|
} |
|
|
|
} |
|
|
|
#endif // KWIN_CURSOR_H
|
|
|