Properly handle move during touch events
Summary: When a window was being moved the touch handling performed the wrong interaction. Due to that it was possible to move the window, but KWin did not enter the correct code paths, thus quick tiling was for example not functional. BUG: 390113 FIXED-IN: 5.12.3 Test Plan: New test case added and manual test in nested KWin Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #plasma Differential Revision: https://phabricator.kde.org/D10431
This commit is contained in:
parent
b5e8694fdf
commit
338c7362c9
2 changed files with 84 additions and 8 deletions
|
@ -28,8 +28,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "shell_client.h"
|
||||
#include "scripting/scripting.h"
|
||||
|
||||
#include <KDecoration2/Decoration>
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/compositor.h>
|
||||
#include <KWayland/Client/server_decoration.h>
|
||||
#include <KWayland/Client/shell.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
#include <KWayland/Client/xdgshell.h>
|
||||
|
@ -70,6 +73,8 @@ private Q_SLOTS:
|
|||
void testQuickTilingPointerMove();
|
||||
void testQuickTilingPointerMoveXdgShell_data();
|
||||
void testQuickTilingPointerMoveXdgShell();
|
||||
void testQuickTilingTouchMoveXdgShell_data();
|
||||
void testQuickTilingTouchMoveXdgShell();
|
||||
void testX11QuickTiling_data();
|
||||
void testX11QuickTiling();
|
||||
void testX11QuickTilingAfterVertMaximize_data();
|
||||
|
@ -115,7 +120,7 @@ void QuickTilingTest::initTestCase()
|
|||
|
||||
void QuickTilingTest::init()
|
||||
{
|
||||
QVERIFY(Test::setupWaylandConnection());
|
||||
QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Decoration));
|
||||
m_connection = Test::waylandConnection();
|
||||
m_compositor = Test::waylandCompositor();
|
||||
m_shell = Test::waylandShell();
|
||||
|
@ -496,6 +501,69 @@ void QuickTilingTest::testQuickTilingPointerMoveXdgShell()
|
|||
QCOMPARE(false, configureRequestedSpy.last().first().toSize().isEmpty());
|
||||
}
|
||||
|
||||
void QuickTilingTest::testQuickTilingTouchMoveXdgShell_data()
|
||||
{
|
||||
QTest::addColumn<QPoint>("targetPos");
|
||||
QTest::addColumn<QuickTileMode>("expectedMode");
|
||||
|
||||
QTest::newRow("topRight") << QPoint(2559, 24) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Right);
|
||||
QTest::newRow("right") << QPoint(2559, 512) << QuickTileMode(QuickTileFlag::Right);
|
||||
QTest::newRow("bottomRight") << QPoint(2559, 1023) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Right);
|
||||
QTest::newRow("bottomLeft") << QPoint(0, 1023) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Left);
|
||||
QTest::newRow("Left") << QPoint(0, 512) << QuickTileMode(QuickTileFlag::Left);
|
||||
QTest::newRow("topLeft") << QPoint(0, 24) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Left);
|
||||
}
|
||||
|
||||
void QuickTilingTest::testQuickTilingTouchMoveXdgShell()
|
||||
{
|
||||
// test verifies that touch on decoration also allows quick tiling
|
||||
// see BUG: 390113
|
||||
using namespace KWayland::Client;
|
||||
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QVERIFY(!surface.isNull());
|
||||
QScopedPointer<ServerSideDecoration> deco(Test::waylandServerSideDecoration()->create(surface.data()));
|
||||
|
||||
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellV6Surface(surface.data()));
|
||||
QVERIFY(!shellSurface.isNull());
|
||||
QSignalSpy configureRequestedSpy(shellSurface.data(), &XdgShellSurface::configureRequested);
|
||||
QVERIFY(configureRequestedSpy.isValid());
|
||||
// let's render
|
||||
auto c = Test::renderAndWaitForShown(surface.data(), QSize(1000, 50), Qt::blue);
|
||||
|
||||
QVERIFY(c);
|
||||
QVERIFY(c->isDecorated());
|
||||
const auto decoration = c->decoration();
|
||||
QCOMPARE(workspace()->activeClient(), c);
|
||||
QCOMPARE(c->geometry(), QRect(-decoration->borderLeft(), 0,
|
||||
1000 + decoration->borderLeft() + decoration->borderRight(),
|
||||
50 + decoration->borderTop() + decoration->borderBottom()));
|
||||
QCOMPARE(c->quickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
QCOMPARE(c->maximizeMode(), MaximizeRestore);
|
||||
QVERIFY(configureRequestedSpy.wait());
|
||||
QTRY_COMPARE(configureRequestedSpy.count(), 2);
|
||||
|
||||
QSignalSpy quickTileChangedSpy(c, &AbstractClient::quickTileModeChanged);
|
||||
QVERIFY(quickTileChangedSpy.isValid());
|
||||
|
||||
quint32 timestamp = 1;
|
||||
kwinApp()->platform()->touchDown(0, QPointF(c->geometry().center().x(), c->geometry().y() + decoration->borderTop() / 2), timestamp++);
|
||||
QVERIFY(configureRequestedSpy.wait());
|
||||
QCOMPARE(c, workspace()->getMovingClient());
|
||||
QCOMPARE(configureRequestedSpy.count(), 3);
|
||||
|
||||
QFETCH(QPoint, targetPos);
|
||||
kwinApp()->platform()->touchMotion(0, targetPos, timestamp++);
|
||||
kwinApp()->platform()->touchUp(0, timestamp++);
|
||||
QVERIFY(!workspace()->getMovingClient());
|
||||
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QTEST(c->quickTileMode(), "expectedMode");
|
||||
QVERIFY(configureRequestedSpy.wait());
|
||||
QCOMPARE(configureRequestedSpy.count(), 5);
|
||||
QCOMPARE(false, configureRequestedSpy.last().first().toSize().isEmpty());
|
||||
}
|
||||
|
||||
struct XcbConnectionDeleter
|
||||
{
|
||||
static inline void cleanup(xcb_connection_t *pointer)
|
||||
|
|
22
input.cpp
22
input.cpp
|
@ -1100,9 +1100,13 @@ public:
|
|||
}
|
||||
m_lastGlobalTouchPos = pos;
|
||||
m_lastLocalTouchPos = pos - decoration->client()->pos();
|
||||
QHoverEvent e(QEvent::HoverMove, m_lastLocalTouchPos, m_lastLocalTouchPos);
|
||||
QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
|
||||
decoration->client()->processDecorationMove(m_lastLocalTouchPos.toPoint(), pos.toPoint());
|
||||
if (auto c = workspace()->getMovingClient()) {
|
||||
c->updateMoveResize(pos);
|
||||
} else {
|
||||
QHoverEvent e(QEvent::HoverMove, m_lastLocalTouchPos, m_lastLocalTouchPos);
|
||||
QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
|
||||
decoration->client()->processDecorationMove(m_lastLocalTouchPos.toPoint(), pos.toPoint());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool touchUp(quint32 id, quint32 time) override {
|
||||
|
@ -1119,10 +1123,14 @@ public:
|
|||
return true;
|
||||
}
|
||||
// send mouse up
|
||||
QMouseEvent e(QEvent::MouseButtonRelease, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::MouseButtons(), input()->keyboardModifiers());
|
||||
e.setAccepted(false);
|
||||
QCoreApplication::sendEvent(decoration->decoration(), &e);
|
||||
decoration->client()->processDecorationButtonRelease(&e);
|
||||
if (auto c = workspace()->getMovingClient()) {
|
||||
c->endMoveResize();
|
||||
} else {
|
||||
QMouseEvent e(QEvent::MouseButtonRelease, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::MouseButtons(), input()->keyboardModifiers());
|
||||
e.setAccepted(false);
|
||||
QCoreApplication::sendEvent(decoration->decoration(), &e);
|
||||
decoration->client()->processDecorationButtonRelease(&e);
|
||||
}
|
||||
|
||||
m_lastGlobalTouchPos = QPointF();
|
||||
m_lastLocalTouchPos = QPointF();
|
||||
|
|
Loading…
Reference in a new issue