From ad7a826ea13656bae19ad17dc812bcc8f3e6501c Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Fri, 19 Feb 2021 12:32:35 +0100 Subject: [PATCH] Drag'n'drop: only activate clients after still hover BUG: 395368 --- src/input.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/input.cpp b/src/input.cpp index 1b88d65b9e..d22a95e5ce 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -1871,9 +1871,17 @@ public: QHash m_cursorByTool; }; -class DragAndDropInputFilter : public InputEventFilter +class DragAndDropInputFilter : public QObject, public InputEventFilter { + Q_OBJECT public: + DragAndDropInputFilter() + { + m_raiseTimer.setSingleShot(true); + m_raiseTimer.setInterval(250); + connect(&m_raiseTimer, &QTimer::timeout, this, &DragAndDropInputFilter::raiseDragTarget); + } + bool pointerEvent(QMouseEvent *event, quint32 nativeButton) override { auto seat = waylandServer()->seat(); if (!seat->isDragPointer()) { @@ -1904,14 +1912,21 @@ public: if (t) { // TODO: consider decorations if (t->surface() != seat->dragSurface()) { - if (AbstractClient *c = qobject_cast(t)) { - workspace()->activateClient(c); + if ((m_dragTarget = qobject_cast(t))) { + workspace()->takeActivity(m_dragTarget, Workspace::ActivityFlag::ActivityFocus); + m_raiseTimer.start(); } seat->setDragTarget(t->surface(), t->inputTransformation()); } + if ((pos - m_lastPos).manhattanLength() > 10) { + m_lastPos = pos; + // reset timer to delay raising the window + m_raiseTimer.start(); + } } else { // no window at that place, if we have a surface we need to reset seat->setDragTarget(nullptr); + m_dragTarget = nullptr; } break; } @@ -1920,6 +1935,7 @@ public: seat->notifyPointerFrame(); break; case QEvent::MouseButtonRelease: + raiseDragTarget(); seat->notifyPointerButton(nativeButton, KWaylandServer::PointerButtonState::Released); seat->notifyPointerFrame(); break; @@ -1943,6 +1959,7 @@ public: } seat->setTimestamp(time); seat->notifyTouchDown(id, pos); + m_lastPos = pos; return true; } bool touchMotion(qint32 id, const QPointF &pos, quint32 time) override { @@ -1968,14 +1985,21 @@ public: if (Toplevel *t = input()->findToplevel(pos.toPoint())) { // TODO: consider decorations if (t->surface() != seat->dragSurface()) { - if (AbstractClient *c = qobject_cast(t)) { - workspace()->activateClient(c); + if ((m_dragTarget = qobject_cast(t))) { + workspace()->takeActivity(m_dragTarget, Workspace::ActivityFlag::ActivityFocus); + m_raiseTimer.start(); } seat->setDragTarget(t->surface(), pos, t->inputTransformation()); } + if ((pos - m_lastPos).manhattanLength() > 10) { + m_lastPos = pos; + // reset timer to delay raising the window + m_raiseTimer.start(); + } } else { // no window at that place, if we have a surface we need to reset seat->setDragTarget(nullptr); + m_dragTarget = nullptr; } return true; } @@ -1988,11 +2012,22 @@ public: seat->notifyTouchUp(id); if (m_touchId == id) { m_touchId = -1; + raiseDragTarget(); } return true; } private: + void raiseDragTarget() + { + m_raiseTimer.stop(); + if (m_dragTarget) { + workspace()->takeActivity(m_dragTarget, Workspace::ActivityFlag::ActivityRaise); + } + } qint32 m_touchId = -1; + QPointF m_lastPos = QPointF(-1, -1); + QPointer m_dragTarget; + QTimer m_raiseTimer; }; KWIN_SINGLETON_FACTORY(InputRedirection) @@ -2847,3 +2882,5 @@ QWindow *InputDeviceHandler::internalWindow() const } } // namespace + +#include "input.moc"