File patches.obscpio of Package kwin6

07070100200110000081A4000003E8000003E80000000165FA8A1F0000002F000001030000000500000000000000000000000F00000000patches/series0b2d8901ab086bf5119077911ba39f63b1bdecfe.patch
070701002000D3000081A4000003E8000003E80000000165FA8A1400002CA4000001030000000500000000000000000000003700000000patches/0b2d8901ab086bf5119077911ba39f63b1bdecfe.patchFrom 0b2d8901ab086bf5119077911ba39f63b1bdecfe Mon Sep 17 00:00:00 2001
From: Xaver Hugl <xaver.hugl@gmail.com>
Date: Tue, 12 Mar 2024 23:01:41 +0100
Subject: [PATCH] pointer input: handle warp events differently from absolute
 motion events

As Wayland doesn't have a warp event yet, before this commit, warps were
dealt with like normal absolute motion events. This trips up games though,
which don't deal with actual absolute motion events well. As a solution
to that, until an actual warp event is a thing, we send a motion event with
a position + a relative motion event with no motion

BUG: 458233
CCBUG: 482476
(cherry picked from commit 630ba5fab4b02c2b496553c79d4a315da9271b53)
---
 autotests/libinput/input_event_test.cpp |  2 +-
 src/input.cpp                           |  6 ++++-
 src/input_event.cpp                     |  3 ++-
 src/input_event.h                       |  8 ++++++-
 src/pointer_input.cpp                   | 30 +++++++++++++++----------
 src/pointer_input.h                     |  7 +++++-
 6 files changed, 39 insertions(+), 17 deletions(-)

diff --git a/autotests/libinput/input_event_test.cpp b/autotests/libinput/input_event_test.cpp
index ed2096e6a5d..d3ccb0d4560 100644
--- a/autotests/libinput/input_event_test.cpp
+++ b/autotests/libinput/input_event_test.cpp
@@ -53,7 +53,7 @@ void InputEventsTest::testInitMouseEvent()
     QFETCH(QEvent::Type, type);
     // now create our own event
     MouseEvent event(type, QPointF(100, 200), Qt::LeftButton, Qt::LeftButton | Qt::RightButton,
-                     Qt::ShiftModifier | Qt::ControlModifier, 300ms, QPointF(1, 2), QPointF(3, 4), &d);
+                     Qt::ShiftModifier | Qt::ControlModifier, 300ms, QPointF(1, 2), QPointF(3, 4), &d, false);
     // and verify the contract of QMouseEvent
     QCOMPARE(event.type(), type);
     QCOMPARE(event.globalPos(), QPoint(100, 200));
diff --git a/src/input.cpp b/src/input.cpp
index af75156fc0b..f633226df98 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -1786,7 +1786,11 @@ public:
         case QEvent::MouseMove: {
             seat->notifyPointerMotion(event->globalPosition());
             MouseEvent *e = static_cast<MouseEvent *>(event);
-            if (!e->delta().isNull()) {
+            // absolute motion events confuse games and Wayland doesn't have a warp event yet
+            // -> send a relative motion event with a zero delta to signal the warp instead
+            if (e->isWarp()) {
+                seat->relativePointerMotion(QPointF(0, 0), QPointF(0, 0), e->timestamp());
+            } else if (!e->delta().isNull()) {
                 seat->relativePointerMotion(e->delta(), e->deltaUnaccelerated(), e->timestamp());
             }
             break;
diff --git a/src/input_event.cpp b/src/input_event.cpp
index 9a4d3c5ba03..3eac2f96585 100644
--- a/src/input_event.cpp
+++ b/src/input_event.cpp
@@ -14,12 +14,13 @@ namespace KWin
 
 MouseEvent::MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button,
                        Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, std::chrono::microseconds timestamp,
-                       const QPointF &delta, const QPointF &deltaNonAccelerated, InputDevice *device)
+                       const QPointF &delta, const QPointF &deltaNonAccelerated, InputDevice *device, bool warp)
     : QMouseEvent(type, pos, pos, button, buttons, modifiers)
     , m_delta(delta)
     , m_deltaUnccelerated(deltaNonAccelerated)
     , m_timestamp(timestamp)
     , m_device(device)
+    , m_warp(warp)
 {
     setTimestamp(std::chrono::duration_cast<std::chrono::milliseconds>(timestamp).count());
 }
diff --git a/src/input_event.h b/src/input_event.h
index 416887e6364..60d1aea4118 100644
--- a/src/input_event.h
+++ b/src/input_event.h
@@ -23,7 +23,7 @@ class MouseEvent : public QMouseEvent
 public:
     explicit MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button, Qt::MouseButtons buttons,
                         Qt::KeyboardModifiers modifiers, std::chrono::microseconds timestamp,
-                        const QPointF &delta, const QPointF &deltaNonAccelerated, InputDevice *device);
+                        const QPointF &delta, const QPointF &deltaNonAccelerated, InputDevice *device, bool warp);
 
     QPointF delta() const
     {
@@ -65,6 +65,11 @@ public:
         m_nativeButton = button;
     }
 
+    bool isWarp() const
+    {
+        return m_warp;
+    }
+
 private:
     QPointF m_delta;
     QPointF m_deltaUnccelerated;
@@ -72,6 +77,7 @@ private:
     InputDevice *m_device;
     Qt::KeyboardModifiers m_modifiersRelevantForShortcuts = Qt::KeyboardModifiers();
     quint32 m_nativeButton = 0;
+    bool m_warp = false;
 };
 
 // TODO: Don't derive from QWheelEvent, this event is quite domain specific.
diff --git a/src/pointer_input.cpp b/src/pointer_input.cpp
index b6d34b33a25..1f31903f096 100644
--- a/src/pointer_input.cpp
+++ b/src/pointer_input.cpp
@@ -183,7 +183,7 @@ public:
         if (s_counter == 0) {
             if (!s_scheduledPositions.isEmpty()) {
                 const auto pos = s_scheduledPositions.takeFirst();
-                m_pointer->processMotionInternal(pos.pos, pos.delta, pos.deltaNonAccelerated, pos.time, nullptr);
+                m_pointer->processMotionInternal(pos.pos, pos.delta, pos.deltaNonAccelerated, pos.time, nullptr, pos.type);
             }
         }
     }
@@ -193,9 +193,9 @@ public:
         return s_counter > 0;
     }
 
-    static void schedulePosition(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time)
+    static void schedulePosition(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, PointerInputRedirection::MotionType type)
     {
-        s_scheduledPositions.append({pos, delta, deltaNonAccelerated, time});
+        s_scheduledPositions.append({pos, delta, deltaNonAccelerated, time, type});
     }
 
 private:
@@ -206,6 +206,7 @@ private:
         QPointF delta;
         QPointF deltaNonAccelerated;
         std::chrono::microseconds time;
+        PointerInputRedirection::MotionType type;
     };
     static QList<ScheduledPosition> s_scheduledPositions;
 
@@ -217,22 +218,27 @@ QList<PositionUpdateBlocker::ScheduledPosition> PositionUpdateBlocker::s_schedul
 
 void PointerInputRedirection::processMotionAbsolute(const QPointF &pos, std::chrono::microseconds time, InputDevice *device)
 {
-    processMotionInternal(pos, QPointF(), QPointF(), time, device);
+    processMotionInternal(pos, QPointF(), QPointF(), time, device, MotionType::Motion);
+}
+
+void PointerInputRedirection::processWarp(const QPointF &pos, std::chrono::microseconds time, InputDevice *device)
+{
+    processMotionInternal(pos, QPointF(), QPointF(), time, device, MotionType::Warp);
 }
 
 void PointerInputRedirection::processMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device)
 {
-    processMotionInternal(m_pos + delta, delta, deltaNonAccelerated, time, device);
+    processMotionInternal(m_pos + delta, delta, deltaNonAccelerated, time, device, MotionType::Motion);
 }
 
-void PointerInputRedirection::processMotionInternal(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device)
+void PointerInputRedirection::processMotionInternal(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device, MotionType type)
 {
     input()->setLastInputHandler(this);
     if (!inited()) {
         return;
     }
     if (PositionUpdateBlocker::isPositionBlocked()) {
-        PositionUpdateBlocker::schedulePosition(pos, delta, deltaNonAccelerated, time);
+        PositionUpdateBlocker::schedulePosition(pos, delta, deltaNonAccelerated, time, type);
         return;
     }
 
@@ -240,7 +246,7 @@ void PointerInputRedirection::processMotionInternal(const QPointF &pos, const QP
     updatePosition(pos);
     MouseEvent event(QEvent::MouseMove, m_pos, Qt::NoButton, m_qtButtons,
                      input()->keyboardModifiers(), time,
-                     delta, deltaNonAccelerated, device);
+                     delta, deltaNonAccelerated, device, type == MotionType::Warp);
     event.setModifiersRelevantForGlobalShortcuts(input()->modifiersRelevantForGlobalShortcuts());
 
     update();
@@ -268,7 +274,7 @@ void PointerInputRedirection::processButton(uint32_t button, InputRedirection::P
     updateButton(button, state);
 
     MouseEvent event(type, m_pos, buttonToQtMouseButton(button), m_qtButtons,
-                     input()->keyboardModifiers(), time, QPointF(), QPointF(), device);
+                     input()->keyboardModifiers(), time, QPointF(), QPointF(), device, false);
     event.setModifiersRelevantForGlobalShortcuts(input()->modifiersRelevantForGlobalShortcuts());
     event.setNativeButton(button);
 
@@ -664,7 +670,7 @@ void PointerInputRedirection::updatePointerConstraints()
                 m_locked = false;
                 disconnectLockedPointerAboutToBeUnboundConnection();
                 if (!(hint.x() < 0 || hint.y() < 0) && focus()) {
-                    processMotionAbsolute(focus()->mapFromLocal(hint), waylandServer()->seat()->timestamp());
+                    processWarp(focus()->mapFromLocal(hint), waylandServer()->seat()->timestamp());
                 }
             }
             return;
@@ -684,7 +690,7 @@ void PointerInputRedirection::updatePointerConstraints()
 
                 // When the resource finally goes away, reposition the cursor according to the hint
                 connect(lock, &LockedPointerV1Interface::destroyed, this, [this, globalHint]() {
-                    processMotionAbsolute(globalHint, waylandServer()->seat()->timestamp());
+                    processWarp(globalHint, waylandServer()->seat()->timestamp());
                 });
             });
             // TODO: connect to region change - is it needed at all? If the pointer is locked it's always in the region
@@ -779,7 +785,7 @@ void PointerInputRedirection::updateButton(uint32_t button, InputRedirection::Po
 void PointerInputRedirection::warp(const QPointF &pos)
 {
     if (supportsWarping()) {
-        processMotionAbsolute(pos, waylandServer()->seat()->timestamp());
+        processWarp(pos, waylandServer()->seat()->timestamp());
     }
 }
 
diff --git a/src/pointer_input.h b/src/pointer_input.h
index f1f980339ec..1ce58549be3 100644
--- a/src/pointer_input.h
+++ b/src/pointer_input.h
@@ -144,7 +144,12 @@ public:
     void processFrame(KWin::InputDevice *device = nullptr);
 
 private:
-    void processMotionInternal(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device);
+    void processWarp(const QPointF &pos, std::chrono::microseconds time, InputDevice *device = nullptr);
+    enum class MotionType {
+        Motion,
+        Warp
+    };
+    void processMotionInternal(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device, MotionType type);
     void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now) override;
 
     void focusUpdate(Window *focusOld, Window *focusNow) override;
-- 
GitLab

07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!
openSUSE Build Service is sponsored by