diff --git a/autotests/integration/quick_tiling_test.cpp b/autotests/integration/quick_tiling_test.cpp index 7958612d64..d3c5ea9827 100644 --- a/autotests/integration/quick_tiling_test.cpp +++ b/autotests/integration/quick_tiling_test.cpp @@ -28,8 +28,11 @@ along with this program. If not, see . #include "shell_client.h" #include "scripting/scripting.h" +#include + #include #include +#include #include #include #include @@ -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("targetPos"); + QTest::addColumn("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(Test::createSurface()); + QVERIFY(!surface.isNull()); + QScopedPointer deco(Test::waylandServerSideDecoration()->create(surface.data())); + + QScopedPointer 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) diff --git a/input.cpp b/input.cpp index cd6d841f3e..0385d1dda9 100644 --- a/input.cpp +++ b/input.cpp @@ -1096,9 +1096,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 { @@ -1115,10 +1119,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(); diff --git a/kcmkwin/kwinrules/main.cpp b/kcmkwin/kwinrules/main.cpp index ae66a0372b..42ee9fce90 100644 --- a/kcmkwin/kwinrules/main.cpp +++ b/kcmkwin/kwinrules/main.cpp @@ -248,6 +248,7 @@ static int edit(Window wid, bool whole_app) extern "C" KWIN_EXPORT int kdemain(int argc, char* argv[]) { + qputenv("QT_QPA_PLATFORM", "xcb"); QApplication app(argc, argv); app.setApplicationDisplayName(i18n("KWin")); app.setApplicationName("kwin_rules_dialog"); diff --git a/useractions.cpp b/useractions.cpp index dc56707932..59344685a7 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -40,6 +40,7 @@ along with this program. If not, see . #include "effects.h" #include "platform.h" #include "screens.h" +#include "shell_client.h" #include "virtualdesktops.h" #include "scripting/scripting.h" @@ -318,10 +319,12 @@ void UserActionsMenu::init() QAction *action = advancedMenu->addAction(i18n("Special &Window Settings...")); action->setIcon(QIcon::fromTheme(QStringLiteral("preferences-system-windows-actions"))); action->setData(Options::WindowRulesOp); + m_rulesOperation = action; action = advancedMenu->addAction(i18n("S&pecial Application Settings...")); action->setIcon(QIcon::fromTheme(QStringLiteral("preferences-system-windows-actions"))); action->setData(Options::ApplicationRulesOp); + m_applicationRulesOperation = action; if (!kwinApp()->config()->isImmutable() && !KAuthorized::authorizeControlModules(configModules(true)).isEmpty()) { advancedMenu->addSeparator(); @@ -465,6 +468,15 @@ void UserActionsMenu::menuAboutToShow() action->setText(i18n("&Extensions")); } + // disable rules for Wayland windows - dialog is X11 only + if (qobject_cast(m_client.data())) { + m_rulesOperation->setEnabled(false); + m_applicationRulesOperation->setEnabled(false); + } else { + m_rulesOperation->setEnabled(true); + m_applicationRulesOperation->setEnabled(true); + } + showHideActivityMenu(); } diff --git a/useractions.h b/useractions.h index 9f489346e7..005b2ccfa3 100644 --- a/useractions.h +++ b/useractions.h @@ -260,6 +260,8 @@ private: * The Client for which the menu is shown. **/ QWeakPointer m_client; + QAction *m_rulesOperation = nullptr; + QAction *m_applicationRulesOperation = nullptr; }; class ShortcutDialog