wayland: Fix handling of synthetic touch cancel events
In case the compositor wants to cancel a touch sequence, we need to ignore subsequent touch motion and touch up events until a new sequence is initiated by the user. Previously, it was implicitly handled by clearing the mapping table between the touch slots and touch ids generated by kwayland-server.
This commit is contained in:
parent
8f2520e00e
commit
d23dab7be9
4 changed files with 20 additions and 21 deletions
|
@ -275,8 +275,6 @@ void TouchInputTest::testTouchPointCount()
|
||||||
kwinApp()->platform()->touchUp(1, timestamp++);
|
kwinApp()->platform()->touchUp(1, timestamp++);
|
||||||
QCOMPARE(kwinApp()->platform()->touchPointCount(), 2);
|
QCOMPARE(kwinApp()->platform()->touchPointCount(), 2);
|
||||||
|
|
||||||
kwinApp()->platform()->cancelTouchSequence();
|
|
||||||
QCOMPARE(kwinApp()->platform()->touchPointCount(), 1);
|
|
||||||
kwinApp()->platform()->cancelTouchSequence();
|
kwinApp()->platform()->cancelTouchSequence();
|
||||||
QCOMPARE(kwinApp()->platform()->touchPointCount(), 0);
|
QCOMPARE(kwinApp()->platform()->touchPointCount(), 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2303,7 +2303,7 @@ void InputRedirection::setupLibInput()
|
||||||
connect(conn, &LibInput::Connection::touchDown, m_touch, &TouchInputRedirection::processDown);
|
connect(conn, &LibInput::Connection::touchDown, m_touch, &TouchInputRedirection::processDown);
|
||||||
connect(conn, &LibInput::Connection::touchUp, m_touch, &TouchInputRedirection::processUp);
|
connect(conn, &LibInput::Connection::touchUp, m_touch, &TouchInputRedirection::processUp);
|
||||||
connect(conn, &LibInput::Connection::touchMotion, m_touch, &TouchInputRedirection::processMotion);
|
connect(conn, &LibInput::Connection::touchMotion, m_touch, &TouchInputRedirection::processMotion);
|
||||||
connect(conn, &LibInput::Connection::touchCanceled, m_touch, &TouchInputRedirection::processCancel);
|
connect(conn, &LibInput::Connection::touchCanceled, m_touch, &TouchInputRedirection::cancel);
|
||||||
connect(conn, &LibInput::Connection::touchFrame, m_touch, &TouchInputRedirection::frame);
|
connect(conn, &LibInput::Connection::touchFrame, m_touch, &TouchInputRedirection::frame);
|
||||||
auto handleSwitchEvent = [this] (SwitchEvent::State state, quint32 time, quint64 timeMicroseconds, LibInput::Device *device) {
|
auto handleSwitchEvent = [this] (SwitchEvent::State state, quint32 time, quint64 timeMicroseconds, LibInput::Device *device) {
|
||||||
SwitchEvent event(state, time, timeMicroseconds, device);
|
SwitchEvent event(state, time, timeMicroseconds, device);
|
||||||
|
@ -2496,7 +2496,7 @@ void InputRedirection::processTouchMotion(qint32 id, const QPointF &pos, quint32
|
||||||
|
|
||||||
void InputRedirection::cancelTouchSequence()
|
void InputRedirection::cancelTouchSequence()
|
||||||
{
|
{
|
||||||
m_touch->processCancel();
|
m_touch->cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRedirection::cancelTouch()
|
void InputRedirection::cancelTouch()
|
||||||
|
|
|
@ -66,7 +66,7 @@ bool TouchInputRedirection::focusUpdatesBlocked()
|
||||||
if (waylandServer()->seat()->isDragTouch()) {
|
if (waylandServer()->seat()->isDragTouch()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (m_touches > 1) {
|
if (m_activeTouchPoints.count() > 1) {
|
||||||
// first touch defines focus
|
// first touch defines focus
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,8 @@ bool TouchInputRedirection::focusUpdatesBlocked()
|
||||||
|
|
||||||
bool TouchInputRedirection::positionValid() const
|
bool TouchInputRedirection::positionValid() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_touches >= 0);
|
|
||||||
// we can only determine a position with at least one touch point
|
// we can only determine a position with at least one touch point
|
||||||
return m_touches;
|
return !m_activeTouchPoints.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TouchInputRedirection::focusUpdate(Toplevel *focusOld, Toplevel *focusNow)
|
void TouchInputRedirection::focusUpdate(Toplevel *focusOld, Toplevel *focusNow)
|
||||||
|
@ -144,8 +143,8 @@ void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 t
|
||||||
}
|
}
|
||||||
m_lastPosition = pos;
|
m_lastPosition = pos;
|
||||||
m_windowUpdatedInCycle = false;
|
m_windowUpdatedInCycle = false;
|
||||||
m_touches++;
|
m_activeTouchPoints.insert(id);
|
||||||
if (m_touches == 1) {
|
if (m_activeTouchPoints.count() == 1) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
input()->processSpies(std::bind(&InputEventSpy::touchDown, std::placeholders::_1, id, pos, time));
|
input()->processSpies(std::bind(&InputEventSpy::touchDown, std::placeholders::_1, id, pos, time));
|
||||||
|
@ -159,12 +158,14 @@ void TouchInputRedirection::processUp(qint32 id, quint32 time, LibInput::Device
|
||||||
if (!inited()) {
|
if (!inited()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!m_activeTouchPoints.remove(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_windowUpdatedInCycle = false;
|
m_windowUpdatedInCycle = false;
|
||||||
input()->processSpies(std::bind(&InputEventSpy::touchUp, std::placeholders::_1, id, time));
|
input()->processSpies(std::bind(&InputEventSpy::touchUp, std::placeholders::_1, id, time));
|
||||||
input()->processFilters(std::bind(&InputEventFilter::touchUp, std::placeholders::_1, id, time));
|
input()->processFilters(std::bind(&InputEventFilter::touchUp, std::placeholders::_1, id, time));
|
||||||
m_windowUpdatedInCycle = false;
|
m_windowUpdatedInCycle = false;
|
||||||
m_touches--;
|
if (m_activeTouchPoints.count() == 0) {
|
||||||
if (m_touches == 0) {
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,6 +176,9 @@ void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32
|
||||||
if (!inited()) {
|
if (!inited()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!m_activeTouchPoints.contains(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_lastPosition = pos;
|
m_lastPosition = pos;
|
||||||
m_windowUpdatedInCycle = false;
|
m_windowUpdatedInCycle = false;
|
||||||
input()->processSpies(std::bind(&InputEventSpy::touchMotion, std::placeholders::_1, id, pos, time));
|
input()->processSpies(std::bind(&InputEventSpy::touchMotion, std::placeholders::_1, id, pos, time));
|
||||||
|
@ -182,17 +186,16 @@ void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32
|
||||||
m_windowUpdatedInCycle = false;
|
m_windowUpdatedInCycle = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TouchInputRedirection::processCancel()
|
|
||||||
{
|
|
||||||
m_touches--;
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TouchInputRedirection::cancel()
|
void TouchInputRedirection::cancel()
|
||||||
{
|
{
|
||||||
if (!inited()) {
|
if (!inited()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If the touch sequence is artificially cancelled by the compositor, touch motion and touch
|
||||||
|
// up events will be silently ignored and won't be passed down through the event filter chain.
|
||||||
|
// If the touch sequence is cancelled because we received a TOUCH_CANCEL event from libinput,
|
||||||
|
// the compositor will not receive any TOUCH_MOTION or TOUCH_UP events for that slot.
|
||||||
|
m_activeTouchPoints.clear();
|
||||||
waylandServer()->seat()->cancelTouchSequence();
|
waylandServer()->seat()->cancelTouchSequence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ public:
|
||||||
void processDown(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device = nullptr);
|
void processDown(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device = nullptr);
|
||||||
void processUp(qint32 id, quint32 time, LibInput::Device *device = nullptr);
|
void processUp(qint32 id, quint32 time, LibInput::Device *device = nullptr);
|
||||||
void processMotion(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device = nullptr);
|
void processMotion(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device = nullptr);
|
||||||
void processCancel();
|
|
||||||
void cancel();
|
void cancel();
|
||||||
void frame();
|
void frame();
|
||||||
|
|
||||||
|
@ -68,7 +67,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int touchPointCount() const {
|
int touchPointCount() const {
|
||||||
return m_touches;
|
return m_activeTouchPoints.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -77,14 +76,13 @@ private:
|
||||||
|
|
||||||
void focusUpdate(Toplevel *focusOld, Toplevel *focusNow) override;
|
void focusUpdate(Toplevel *focusOld, Toplevel *focusNow) override;
|
||||||
|
|
||||||
|
QSet<qint32> m_activeTouchPoints;
|
||||||
bool m_inited = false;
|
bool m_inited = false;
|
||||||
qint32 m_decorationId = -1;
|
qint32 m_decorationId = -1;
|
||||||
qint32 m_internalId = -1;
|
qint32 m_internalId = -1;
|
||||||
QMetaObject::Connection m_focusGeometryConnection;
|
QMetaObject::Connection m_focusGeometryConnection;
|
||||||
bool m_windowUpdatedInCycle = false;
|
bool m_windowUpdatedInCycle = false;
|
||||||
QPointF m_lastPosition;
|
QPointF m_lastPosition;
|
||||||
|
|
||||||
int m_touches = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue