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