Commit 2e297113 authored by Roman Gilg's avatar Roman Gilg

Rework InputDeviceHandler focus tracking

Summary:
This patch aims at improving the Toplevel, internal window and decoration
focus tracking.

In detail the goals are:
* Clean tracking of beneath and focus Toplevel as well as decoration and
internal windows. Splitting this up in well defined sub routines.
* Minimal find Toplevel operations on window stack.
* Reduce code duplication in pointer and touch child classes.
* Reuse tracking in drag operations.
* Allow direct usage of Wayland input interfaces for decoration and internal
windows in the future.
* Update touch focus on external events like VD switches correctly.

Test Plan: Manually and existing autotests.

Reviewers: #kwin

Subscribers: kwin, zzag

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D15595
parent eab71a8a
......@@ -836,8 +836,8 @@ void DecorationInputTest::testTouchEvents()
QCOMPARE(hoverMoveSpy.count(), 3);
QCOMPARE(hoverLeaveSpy.count(), 1);
kwinApp()->platform()->touchUp(0, timestamp++);
QCOMPARE(hoverMoveSpy.count(), 4);
QCOMPARE(hoverLeaveSpy.count(), 1);
QCOMPARE(hoverMoveSpy.count(), 3);
QCOMPARE(hoverLeaveSpy.count(), 2);
}
void DecorationInputTest::testTooltipDoesntEatKeyEvents_data()
......
......@@ -230,11 +230,11 @@ void InternalWindowTest::testEnterLeave()
quint32 timestamp = 1;
kwinApp()->platform()->pointerMotion(QPoint(50, 50), timestamp++);
QTRY_COMPARE(enterSpy.count(), 1);
QTRY_COMPARE(moveSpy.count(), 1);
kwinApp()->platform()->pointerMotion(QPoint(60, 50), timestamp++);
QTRY_COMPARE(moveSpy.count(), 1);
QCOMPARE(moveSpy.first().first().toPoint(), QPoint(60, 50));
QTRY_COMPARE(moveSpy.count(), 2);
QCOMPARE(moveSpy[1].first().toPoint(), QPoint(60, 50));
kwinApp()->platform()->pointerMotion(QPoint(101, 50), timestamp++);
QTRY_COMPARE(leaveSpy.count(), 1);
......
......@@ -232,7 +232,7 @@ void TestPointerConstraints::testConfinedPointer()
QVERIFY(unconfinedSpy2.isValid());
// activate it again, this confines again
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->window().data()));
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->focus().data()));
QVERIFY(confinedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), true);
......@@ -241,7 +241,7 @@ void TestPointerConstraints::testConfinedPointer()
QVERIFY(unconfinedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), false);
// activate it again, this confines again
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->window().data()));
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->focus().data()));
QVERIFY(confinedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), true);
......@@ -272,7 +272,7 @@ void TestPointerConstraints::testConfinedPointer()
confinedPointer.reset(nullptr);
Test::flushWaylandConnection();
QSignalSpy constraintsChangedSpy(input()->pointer()->window()->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged);
QSignalSpy constraintsChangedSpy(input()->pointer()->focus()->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged);
QVERIFY(constraintsChangedSpy.isValid());
QVERIFY(constraintsChangedSpy.wait());
......@@ -348,7 +348,7 @@ void TestPointerConstraints::testLockedPointer()
QVERIFY(lockedSpy2.isValid());
// activate the client again, this should lock again
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->window().data()));
workspace()->activateClient(static_cast<AbstractClient*>(input()->pointer()->focus().data()));
QVERIFY(lockedSpy2.wait());
QCOMPARE(input()->pointer()->isConstrained(), true);
......@@ -361,7 +361,7 @@ void TestPointerConstraints::testLockedPointer()
lockedPointer.reset(nullptr);
Test::flushWaylandConnection();
QSignalSpy constraintsChangedSpy(input()->pointer()->window()->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged);
QSignalSpy constraintsChangedSpy(input()->pointer()->focus()->surface(), &KWayland::Server::SurfaceInterface::pointerConstraintsChanged);
QVERIFY(constraintsChangedSpy.isValid());
QVERIFY(constraintsChangedSpy.wait());
......
......@@ -963,7 +963,7 @@ void PointerInputTest::testCursorImage()
// move cursor to center of window, this should first set a null pointer, so we still show old cursor
Cursor::setPos(window->geometry().center());
QCOMPARE(p->window().data(), window);
QCOMPARE(p->focus().data(), window);
QCOMPARE(p->cursorImage(), fallbackCursor);
QVERIFY(enteredSpy.wait());
......@@ -1018,7 +1018,7 @@ void PointerInputTest::testCursorImage()
// move cursor somewhere else, should reset to fallback cursor
Cursor::setPos(window->geometry().bottomLeft() + QPoint(20, 20));
QVERIFY(p->window().isNull());
QVERIFY(p->focus().isNull());
QVERIFY(!p->cursorImage().isNull());
QCOMPARE(p->cursorImage(), fallbackCursor);
}
......
......@@ -115,7 +115,7 @@ void TestWindowSelection::testSelectOnWindowPointer()
QVERIFY(client);
QVERIFY(keyboardEnteredSpy.wait());
KWin::Cursor::setPos(client->geometry().center());
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
QVERIFY(pointerEnteredSpy.wait());
Toplevel *selectedWindow = nullptr;
......@@ -142,11 +142,11 @@ void TestWindowSelection::testSelectOnWindowPointer()
// should not have ended the mode
QCOMPARE(input()->isSelectingWindow(), true);
QVERIFY(!selectedWindow);
QVERIFY(input()->pointer()->window().isNull());
QVERIFY(input()->pointer()->focus().isNull());
// updating the pointer should not change anything
input()->pointer()->update();
QVERIFY(input()->pointer()->window().isNull());
QVERIFY(input()->pointer()->focus().isNull());
// updating keyboard should also not change
input()->keyboard()->update();
......@@ -160,7 +160,7 @@ void TestWindowSelection::testSelectOnWindowPointer()
kwinApp()->platform()->pointerButtonReleased(BTN_LEFT, timestamp++);
QCOMPARE(input()->isSelectingWindow(), false);
QCOMPARE(selectedWindow, client);
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
// should give back keyboard and pointer
QVERIFY(pointerEnteredSpy.wait());
if (keyboardEnteredSpy.count() != 2) {
......@@ -240,7 +240,7 @@ void TestWindowSelection::testSelectOnWindowKeyboard()
kwinApp()->platform()->keyboardKeyPressed(key, timestamp++);
QCOMPARE(input()->isSelectingWindow(), false);
QCOMPARE(selectedWindow, client);
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
// should give back keyboard and pointer
QVERIFY(pointerEnteredSpy.wait());
if (keyboardEnteredSpy.count() != 2) {
......@@ -336,7 +336,7 @@ void TestWindowSelection::testCancelOnWindowPointer()
QVERIFY(client);
QVERIFY(keyboardEnteredSpy.wait());
KWin::Cursor::setPos(client->geometry().center());
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
QVERIFY(pointerEnteredSpy.wait());
Toplevel *selectedWindow = nullptr;
......@@ -363,7 +363,7 @@ void TestWindowSelection::testCancelOnWindowPointer()
kwinApp()->platform()->pointerButtonReleased(BTN_RIGHT, timestamp++);
QCOMPARE(input()->isSelectingWindow(), false);
QVERIFY(!selectedWindow);
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
// should give back keyboard and pointer
QVERIFY(pointerEnteredSpy.wait());
if (keyboardEnteredSpy.count() != 2) {
......@@ -395,7 +395,7 @@ void TestWindowSelection::testCancelOnWindowKeyboard()
QVERIFY(client);
QVERIFY(keyboardEnteredSpy.wait());
KWin::Cursor::setPos(client->geometry().center());
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
QVERIFY(pointerEnteredSpy.wait());
Toplevel *selectedWindow = nullptr;
......@@ -421,7 +421,7 @@ void TestWindowSelection::testCancelOnWindowKeyboard()
kwinApp()->platform()->keyboardKeyPressed(KEY_ESC, timestamp++);
QCOMPARE(input()->isSelectingWindow(), false);
QVERIFY(!selectedWindow);
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
// should give back keyboard and pointer
QVERIFY(pointerEnteredSpy.wait());
if (keyboardEnteredSpy.count() != 2) {
......@@ -454,7 +454,7 @@ void TestWindowSelection::testSelectPointPointer()
QVERIFY(client);
QVERIFY(keyboardEnteredSpy.wait());
KWin::Cursor::setPos(client->geometry().center());
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
QVERIFY(pointerEnteredSpy.wait());
QPoint point;
......@@ -488,11 +488,11 @@ void TestWindowSelection::testSelectPointPointer()
// should not have ended the mode
QCOMPARE(input()->isSelectingWindow(), true);
QCOMPARE(point, QPoint());
QVERIFY(input()->pointer()->window().isNull());
QVERIFY(input()->pointer()->focus().isNull());
// updating the pointer should not change anything
input()->pointer()->update();
QVERIFY(input()->pointer()->window().isNull());
QVERIFY(input()->pointer()->focus().isNull());
// updating keyboard should also not change
input()->keyboard()->update();
......@@ -506,7 +506,7 @@ void TestWindowSelection::testSelectPointPointer()
kwinApp()->platform()->pointerButtonReleased(BTN_LEFT, timestamp++);
QCOMPARE(input()->isSelectingWindow(), false);
QCOMPARE(point, input()->globalPointer().toPoint());
QCOMPARE(input()->pointer()->window().data(), client);
QCOMPARE(input()->pointer()->focus().data(), client);
// should give back keyboard and pointer
QVERIFY(pointerEnteredSpy.wait());
if (keyboardEnteredSpy.count() != 2) {
......
This diff is collapsed.
......@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2018 Roman Gilg <subdiff@gmail.com>
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
......@@ -365,50 +366,91 @@ protected:
void passToWaylandServer(QKeyEvent *event);
};
class InputDeviceHandler : public QObject
class KWIN_EXPORT InputDeviceHandler : public QObject
{
Q_OBJECT
public:
virtual ~InputDeviceHandler();
virtual void init();
QPointer<Toplevel> window() const {
return m_window;
void update();
/**
* @brief First Toplevel currently at the position of the input device
* according to the stacking order.
* @return Toplevel* at device position.
*/
QPointer<Toplevel> at() const {
return m_at;
}
/**
* @brief Toplevel currently having pointer input focus (this might
* be different from the Toplevel at the position of the pointer).
* @return Toplevel* with pointer focus.
*/
QPointer<Toplevel> focus() const {
return m_focus.focus;
}
/**
* @brief The Decoration currently receiving events.
* @return decoration with pointer focus.
**/
QPointer<Decoration::DecoratedClientImpl> decoration() const {
return m_decoration;
return m_focus.decoration;
}
/**
* @brief The internal window currently receiving events.
* @return QWindow with pointer focus.
**/
QPointer<QWindow> internalWindow() const {
return m_internalWindow;
return m_focus.internalWindow;
}
virtual QPointF position() const = 0;
void setFocus(Toplevel *toplevel);
void setDecoration(QPointer<Decoration::DecoratedClientImpl> decoration);
void setInternalWindow(QWindow *window);
Q_SIGNALS:
void atChanged(Toplevel *old, Toplevel *now);
void decorationChanged();
void internalWindowChanged();
protected:
explicit InputDeviceHandler(InputRedirection *parent);
void updateDecoration(Toplevel *t, const QPointF &pos);
void updateInternalWindow(const QPointF &pos);
void setWindow(QPointer<Toplevel> window = QPointer<Toplevel>()) {
m_window = window;
virtual void cleanupInternalWindow(QWindow *old, QWindow *now) = 0;
virtual void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now) = 0;
virtual void focusUpdate(Toplevel *old, Toplevel *now) = 0;
virtual bool focusUpdatesBlocked() {
return false;
}
void clearDecoration() {
m_decoration.clear();
inline bool inited() const {
return m_inited;
}
void clearInternalWindow() {
m_internalWindow.clear();
inline void setInited(bool set) {
m_inited = set;
}
private:
/**
* @brief The Toplevel which currently receives events
*/
QPointer<Toplevel> m_window;
/**
* @brief The Decoration which currently receives events.
**/
QPointer<Decoration::DecoratedClientImpl> m_decoration;
QPointer<QWindow> m_internalWindow;
bool setAt(Toplevel *toplevel);
void updateFocus();
bool updateDecoration();
void updateInternalWindow(QWindow *window);
QWindow* findInternalWindow(const QPoint &pos) const;
QPointer<Toplevel> m_at;
struct {
QPointer<Toplevel> focus;
QPointer<Decoration::DecoratedClientImpl> decoration;
QPointer<QWindow> internalWindow;
} m_focus;
bool m_inited = false;
};
inline
......
This diff is collapsed.
......@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2018 Roman Gilg <subdiff@gmail.com>
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
......@@ -64,7 +65,6 @@ public:
void init();
void update();
void updateAfterScreenChange();
bool supportsWarping() const;
void warp(const QPointF &pos);
......@@ -75,6 +75,7 @@ public:
Qt::MouseButtons buttons() const {
return m_qtButtons;
}
bool areButtonsPressed() const;
QImage cursorImage() const;
QPoint cursorHotSpot() const;
......@@ -92,6 +93,8 @@ public:
return m_confined || m_locked;
}
bool focusUpdatesBlocked() override;
/**
* @internal
*/
......@@ -142,6 +145,13 @@ public:
void processPinchGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr);
private:
void cleanupInternalWindow(QWindow *old, QWindow *now) override;
void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now) override;
void focusUpdate(Toplevel *focusOld, Toplevel *focusNow) override;
QPointF position() const override;
void updateOnStartMoveResize();
void updateToReset();
void updatePosition(const QPointF &pos);
......@@ -152,14 +162,12 @@ private:
void disconnectLockedPointerAboutToBeUnboundConnection();
void disconnectPointerConstraintsConnection();
void breakPointerConstraints(KWayland::Server::SurfaceInterface *surface);
bool areButtonsPressed() const;
CursorImage *m_cursor;
bool m_inited = false;
bool m_supportsWarping;
QPointF m_pos;
QHash<uint32_t, InputRedirection::PointerButtonState> m_buttons;
Qt::MouseButtons m_qtButtons;
QMetaObject::Connection m_windowGeometryConnection;
QMetaObject::Connection m_focusGeometryConnection;
QMetaObject::Connection m_internalWindowConnection;
QMetaObject::Connection m_constraintsConnection;
QMetaObject::Connection m_constraintsActivatedConnection;
......
......@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2018 Roman Gilg <subdiff@gmail.com>
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
......@@ -20,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "touch_input.h"
#include "abstract_client.h"
#include "input.h"
#include "pointer_input.h"
#include "input_event_spy.h"
#include "toplevel.h"
#include "wayland_server.h"
......@@ -47,8 +49,9 @@ TouchInputRedirection::~TouchInputRedirection() = default;
void TouchInputRedirection::init()
{
Q_ASSERT(!m_inited);
m_inited = true;
Q_ASSERT(!inited());
setInited(true);
InputDeviceHandler::init();
if (waylandServer()->hasScreenLockerIntegration()) {
connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this,
......@@ -59,73 +62,83 @@ void TouchInputRedirection::init()
}
);
}
connect(workspace(), &QObject::destroyed, this, [this] { m_inited = false; });
connect(waylandServer(), &QObject::destroyed, this, [this] { m_inited = false; });
connect(workspace(), &QObject::destroyed, this, [this] { setInited(false); });
connect(waylandServer(), &QObject::destroyed, this, [this] { setInited(false); });
}
void TouchInputRedirection::update(const QPointF &pos)
bool TouchInputRedirection::focusUpdatesBlocked()
{
if (!m_inited) {
return;
if (!inited()) {
return true;
}
if (m_windowUpdatedInCycle) {
return;
return true;
}
m_windowUpdatedInCycle = true;
// TODO: handle pointer grab aka popups
Toplevel *t = input()->findToplevel(pos.toPoint());
auto oldWindow = window();
updateInternalWindow(pos);
if (!internalWindow()) {
updateDecoration(t, pos);
} else {
// TODO: send hover leave to decoration
if (decoration()) {
decoration()->client()->leaveEvent();
}
clearDecoration();
if (m_touches > 0) {
// first touch defines focus
return true;
}
if (decoration() || internalWindow()) {
t = nullptr;
} else if (!decoration()) {
m_decorationId = -1;
} else if (!internalWindow()) {
m_internalId = -1;
return false;
}
void TouchInputRedirection::focusUpdate(Toplevel *focusOld, Toplevel *focusNow)
{
// TODO: handle pointer grab aka popups
if (AbstractClient *ac = qobject_cast<AbstractClient*>(focusOld)) {
ac->leaveEvent();
}
if (!oldWindow.isNull() && t == oldWindow.data()) {
return;
disconnect(m_focusGeometryConnection);
m_focusGeometryConnection = QMetaObject::Connection();
if (AbstractClient *ac = qobject_cast<AbstractClient*>(focusNow)) {
ac->enterEvent(m_lastPosition.toPoint());
workspace()->updateFocusMousePosition(m_lastPosition.toPoint());
}
auto seat = waylandServer()->seat();
// disconnect old surface
if (oldWindow) {
disconnect(m_windowGeometryConnection);
m_windowGeometryConnection = QMetaObject::Connection();
}
if (t && t->surface()) {
// FIXME: add input transformation API to KWayland::Server::SeatInterface for touch input
seat->setFocusedTouchSurface(t->surface(), -1 * t->inputTransformation().map(t->pos()) + t->pos());
m_windowGeometryConnection = connect(t, &Toplevel::geometryChanged, this,
[this] {
if (window().isNull()) {
return;
}
auto seat = waylandServer()->seat();
if (window().data()->surface() != seat->focusedTouchSurface()) {
return;
}
auto t = window().data();
seat->setFocusedTouchSurfacePosition(-1 * t->inputTransformation().map(t->pos()) + t->pos());
}
);
} else {
if (!focusNow || !focusNow->surface() || decoration()) {
// no new surface or internal window or on decoration -> cleanup
seat->setFocusedTouchSurface(nullptr);
t = nullptr;
}
if (!t) {
setWindow();
return;
}
setWindow(t);
// TODO: invalidate pointer focus?
// FIXME: add input transformation API to KWayland::Server::SeatInterface for touch input
seat->setFocusedTouchSurface(focusNow->surface(), -1 * focusNow->inputTransformation().map(focusNow->pos()) + focusNow->pos());
m_focusGeometryConnection = connect(focusNow, &Toplevel::geometryChanged, this,
[this] {
if (focus().isNull()) {
return;
}
auto seat = waylandServer()->seat();
if (focus().data()->surface() != seat->focusedTouchSurface()) {
return;
}
seat->setFocusedTouchSurfacePosition(-1 * focus()->inputTransformation().map(focus()->pos()) + focus()->pos());
}
);
}
void TouchInputRedirection::cleanupInternalWindow(QWindow *old, QWindow *now)
{
Q_UNUSED(old);
Q_UNUSED(now);
// nothing to do
}
void TouchInputRedirection::cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now)
{
Q_UNUSED(now);
if (old) {
// send leave event to old decoration
QHoverEvent event(QEvent::HoverLeave, QPointF(), QPointF());
QCoreApplication::instance()->sendEvent(old->decoration(), &event);
}
}
void TouchInputRedirection::insertId(quint32 internalId, qint32 kwaylandId)
......@@ -150,10 +163,15 @@ void TouchInputRedirection::removeId(quint32 internalId)
void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device)
{
Q_UNUSED(device)
if (!m_inited) {
if (!inited()) {
return;
}
m_lastPosition = pos;
m_windowUpdatedInCycle = false;
if (m_touches == 0) {
update();
}
m_touches++;
input()->processSpies(std::bind(&InputEventSpy::touchDown, std::placeholders::_1, id, pos, time));
input()->processFilters(std::bind(&InputEventFilter::touchDown, std::placeholders::_1, id, pos, time));
m_windowUpdatedInCycle = false;
......@@ -162,21 +180,26 @@ void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 t
void TouchInputRedirection::processUp(qint32 id, quint32 time, LibInput::Device *device)
{
Q_UNUSED(device)
if (!m_inited) {
if (!inited()) {
return;
}
m_windowUpdatedInCycle = false;
input()->processSpies(std::bind(&InputEventSpy::touchUp, std::placeholders::_1, id, time));
input()->processFilters(std::bind(&InputEventFilter::touchUp, std::placeholders::_1, id, time));
m_windowUpdatedInCycle = false;
m_touches--;
if (m_touches == 0) {
update();
}
}
void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device)
{
Q_UNUSED(device)
if (!m_inited) {
if (!inited()) {
return;
}
m_lastPosition = pos;
m_windowUpdatedInCycle = false;
input()->processSpies(std::bind(&InputEventSpy::touchMotion, std::placeholders::_1, id, pos, time));
input()->processFilters(std::bind(&InputEventFilter::touchMotion, std::placeholders::_1, id, pos, time));
......@@ -185,7 +208,7 @@ void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32
void TouchInputRedirection::cancel()
{
if (!m_inited) {
if (!inited()) {
return;
}
waylandServer()->seat()->cancelTouchSequence();
......@@ -194,7 +217,7 @@ void TouchInputRedirection::cancel()
void TouchInputRedirection::frame()
{
if (!m_inited) {
if (!inited()) {
return;
}
waylandServer()->seat()->touchFrame();
......
......@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2018 Roman Gilg <subdiff@gmail.com>
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
......@@ -49,7 +50,7 @@ public:
explicit TouchInputRedirection(InputRedirection *parent);
virtual ~TouchInputRedirection();
void update(const QPointF &pos = QPointF());
bool focusUpdatesBlocked() override;
void init();
void processDown(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device = nullptr);
......@@ -75,7 +76,16 @@ public:
return m_internalId;
}
QPointF position() const override {
return m_lastPosition;
}
private:
void cleanupInternalWindow(QWindow *old, QWindow *now) override;
void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now) override;
void focusUpdate(Toplevel *focusOld, Toplevel *focusNow) override;
bool m_inited = false;
qint32 m_decorationId = -1;
qint32 m_internalId = -1;
......@@ -83,8 +93,11 @@ private:
* external/kwayland
**/
QHash<qint32, qint32> m_idMapper;
QMetaObject::Connection m_windowGeometryConnection;
QMetaObject::Connection m_focusGeometryConnection;
bool m_windowUpdatedInCycle = false;
QPointF m_lastPosition;
int m_touches = 0;
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment