summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Gräßlin <mgraesslin@kde.org>2017-02-14 06:29:38 (GMT)
committerMartin Gräßlin <mgraesslin@kde.org>2017-02-14 06:29:38 (GMT)
commit8b4f284249f1ff6a52b7148c0536164c42ceaa73 (patch)
tree3af89cd0f816677f517b886bbc142d36861941c5
parente9155286e8155f22ac7277d1a7ccabac986c6e51 (diff)
[autotests] Add test case for quick tiling on X11
Exposes our regressions of X11 quick tiling when a window is vertically maximized. CCBUG: 376155
-rw-r--r--autotests/integration/CMakeLists.txt2
-rw-r--r--autotests/integration/quick_tiling_test.cpp183
2 files changed, 184 insertions, 1 deletions
diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt
index 6134011..9d367a2 100644
--- a/autotests/integration/CMakeLists.txt
+++ b/autotests/integration/CMakeLists.txt
@@ -16,7 +16,6 @@ endfunction()
integrationTest(NAME testStart SRCS start_test.cpp)
integrationTest(NAME testTransientNoInput SRCS transient_no_input_test.cpp)
-integrationTest(NAME testQuickTiling SRCS quick_tiling_test.cpp)
integrationTest(NAME testDontCrashGlxgears SRCS dont_crash_glxgears.cpp)
integrationTest(NAME testLockScreen SRCS lockscreen.cpp)
integrationTest(NAME testDecorationInput SRCS decoration_input_test.cpp)
@@ -55,6 +54,7 @@ if (XCB_ICCCM_FOUND)
integrationTest(NAME testXwaylandInput SRCS xwayland_input_test.cpp LIBS XCB::ICCCM)
integrationTest(NAME testWindowRules SRCS window_rules_test.cpp LIBS XCB::ICCCM)
integrationTest(NAME testX11Client SRCS x11_client_test.cpp LIBS XCB::ICCCM)
+ integrationTest(NAME testQuickTiling SRCS quick_tiling_test.cpp LIBS XCB::ICCCM)
if (KWIN_BUILD_ACTIVITIES)
integrationTest(NAME testActivities SRCS activities_test.cpp LIBS XCB::ICCCM)
diff --git a/autotests/integration/quick_tiling_test.cpp b/autotests/integration/quick_tiling_test.cpp
index 9456ee6..f506810 100644
--- a/autotests/integration/quick_tiling_test.cpp
+++ b/autotests/integration/quick_tiling_test.cpp
@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "kwin_wayland_test.h"
#include "platform.h"
#include "abstract_client.h"
+#include "client.h"
#include "cursor.h"
#include "screens.h"
#include "wayland_server.h"
@@ -31,6 +32,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KWayland/Client/shell.h>
#include <KWayland/Client/surface.h>
+#include <netwm.h>
+#include <xcb/xcb_icccm.h>
+
#include <linux/input.h>
Q_DECLARE_METATYPE(KWin::AbstractClient::QuickTileMode)
@@ -56,6 +60,10 @@ private Q_SLOTS:
void testQuickTilingKeyboardMove();
void testQuickTilingPointerMove_data();
void testQuickTilingPointerMove();
+ void testX11QuickTiling_data();
+ void testX11QuickTiling();
+ void testX11QuickTilingAfterVertMaximize_data();
+ void testX11QuickTilingAfterVertMaximize();
private:
KWayland::Client::ConnectionThread *m_connection = nullptr;
@@ -406,6 +414,181 @@ void QuickTilingTest::testQuickTilingPointerMove()
QTEST(c->quickTileMode(), "expectedMode");
}
+struct XcbConnectionDeleter
+{
+ static inline void cleanup(xcb_connection_t *pointer)
+ {
+ xcb_disconnect(pointer);
+ }
+};
+
+void QuickTilingTest::testX11QuickTiling_data()
+{
+ QTest::addColumn<AbstractClient::QuickTileMode>("mode");
+ QTest::addColumn<QRect>("expectedGeometry");
+
+#define FLAG(name) AbstractClient::QuickTileMode(AbstractClient::QuickTile##name)
+
+ QTest::newRow("left") << FLAG(Left) << QRect(0, 0, 640, 1024);
+ QTest::newRow("top") << FLAG(Top) << QRect(0, 0, 1280, 512);
+ QTest::newRow("right") << FLAG(Right) << QRect(640, 0, 640, 1024);
+ QTest::newRow("bottom") << FLAG(Bottom) << QRect(0, 512, 1280, 512);
+
+ QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRect(0, 0, 640, 512);
+ QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRect(640, 0, 640, 512);
+ QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRect(0, 512, 640, 512);
+ QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRect(640, 512, 640, 512);
+
+ QTest::newRow("maximize") << FLAG(Maximize) << QRect(0, 0, 1280, 1024);
+
+#undef FLAG
+}
+void QuickTilingTest::testX11QuickTiling()
+{
+ QScopedPointer<xcb_connection_t, XcbConnectionDeleter> c(xcb_connect(nullptr, nullptr));
+ QVERIFY(!xcb_connection_has_error(c.data()));
+ const QRect windowGeometry(0, 0, 100, 200);
+ xcb_window_t w = xcb_generate_id(c.data());
+ xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w, rootWindow(),
+ windowGeometry.x(),
+ windowGeometry.y(),
+ windowGeometry.width(),
+ windowGeometry.height(),
+ 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
+ xcb_size_hints_t hints;
+ memset(&hints, 0, sizeof(hints));
+ xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
+ xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
+ xcb_icccm_set_wm_normal_hints(c.data(), w, &hints);
+ xcb_map_window(c.data(), w);
+ xcb_flush(c.data());
+
+ // we should get a client for it
+ QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded);
+ QVERIFY(windowCreatedSpy.isValid());
+ QVERIFY(windowCreatedSpy.wait());
+ Client *client = windowCreatedSpy.first().first().value<Client*>();
+ QVERIFY(client);
+ QCOMPARE(client->window(), w);
+
+ // now quick tile
+ QSignalSpy quickTileChangedSpy(client, &AbstractClient::quickTileModeChanged);
+ QVERIFY(quickTileChangedSpy.isValid());
+ const QRect origGeo = client->geometry();
+ QFETCH(AbstractClient::QuickTileMode, mode);
+ client->setQuickTileMode(mode, true);
+ QCOMPARE(client->quickTileMode(), mode);
+ QTEST(client->geometry(), "expectedGeometry");
+ QCOMPARE(client->geometryRestore(), origGeo);
+ QEXPECT_FAIL("maximize", "For maximize we get two changed signals", Continue);
+ QCOMPARE(quickTileChangedSpy.count(), 1);
+
+ // and destroy the window again
+ xcb_unmap_window(c.data(), w);
+ xcb_destroy_window(c.data(), w);
+ xcb_flush(c.data());
+ c.reset();
+
+ QSignalSpy windowClosedSpy(client, &Client::windowClosed);
+ QVERIFY(windowClosedSpy.isValid());
+ QVERIFY(windowClosedSpy.wait());
+}
+
+void QuickTilingTest::testX11QuickTilingAfterVertMaximize_data()
+{
+ QTest::addColumn<AbstractClient::QuickTileMode>("mode");
+ QTest::addColumn<QRect>("expectedGeometry");
+
+#define FLAG(name) AbstractClient::QuickTileMode(AbstractClient::QuickTile##name)
+
+ QTest::newRow("left") << FLAG(Left) << QRect(0, 0, 640, 1024);
+ QTest::newRow("top") << FLAG(Top) << QRect(0, 0, 1280, 512);
+ QTest::newRow("right") << FLAG(Right) << QRect(640, 0, 640, 1024);
+ QTest::newRow("bottom") << FLAG(Bottom) << QRect(0, 512, 1280, 512);
+
+ QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRect(0, 0, 640, 512);
+ QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRect(640, 0, 640, 512);
+ QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRect(0, 512, 640, 512);
+ QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRect(640, 512, 640, 512);
+
+ QTest::newRow("maximize") << FLAG(Maximize) << QRect(0, 0, 1280, 1024);
+
+#undef FLAG
+}
+
+void QuickTilingTest::testX11QuickTilingAfterVertMaximize()
+{
+ QScopedPointer<xcb_connection_t, XcbConnectionDeleter> c(xcb_connect(nullptr, nullptr));
+ QVERIFY(!xcb_connection_has_error(c.data()));
+ const QRect windowGeometry(0, 0, 100, 200);
+ xcb_window_t w = xcb_generate_id(c.data());
+ xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w, rootWindow(),
+ windowGeometry.x(),
+ windowGeometry.y(),
+ windowGeometry.width(),
+ windowGeometry.height(),
+ 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
+ xcb_size_hints_t hints;
+ memset(&hints, 0, sizeof(hints));
+ xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
+ xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
+ xcb_icccm_set_wm_normal_hints(c.data(), w, &hints);
+ xcb_map_window(c.data(), w);
+ xcb_flush(c.data());
+
+ // we should get a client for it
+ QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded);
+ QVERIFY(windowCreatedSpy.isValid());
+ QVERIFY(windowCreatedSpy.wait());
+ Client *client = windowCreatedSpy.first().first().value<Client*>();
+ QVERIFY(client);
+ QCOMPARE(client->window(), w);
+
+ const QRect origGeo = client->geometry();
+ QCOMPARE(client->maximizeMode(), MaximizeRestore);
+ // vertically maximize the window
+ client->maximize(client->maximizeMode() ^ MaximizeVertical);
+ QCOMPARE(client->geometry().width(), origGeo.width());
+ QCOMPARE(client->height(), screens()->size(client->screen()).height());
+ QCOMPARE(client->geometryRestore(), origGeo);
+
+ // now quick tile
+ QSignalSpy quickTileChangedSpy(client, &AbstractClient::quickTileModeChanged);
+ QVERIFY(quickTileChangedSpy.isValid());
+ QFETCH(AbstractClient::QuickTileMode, mode);
+ client->setQuickTileMode(mode, true);
+ QEXPECT_FAIL("left", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("right", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("top", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("bottom", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("top left", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("top right", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("bottom left", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("bottom right", "Quick tiling not working", Continue);
+ QCOMPARE(client->quickTileMode(), mode);
+ QEXPECT_FAIL("left", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("right", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("top", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("bottom", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("top left", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("top right", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("bottom left", "Quick tiling not working", Continue);
+ QEXPECT_FAIL("bottom right", "Quick tiling not working", Continue);
+ QTEST(client->geometry(), "expectedGeometry");
+ QEXPECT_FAIL("", "We get two changed events", Continue);
+ QCOMPARE(quickTileChangedSpy.count(), 1);
+
+ // and destroy the window again
+ xcb_unmap_window(c.data(), w);
+ xcb_destroy_window(c.data(), w);
+ xcb_flush(c.data());
+ c.reset();
+
+ QSignalSpy windowClosedSpy(client, &Client::windowClosed);
+ QVERIFY(windowClosedSpy.isValid());
+ QVERIFY(windowClosedSpy.wait());
+}
+
}
WAYLANDTEST_MAIN(KWin::QuickTilingTest)