Replacement class for QCursor
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.icc-effect-5.14.5
parent
9655c7b3cb
commit
f12cf0efba
|
@ -94,6 +94,7 @@ set(kwin_KDEINIT_SRCS
|
|||
dbusinterface.cpp
|
||||
client.cpp
|
||||
client_machine.cpp
|
||||
cursor.cpp
|
||||
tabgroup.cpp
|
||||
focuschain.cpp
|
||||
placement.cpp
|
||||
|
|
|
@ -90,7 +90,6 @@ Compositor::Compositor(QObject* workspace)
|
|||
connect(&unredirectTimer, SIGNAL(timeout()), SLOT(delayedCheckUnredirect()));
|
||||
connect(&compositeResetTimer, SIGNAL(timeout()), SLOT(restart()));
|
||||
connect(workspace, SIGNAL(configChanged()), SLOT(slotConfigChanged()));
|
||||
connect(&mousePollingTimer, SIGNAL(timeout()), SLOT(performMousePoll()));
|
||||
unredirectTimer.setSingleShot(true);
|
||||
compositeResetTimer.setSingleShot(true);
|
||||
nextPaintReference.invalidate(); // Initialize the timer
|
||||
|
@ -286,7 +285,6 @@ void Compositor::finish()
|
|||
delete m_scene;
|
||||
m_scene = NULL;
|
||||
compositeTimer.stop();
|
||||
mousePollingTimer.stop();
|
||||
repaints_region = QRegion();
|
||||
for (ClientList::ConstIterator it = Workspace::self()->clientList().constBegin();
|
||||
it != Workspace::self()->clientList().constEnd();
|
||||
|
@ -583,11 +581,6 @@ void Compositor::performCompositing()
|
|||
scheduleRepaint();
|
||||
}
|
||||
|
||||
void Compositor::performMousePoll()
|
||||
{
|
||||
Workspace::self()->checkCursorPos();
|
||||
}
|
||||
|
||||
bool Compositor::windowRepaintsPending() const
|
||||
{
|
||||
foreach (Toplevel * c, Workspace::self()->clientList())
|
||||
|
@ -649,16 +642,6 @@ void Compositor::setCompositeTimer()
|
|||
compositeTimer.start(qMin(padding, 250u), this); // force 4fps minimum
|
||||
}
|
||||
|
||||
void Compositor::startMousePolling()
|
||||
{
|
||||
mousePollingTimer.start(20); // 50Hz. TODO: How often do we really need to poll?
|
||||
}
|
||||
|
||||
void Compositor::stopMousePolling()
|
||||
{
|
||||
mousePollingTimer.stop();
|
||||
}
|
||||
|
||||
bool Compositor::isActive()
|
||||
{
|
||||
return !m_finishing && hasScene();
|
||||
|
|
|
@ -74,9 +74,6 @@ public:
|
|||
void addRepaint(const QRect& r);
|
||||
void addRepaint(const QRegion& r);
|
||||
void addRepaint(int x, int y, int w, int h);
|
||||
// Mouse polling
|
||||
void startMousePolling();
|
||||
void stopMousePolling();
|
||||
/**
|
||||
* Whether the Compositor is active. That is a Scene is present and the Compositor is
|
||||
* not shutting down itself.
|
||||
|
@ -281,7 +278,6 @@ private Q_SLOTS:
|
|||
void restart();
|
||||
void fallbackToXRenderCompositing();
|
||||
void performCompositing();
|
||||
void performMousePoll();
|
||||
void delayedCheckUnredirect();
|
||||
void slotConfigChanged();
|
||||
void releaseCompositorSelection();
|
||||
|
@ -309,7 +305,6 @@ private:
|
|||
uint vBlankInterval, fpsInterval;
|
||||
int m_xrrRefreshRate;
|
||||
QElapsedTimer nextPaintReference;
|
||||
QTimer mousePollingTimer;
|
||||
QRegion repaints_region;
|
||||
|
||||
QTimer unredirectTimer;
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
|
||||
#include "cursor.h"
|
||||
// kwin
|
||||
#include <kwinglobals.h>
|
||||
#include "utils.h"
|
||||
// Qt
|
||||
#include <QTimer>
|
||||
// Xlib
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <fixx11h.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
Cursor *Cursor::s_self = NULL;
|
||||
|
||||
Cursor::Cursor(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_mousePollingCounter(0)
|
||||
{
|
||||
}
|
||||
|
||||
Cursor::~Cursor()
|
||||
{
|
||||
s_self = NULL;
|
||||
}
|
||||
|
||||
Cursor *Cursor::create(QObject *parent)
|
||||
{
|
||||
Q_ASSERT(!s_self);
|
||||
s_self = new X11Cursor(parent);
|
||||
return s_self;
|
||||
}
|
||||
|
||||
QPoint Cursor::pos()
|
||||
{
|
||||
s_self->doGetPos();
|
||||
return s_self->m_pos;
|
||||
}
|
||||
|
||||
void Cursor::setPos(const QPoint &pos)
|
||||
{
|
||||
// first query the current pos to not warp to the already existing pos
|
||||
if (pos == Cursor::pos()) {
|
||||
return;
|
||||
}
|
||||
s_self->m_pos = pos;
|
||||
s_self->doSetPos();
|
||||
}
|
||||
|
||||
void Cursor::setPos(int x, int y)
|
||||
{
|
||||
Cursor::setPos(QPoint(x, y));
|
||||
}
|
||||
|
||||
xcb_cursor_t Cursor::getX11Cursor(Qt::CursorShape shape)
|
||||
{
|
||||
Q_UNUSED(shape)
|
||||
return XCB_CURSOR_NONE;
|
||||
}
|
||||
|
||||
xcb_cursor_t Cursor::x11Cursor(Qt::CursorShape shape)
|
||||
{
|
||||
return s_self->getX11Cursor(shape);
|
||||
}
|
||||
|
||||
void Cursor::doSetPos()
|
||||
{
|
||||
emit posChanged(m_pos);
|
||||
}
|
||||
|
||||
void Cursor::doGetPos()
|
||||
{
|
||||
}
|
||||
|
||||
void Cursor::updatePos(const QPoint &pos)
|
||||
{
|
||||
if (m_pos == pos) {
|
||||
return;
|
||||
}
|
||||
m_pos = pos;
|
||||
emit posChanged(m_pos);
|
||||
}
|
||||
|
||||
void Cursor::startMousePolling()
|
||||
{
|
||||
++m_mousePollingCounter;
|
||||
if (m_mousePollingCounter == 1) {
|
||||
doStartMousePolling();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::stopMousePolling()
|
||||
{
|
||||
Q_ASSERT(m_mousePollingCounter > 0);
|
||||
--m_mousePollingCounter;
|
||||
if (m_mousePollingCounter == 0) {
|
||||
doStopMousePolling();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::doStartMousePolling()
|
||||
{
|
||||
}
|
||||
|
||||
void Cursor::doStopMousePolling()
|
||||
{
|
||||
}
|
||||
|
||||
X11Cursor::X11Cursor(QObject *parent)
|
||||
: Cursor(parent)
|
||||
, m_timeStamp(XCB_TIME_CURRENT_TIME)
|
||||
, m_buttonMask(0)
|
||||
, m_resetTimeStampTimer(new QTimer(this))
|
||||
, m_mousePollingTimer(new QTimer(this))
|
||||
{
|
||||
m_resetTimeStampTimer->setSingleShot(true);
|
||||
connect(m_resetTimeStampTimer, SIGNAL(timeout()), SLOT(resetTimeStamp()));
|
||||
// TODO: How often do we really need to poll?
|
||||
m_mousePollingTimer->setInterval(100);
|
||||
connect(m_mousePollingTimer, SIGNAL(timeout()), SLOT(mousePolled()));
|
||||
}
|
||||
|
||||
X11Cursor::~X11Cursor()
|
||||
{
|
||||
}
|
||||
|
||||
void X11Cursor::doSetPos()
|
||||
{
|
||||
const QPoint &pos = currentPos();
|
||||
xcb_warp_pointer(connection(), XCB_WINDOW_NONE, rootWindow(), 0, 0, 0, 0, pos.x(), pos.y());
|
||||
// call default implementation to emit signal
|
||||
Cursor::doSetPos();
|
||||
}
|
||||
|
||||
void X11Cursor::doGetPos()
|
||||
{
|
||||
if (m_timeStamp != XCB_TIME_CURRENT_TIME &&
|
||||
m_timeStamp == QX11Info::appTime()) {
|
||||
// time stamps did not change, no need to query again
|
||||
return;
|
||||
}
|
||||
m_timeStamp = QX11Info::appTime();
|
||||
ScopedCPointer<xcb_query_pointer_reply_t> pointer(xcb_query_pointer_reply(connection(),
|
||||
xcb_query_pointer_unchecked(connection(), rootWindow()), NULL));
|
||||
if (!pointer) {
|
||||
return;
|
||||
}
|
||||
m_buttonMask = pointer->mask;
|
||||
updatePos(pointer->root_x, pointer->root_y);
|
||||
m_resetTimeStampTimer->start(0);
|
||||
}
|
||||
|
||||
void X11Cursor::resetTimeStamp()
|
||||
{
|
||||
m_timeStamp = XCB_TIME_CURRENT_TIME;
|
||||
}
|
||||
|
||||
void X11Cursor::doStartMousePolling()
|
||||
{
|
||||
m_mousePollingTimer->start();
|
||||
}
|
||||
|
||||
void X11Cursor::doStopMousePolling()
|
||||
{
|
||||
m_mousePollingTimer->stop();
|
||||
}
|
||||
|
||||
void X11Cursor::mousePolled()
|
||||
{
|
||||
const QPoint last = currentPos();
|
||||
const uint16_t lastMask = m_buttonMask;
|
||||
doGetPos(); // Update if needed
|
||||
if (last != currentPos() || lastMask != m_buttonMask) {
|
||||
emit mouseChanged(currentPos(), last,
|
||||
x11ToQtMouseButtons(m_buttonMask), x11ToQtMouseButtons(lastMask),
|
||||
x11ToQtKeyboardModifiers(m_buttonMask), x11ToQtKeyboardModifiers(lastMask));
|
||||
}
|
||||
}
|
||||
|
||||
xcb_cursor_t X11Cursor::getX11Cursor(Qt::CursorShape shape)
|
||||
{
|
||||
QHash<Qt::CursorShape, xcb_cursor_t>::const_iterator it = m_cursors.constFind(shape);
|
||||
if (it != m_cursors.constEnd()) {
|
||||
return it.value();
|
||||
}
|
||||
return createCursor(shape);
|
||||
}
|
||||
|
||||
xcb_cursor_t X11Cursor::createCursor(Qt::CursorShape shape)
|
||||
{
|
||||
const QByteArray name = cursorName(shape);
|
||||
if (name.isEmpty()) {
|
||||
return XCB_CURSOR_NONE;
|
||||
}
|
||||
// XCursor is an XLib only lib
|
||||
const char *theme = XcursorGetTheme(display());
|
||||
const int size = XcursorGetDefaultSize(display());
|
||||
XcursorImage *ximg = XcursorLibraryLoadImage(name.constData(), theme, size);
|
||||
if (!ximg) {
|
||||
return XCB_CURSOR_NONE;
|
||||
}
|
||||
xcb_cursor_t cursor = XcursorImageLoadCursor(display(), ximg);
|
||||
XcursorImageDestroy(ximg);
|
||||
m_cursors.insert(shape, cursor);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
QByteArray X11Cursor::cursorName(Qt::CursorShape shape) const
|
||||
{
|
||||
switch (shape) {
|
||||
case Qt::ArrowCursor:
|
||||
return QByteArray("left_ptr");
|
||||
case Qt::UpArrowCursor:
|
||||
return QByteArray("up_arrow");
|
||||
case Qt::CrossCursor:
|
||||
return QByteArray("cross");
|
||||
case Qt::WaitCursor:
|
||||
return QByteArray("wait");
|
||||
case Qt::IBeamCursor:
|
||||
return QByteArray("ibeam");
|
||||
case Qt::SizeVerCursor:
|
||||
return QByteArray("size_ver");
|
||||
case Qt::SizeHorCursor:
|
||||
return QByteArray("size_hor");
|
||||
case Qt::SizeBDiagCursor:
|
||||
return QByteArray("size_bdiag");
|
||||
case Qt::SizeFDiagCursor:
|
||||
return QByteArray("size_fdiag");
|
||||
case Qt::SizeAllCursor:
|
||||
return QByteArray("size_all");
|
||||
case Qt::SplitVCursor:
|
||||
return QByteArray("split_v");
|
||||
case Qt::SplitHCursor:
|
||||
return QByteArray("split_h");
|
||||
case Qt::PointingHandCursor:
|
||||
return QByteArray("pointing_hand");
|
||||
case Qt::ForbiddenCursor:
|
||||
return QByteArray("forbidden");
|
||||
case Qt::OpenHandCursor:
|
||||
return QByteArray("openhand");
|
||||
case Qt::ClosedHandCursor:
|
||||
return QByteArray("closedhand");
|
||||
case Qt::WhatsThisCursor:
|
||||
return QByteArray("whats_this");
|
||||
case Qt::BusyCursor:
|
||||
return QByteArray("left_ptr_watch");
|
||||
case Qt::DragMoveCursor:
|
||||
return QByteArray("dnd-move");
|
||||
case Qt::DragCopyCursor:
|
||||
return QByteArray("dnd-copy");
|
||||
case Qt::DragLinkCursor:
|
||||
return QByteArray("dnd-link");
|
||||
default:
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -0,0 +1,183 @@
|
|||
/********************************************************************
|
||||
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
|
17
effects.cpp
17
effects.cpp
|
@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "effectsadaptor.h"
|
||||
#include "deleted.h"
|
||||
#include "client.h"
|
||||
#include "cursor.h"
|
||||
#include "group.h"
|
||||
#include "scene_xrender.h"
|
||||
#include "scene_opengl.h"
|
||||
|
@ -205,7 +206,6 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
|
|||
, keyboard_grab_effect(NULL)
|
||||
, fullscreen_effect(0)
|
||||
, next_window_quad_type(EFFECT_QUAD_TYPE_START)
|
||||
, mouse_poll_ref_count(0)
|
||||
, m_compositor(compositor)
|
||||
, m_scene(scene)
|
||||
, m_screenLockerWatcher(new ScreenLockerWatcher(this))
|
||||
|
@ -225,7 +225,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
|
|||
connect(ws, SIGNAL(clientActivated(KWin::Client*)), this, SLOT(slotClientActivated(KWin::Client*)));
|
||||
connect(ws, SIGNAL(deletedRemoved(KWin::Deleted*)), this, SLOT(slotDeletedRemoved(KWin::Deleted*)));
|
||||
connect(vds, SIGNAL(countChanged(uint,uint)), SIGNAL(numberDesktopsChanged(uint)));
|
||||
connect(ws, SIGNAL(mouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)),
|
||||
connect(Cursor::self(), SIGNAL(mouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)),
|
||||
SIGNAL(mouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)));
|
||||
connect(ws, SIGNAL(propertyNotify(long)), this, SLOT(slotPropertyNotify(long)));
|
||||
connect(ws, SIGNAL(activityAdded(QString)), SIGNAL(activityAdded(QString)));
|
||||
|
@ -675,17 +675,12 @@ void* EffectsHandlerImpl::getProxy(QString name)
|
|||
|
||||
void EffectsHandlerImpl::startMousePolling()
|
||||
{
|
||||
if (!mouse_poll_ref_count) // Start timer if required
|
||||
m_compositor->startMousePolling();
|
||||
mouse_poll_ref_count++;
|
||||
Cursor::self()->startMousePolling();
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::stopMousePolling()
|
||||
{
|
||||
assert(mouse_poll_ref_count);
|
||||
mouse_poll_ref_count--;
|
||||
if (!mouse_poll_ref_count) // Stop timer if required
|
||||
m_compositor->stopMousePolling();
|
||||
Cursor::self()->stopMousePolling();
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::hasKeyboardGrab() const
|
||||
|
@ -1161,7 +1156,7 @@ xcb_window_t EffectsHandlerImpl::createInputWindow(Effect* e, int x, int y, int
|
|||
const uint32_t values[] = {
|
||||
true,
|
||||
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION,
|
||||
static_cast<uint32_t>(cursor.handle())
|
||||
Cursor::x11Cursor(cursor.shape())
|
||||
};
|
||||
xcb_create_window(connection(), 0, win, rootWindow(), x, y, w, h, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
|
||||
XCB_COPY_FROM_PARENT, mask, values);
|
||||
|
@ -1276,7 +1271,7 @@ void EffectsHandlerImpl::checkInputWindowStacking()
|
|||
|
||||
QPoint EffectsHandlerImpl::cursorPos() const
|
||||
{
|
||||
return Workspace::self()->cursorPos();
|
||||
return Cursor::pos();
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::reserveElectricBorder(ElectricBorder border, Effect *effect)
|
||||
|
|
|
@ -227,7 +227,6 @@ protected:
|
|||
QMultiMap< int, EffectPair > effect_order;
|
||||
QHash< long, int > registered_atoms;
|
||||
int next_window_quad_type;
|
||||
int mouse_poll_ref_count;
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotEffectsQueried();
|
||||
|
|
|
@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kglobal.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
|
||||
#include "cursor.h"
|
||||
#include "notifications.h"
|
||||
#include <QX11Info>
|
||||
#include "rules.h"
|
||||
|
@ -656,7 +657,7 @@ void Client::embedClient(Window w, const XWindowAttributes& attr)
|
|||
0, // back_pixmap
|
||||
0, // border_pixel
|
||||
static_cast<uint32_t>(attr.colormap), // colormap
|
||||
static_cast<uint32_t>(QCursor(Qt::ArrowCursor).handle()) // cursor
|
||||
Cursor::x11Cursor(Qt::ArrowCursor)
|
||||
};
|
||||
|
||||
const uint32_t cw_mask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
|
||||
|
|
|
@ -32,6 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// KWin
|
||||
#include "atoms.h"
|
||||
#include "client.h"
|
||||
#include "cursor.h"
|
||||
#include "effects.h"
|
||||
#include "utils.h"
|
||||
#include "workspace.h"
|
||||
|
@ -255,7 +256,7 @@ void Edge::switchDesktop(const QPoint &cursorPos)
|
|||
}
|
||||
vds->setCurrent(desktop);
|
||||
if (vds->current() != oldDesktop) {
|
||||
QCursor::setPos(pos);
|
||||
Cursor::setPos(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +277,7 @@ void Edge::pushCursorBack(const QPoint &cursorPos)
|
|||
if (isBottom()) {
|
||||
y -= distance.height();
|
||||
}
|
||||
QCursor::setPos(x, y);
|
||||
Cursor::setPos(x, y);
|
||||
}
|
||||
|
||||
void Edge::setGeometry(const QRect &geometry)
|
||||
|
@ -503,14 +504,16 @@ void WindowBasedEdge::doGeometryUpdate()
|
|||
void WindowBasedEdge::doStartApproaching()
|
||||
{
|
||||
m_approachWindow.unmap();
|
||||
connect(edges(), SIGNAL(mousePollingTimerEvent(QPoint)), SLOT(updateApproaching(QPoint)));
|
||||
edges()->startMousePolling();
|
||||
Cursor *cursor = Cursor::self();
|
||||
connect(cursor, SIGNAL(posChanged(QPoint)), SLOT(updateApproaching(QPoint)));
|
||||
cursor->startMousePolling();
|
||||
}
|
||||
|
||||
void WindowBasedEdge::doStopApproaching()
|
||||
{
|
||||
disconnect(edges(), SIGNAL(mousePollingTimerEvent(QPoint)), this, SLOT(updateApproaching(QPoint)));
|
||||
edges()->stopMousePolling();
|
||||
Cursor *cursor = Cursor::self();
|
||||
disconnect(cursor, SIGNAL(posChanged(QPoint)), this, SLOT(updateApproaching(QPoint)));
|
||||
cursor->stopMousePolling();
|
||||
m_approachWindow.map();
|
||||
}
|
||||
|
||||
|
@ -555,10 +558,7 @@ ScreenEdges::ScreenEdges(QObject *parent)
|
|||
, m_actionBottom(ElectricActionNone)
|
||||
, m_actionBottomLeft(ElectricActionNone)
|
||||
, m_actionLeft(ElectricActionNone)
|
||||
, m_mousePolling(0)
|
||||
, m_mousePollingTimer(new QTimer(this))
|
||||
{
|
||||
connect(m_mousePollingTimer, SIGNAL(timeout()), SLOT(performMousePoll()));
|
||||
}
|
||||
|
||||
ScreenEdges::~ScreenEdges()
|
||||
|
@ -1047,28 +1047,6 @@ void ScreenEdges::ensureOnTop()
|
|||
Xcb::restackWindowsWithRaise(windows());
|
||||
}
|
||||
|
||||
void ScreenEdges::startMousePolling()
|
||||
{
|
||||
m_mousePolling++;
|
||||
if (m_mousePolling == 1) {
|
||||
m_mousePollingTimer->start(100); // TODO: How often do we really need to poll?
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenEdges::stopMousePolling()
|
||||
{
|
||||
m_mousePolling--;
|
||||
if (m_mousePolling == 0) {
|
||||
m_mousePollingTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenEdges::performMousePoll()
|
||||
{
|
||||
Workspace::self()->checkCursorPos();
|
||||
emit mousePollingTimerEvent(Workspace::self()->cursorPos());
|
||||
}
|
||||
|
||||
QVector< xcb_window_t > ScreenEdges::windows() const
|
||||
{
|
||||
QVector<xcb_window_t> wins;
|
||||
|
|
|
@ -282,8 +282,6 @@ public:
|
|||
ElectricBorderAction actionBottom() const;
|
||||
ElectricBorderAction actionBottomLeft() const;
|
||||
ElectricBorderAction actionLeft() const;
|
||||
void startMousePolling();
|
||||
void stopMousePolling();
|
||||
|
||||
/**
|
||||
* Singleton getter for this manager.
|
||||
|
@ -317,12 +315,8 @@ Q_SIGNALS:
|
|||
* @c 0.0 meaning far away from the border, @c 1.0 in trigger distance.
|
||||
**/
|
||||
void approaching(ElectricBorder border, qreal factor, const QRect &geometry);
|
||||
void mousePollingTimerEvent(QPoint cursorPos);
|
||||
void checkBlocking();
|
||||
|
||||
private Q_SLOTS:
|
||||
void performMousePoll();
|
||||
|
||||
private:
|
||||
enum { ElectricDisabled = 0, ElectricMoveOnly = 1, ElectricAlways = 2 };
|
||||
void setDesktopSwitching(bool enable);
|
||||
|
@ -353,8 +347,6 @@ private:
|
|||
ElectricBorderAction m_actionBottom;
|
||||
ElectricBorderAction m_actionBottomLeft;
|
||||
ElectricBorderAction m_actionLeft;
|
||||
int m_mousePolling;
|
||||
QTimer *m_mousePollingTimer;
|
||||
|
||||
static ScreenEdges *s_self;
|
||||
};
|
||||
|
|
|
@ -49,6 +49,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <stdio.h>
|
||||
|
||||
#include "atoms.h"
|
||||
#include "cursor.h"
|
||||
#include "notifications.h"
|
||||
#include "workspace.h"
|
||||
|
||||
|
@ -325,7 +326,7 @@ void ungrabXKeyboard()
|
|||
|
||||
QPoint cursorPos()
|
||||
{
|
||||
return Workspace::self()->cursorPos();
|
||||
return Cursor::self()->pos();
|
||||
}
|
||||
|
||||
// converting between X11 mouse/keyboard state mask and Qt button/keyboard states
|
||||
|
|
|
@ -52,6 +52,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "tabbox.h"
|
||||
#endif
|
||||
#include "atoms.h"
|
||||
#include "cursor.h"
|
||||
#include "placement.h"
|
||||
#include "notifications.h"
|
||||
#include "outline.h"
|
||||
|
@ -159,6 +160,9 @@ Workspace::Workspace(bool restore)
|
|||
Extensions::init();
|
||||
Xcb::Extensions::self();
|
||||
|
||||
// start the cursor support
|
||||
Cursor::create(this);
|
||||
|
||||
// PluginMgr needs access to the config file, so we need to wait for it for finishing
|
||||
reparseConfigFuture.waitForFinished();
|
||||
options->loadConfig();
|
||||
|
@ -1829,60 +1833,6 @@ void Workspace::slotBlockShortcuts(int data)
|
|||
(*it)->updateMouseGrab();
|
||||
}
|
||||
|
||||
// Optimized version of QCursor::pos() that tries to avoid X roundtrips
|
||||
// by updating the value only when the X timestamp changes.
|
||||
static QPoint last_cursor_pos;
|
||||
static int last_buttons = 0;
|
||||
static Time last_cursor_timestamp = CurrentTime;
|
||||
static QTimer* last_cursor_timer;
|
||||
|
||||
QPoint Workspace::cursorPos() const
|
||||
{
|
||||
if (last_cursor_timestamp == CurrentTime ||
|
||||
last_cursor_timestamp != QX11Info::appTime()) {
|
||||
last_cursor_timestamp = QX11Info::appTime();
|
||||
Window root;
|
||||
Window child;
|
||||
int root_x, root_y, win_x, win_y;
|
||||
uint state;
|
||||
XQueryPointer(display(), rootWindow(), &root, &child,
|
||||
&root_x, &root_y, &win_x, &win_y, &state);
|
||||
last_cursor_pos = QPoint(root_x, root_y);
|
||||
last_buttons = state;
|
||||
if (last_cursor_timer == NULL) {
|
||||
Workspace* ws = const_cast<Workspace*>(this);
|
||||
last_cursor_timer = new QTimer(ws);
|
||||
last_cursor_timer->setSingleShot(true);
|
||||
connect(last_cursor_timer, SIGNAL(timeout()), ws, SLOT(resetCursorPosTime()));
|
||||
}
|
||||
last_cursor_timer->start(0);
|
||||
}
|
||||
return last_cursor_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Workspace::resetCursorPosTime()
|
||||
{
|
||||
last_cursor_timestamp = CurrentTime;
|
||||
}
|
||||
|
||||
void Workspace::checkCursorPos()
|
||||
{
|
||||
QPoint last = last_cursor_pos;
|
||||
int lastb = last_buttons;
|
||||
cursorPos(); // Update if needed
|
||||
if (last != last_cursor_pos || lastb != last_buttons) {
|
||||
emit mouseChanged(last_cursor_pos, last,
|
||||
x11ToQtMouseButtons(last_buttons), x11ToQtMouseButtons(lastb),
|
||||
x11ToQtKeyboardModifiers(last_buttons), x11ToQtKeyboardModifiers(lastb));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Outline* Workspace::outline()
|
||||
{
|
||||
return m_outline;
|
||||
|
|
|
@ -379,8 +379,6 @@ public:
|
|||
bool globalShortcutsDisabled() const;
|
||||
void disableGlobalShortcuts(bool disable);
|
||||
void disableGlobalShortcutsForClient(bool disable);
|
||||
QPoint cursorPos() const;
|
||||
void checkCursorPos();
|
||||
|
||||
void sessionSaveStarted();
|
||||
void sessionSaveDone();
|
||||
|
@ -505,7 +503,6 @@ private slots:
|
|||
void slotMenuHidden(qulonglong wid);
|
||||
void slotClearMenus();
|
||||
#endif
|
||||
void resetCursorPosTime();
|
||||
void updateCurrentActivity(const QString &new_activity);
|
||||
void slotActivityRemoved(const QString &activity);
|
||||
void slotActivityAdded(const QString &activity);
|
||||
|
@ -534,9 +531,6 @@ signals:
|
|||
void groupAdded(KWin::Group*);
|
||||
void unmanagedAdded(KWin::Unmanaged*);
|
||||
void deletedRemoved(KWin::Deleted*);
|
||||
void mouseChanged(const QPoint& pos, const QPoint& oldpos,
|
||||
Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
|
||||
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers);
|
||||
void propertyNotify(long a);
|
||||
void configChanged();
|
||||
void reinitializeCompositing();
|
||||
|
|
Loading…
Reference in New Issue