diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt index 0a109cfc3..eb0e672f2 100644 --- a/autotests/integration/CMakeLists.txt +++ b/autotests/integration/CMakeLists.txt @@ -1,91 +1,91 @@ add_subdirectory(helper) add_library(KWinIntegrationTestFramework STATIC kwin_wayland_test.cpp test_helpers.cpp ${kwin_XWAYLAND_SRCS}) target_link_libraries(KWinIntegrationTestFramework kwin Qt5::Test) function(integrationTest) set(optionArgs WAYLAND_ONLY) set(oneValueArgs NAME) set(multiValueArgs SRCS LIBS) cmake_parse_arguments(ARGS "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) add_executable(${ARGS_NAME} ${ARGS_SRCS}) target_link_libraries(${ARGS_NAME} KWinIntegrationTestFramework kwin Qt5::Test ${ARGS_LIBS}) add_test(NAME kwin-${ARGS_NAME} COMMAND dbus-run-session ${CMAKE_BINARY_DIR}/bin/${ARGS_NAME}) if (${ARGS_WAYLAND_ONLY}) add_executable(${ARGS_NAME}_waylandonly ${ARGS_SRCS}) set_target_properties(${ARGS_NAME}_waylandonly PROPERTIES COMPILE_DEFINITIONS "NO_XWAYLAND") target_link_libraries(${ARGS_NAME}_waylandonly KWinIntegrationTestFramework kwin Qt5::Test ${ARGS_LIBS}) add_test(NAME kwin-${ARGS_NAME}-waylandonly COMMAND dbus-run-session ${CMAKE_BINARY_DIR}/bin/${ARGS_NAME}_waylandonly) endif() endfunction() integrationTest(WAYLAND_ONLY NAME testStart SRCS start_test.cpp) integrationTest(WAYLAND_ONLY NAME testTransientNoInput SRCS transient_no_input_test.cpp) integrationTest(NAME testDontCrashGlxgears SRCS dont_crash_glxgears.cpp) integrationTest(NAME testLockScreen SRCS lockscreen.cpp) integrationTest(WAYLAND_ONLY NAME testDecorationInput SRCS decoration_input_test.cpp) integrationTest(WAYLAND_ONLY NAME testInternalWindow SRCS internal_window.cpp) integrationTest(WAYLAND_ONLY NAME testTouchInput SRCS touch_input_test.cpp) integrationTest(WAYLAND_ONLY NAME testInputStackingOrder SRCS input_stacking_order.cpp) integrationTest(NAME testPointerInput SRCS pointer_input.cpp) integrationTest(NAME testPlatformCursor SRCS platformcursor.cpp) integrationTest(WAYLAND_ONLY NAME testDontCrashCancelAnimation SRCS dont_crash_cancel_animation.cpp) integrationTest(WAYLAND_ONLY NAME testTransientPlacement SRCS transient_placement.cpp) integrationTest(NAME testDebugConsole SRCS debug_console_test.cpp) integrationTest(NAME testDontCrashEmptyDeco SRCS dont_crash_empty_deco.cpp) integrationTest(WAYLAND_ONLY NAME testPlasmaSurface SRCS plasma_surface_test.cpp) integrationTest(WAYLAND_ONLY NAME testMaximized SRCS maximize_test.cpp) integrationTest(WAYLAND_ONLY NAME testShellClient SRCS shell_client_test.cpp) integrationTest(WAYLAND_ONLY NAME testDontCrashNoBorder SRCS dont_crash_no_border.cpp) integrationTest(NAME testXwaylandSelections SRCS xwayland_selections_test.cpp) integrationTest(WAYLAND_ONLY NAME testSceneOpenGL SRCS scene_opengl_test.cpp generic_scene_opengl_test.cpp) integrationTest(WAYLAND_ONLY NAME testSceneOpenGLShadow SRCS scene_opengl_shadow_test.cpp) integrationTest(WAYLAND_ONLY NAME testSceneOpenGLES SRCS scene_opengl_es_test.cpp generic_scene_opengl_test.cpp) integrationTest(WAYLAND_ONLY NAME testNoXdgRuntimeDir SRCS no_xdg_runtime_dir_test.cpp) integrationTest(WAYLAND_ONLY NAME testScreenChanges SRCS screen_changes_test.cpp) integrationTest(NAME testModiferOnlyShortcut SRCS modifier_only_shortcut_test.cpp) integrationTest(WAYLAND_ONLY NAME testTabBox SRCS tabbox_test.cpp) integrationTest(WAYLAND_ONLY NAME testWindowSelection SRCS window_selection_test.cpp) integrationTest(WAYLAND_ONLY NAME testPointerConstraints SRCS pointer_constraints_test.cpp) integrationTest(WAYLAND_ONLY NAME testKeyboardLayout SRCS keyboard_layout_test.cpp) integrationTest(WAYLAND_ONLY NAME testKeymapCreationFailure SRCS keymap_creation_failure_test.cpp) integrationTest(WAYLAND_ONLY NAME testShowingDesktop SRCS showing_desktop_test.cpp) integrationTest(WAYLAND_ONLY NAME testDontCrashUseractionsMenu SRCS dont_crash_useractions_menu.cpp) integrationTest(WAYLAND_ONLY NAME testKWinBindings SRCS kwinbindings_test.cpp) integrationTest(WAYLAND_ONLY NAME testVirtualDesktop SRCS virtual_desktop_test.cpp) integrationTest(WAYLAND_ONLY NAME testShellClientRules SRCS shell_client_rules_test.cpp) integrationTest(WAYLAND_ONLY NAME testIdleInhibition SRCS idle_inhibition_test.cpp) integrationTest(WAYLAND_ONLY NAME testColorCorrectNightColor SRCS colorcorrect_nightcolor_test.cpp) integrationTest(WAYLAND_ONLY NAME testDontCrashCursorPhysicalSizeEmpty SRCS dont_crash_cursor_physical_size_empty.cpp) integrationTest(WAYLAND_ONLY NAME testDontCrashReinitializeCompositor SRCS dont_crash_reinitialize_compositor.cpp) integrationTest(WAYLAND_ONLY NAME testNoGlobalShortcuts SRCS no_global_shortcuts_test.cpp) integrationTest(WAYLAND_ONLY NAME testBufferSizeChange SRCS buffer_size_change_test.cpp generic_scene_opengl_test.cpp) -integrationTest(WAYLAND_ONLY NAME testPlacement SRCS placement.cpp) +integrationTest(WAYLAND_ONLY NAME testPlacement SRCS placement_test.cpp) integrationTest(WAYLAND_ONLY NAME testActivation SRCS activation_test.cpp) if (XCB_ICCCM_FOUND) integrationTest(NAME testMoveResize SRCS move_resize_window_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testStruts SRCS struts_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testShade SRCS shade_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testDontCrashAuroraeDestroyDeco SRCS dont_crash_aurorae_destroy_deco.cpp LIBS XCB::ICCCM) integrationTest(NAME testPlasmaWindow SRCS plasmawindow_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testScreenEdgeClientShow SRCS screenedge_client_show_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testX11DesktopWindow SRCS desktop_window_x11_test.cpp LIBS XCB::ICCCM) 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) integrationTest(NAME testGlobalShortcuts SRCS globalshortcuts_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testSceneQPainter SRCS scene_qpainter_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testSceneQPainterShadow SRCS scene_qpainter_shadow_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testStackingOrder SRCS stacking_order_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testDbusInterface SRCS dbus_interface_test.cpp LIBS XCB::ICCCM) if (KWIN_BUILD_ACTIVITIES) integrationTest(NAME testActivities SRCS activities_test.cpp LIBS XCB::ICCCM) endif() endif() add_subdirectory(scripting) add_subdirectory(effects) add_subdirectory(fakes) diff --git a/autotests/integration/placement.cpp b/autotests/integration/placement_test.cpp similarity index 99% rename from autotests/integration/placement.cpp rename to autotests/integration/placement_test.cpp index 63cecb58a..a47d8e4e7 100644 --- a/autotests/integration/placement.cpp +++ b/autotests/integration/placement_test.cpp @@ -1,326 +1,326 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2019 David Edmundson Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "cursor.h" #include "kwin_wayland_test.h" #include "platform.h" #include "screens.h" #include "shell_client.h" #include "wayland_server.h" #include "workspace.h" #include #include #include #include #include #include #include #include using namespace KWin; using namespace KWayland::Client; static const QString s_socketName = QStringLiteral("wayland_test_kwin_placement-0"); struct PlaceWindowResult { QSize initiallyConfiguredSize; KWayland::Client::XdgShellSurface::States initiallyConfiguredStates; QRect finalGeometry; }; class TestPlacement : public QObject { Q_OBJECT private Q_SLOTS: void init(); void cleanup(); void initTestCase(); void testPlaceSmart(); void testPlaceZeroCornered(); void testPlaceMaximized(); void testPlaceCentered(); void testPlaceUnderMouse(); void testPlaceCascaded(); void testPlaceRandom(); private: void setPlacementPolicy(Placement::Policy policy); /* * Create a window with the lifespan of parent and return relevant results for testing * defaultSize is the buffer size to use if the compositor returns an empty size in the first configure * event. */ PlaceWindowResult createAndPlaceWindow(const QSize &defaultSize, QObject *parent); }; void TestPlacement::init() { QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::XdgDecoration | Test::AdditionalWaylandInterface::PlasmaShell)); screens()->setCurrent(0); KWin::Cursor::setPos(QPoint(512, 512)); } void TestPlacement::cleanup() { Test::destroyWaylandConnection(); } void TestPlacement::initTestCase() { qRegisterMetaType(); qRegisterMetaType(); QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); kwinApp()->start(); QVERIFY(workspaceCreatedSpy.wait()); QCOMPARE(screens()->count(), 2); QCOMPARE(screens()->geometry(0), QRect(0, 0, 1280, 1024)); QCOMPARE(screens()->geometry(1), QRect(1280, 0, 1280, 1024)); waylandServer()->initWorkspace(); } void TestPlacement::setPlacementPolicy(Placement::Policy policy) { auto group = kwinApp()->config()->group("Windows"); group.writeEntry("Placement", Placement::policyToString(policy)); group.sync(); Workspace::self()->slotReconfigure(); } PlaceWindowResult TestPlacement::createAndPlaceWindow(const QSize &defaultSize, QObject *parent) { PlaceWindowResult rc; // create a new window auto surface = Test::createSurface(parent); auto shellSurface = Test::createXdgShellStableSurface(surface, surface, Test::CreationSetup::CreateOnly); QSignalSpy configSpy(shellSurface, &XdgShellSurface::configureRequested); surface->commit(Surface::CommitFlag::None); configSpy.wait(); rc.initiallyConfiguredSize = configSpy[0][0].toSize(); rc.initiallyConfiguredStates = configSpy[0][1].value(); shellSurface->ackConfigure(configSpy[0][2].toUInt()); QSize size = rc.initiallyConfiguredSize; if (size.isEmpty()) { size = defaultSize; } auto c = Test::renderAndWaitForShown(surface, size, Qt::red); rc.finalGeometry = c->geometry(); return rc; } void TestPlacement::testPlaceSmart() { setPlacementPolicy(Placement::Smart); QScopedPointer testParent(new QObject); //dumb QObject just for scoping surfaces to the test QRegion usedArea; for (int i = 0; i < 4; i++) { PlaceWindowResult windowPlacement = createAndPlaceWindow(QSize(600, 500), testParent.data()); // smart placement shouldn't define a size on clients QCOMPARE(windowPlacement.initiallyConfiguredSize, QSize(0, 0)); QCOMPARE(windowPlacement.finalGeometry.size(), QSize(600, 500)); // exact placement isn't a defined concept that should be tested // but the goal of smart placement is to make sure windows don't overlap until they need to // 4 windows of 600, 500 should fit without overlap QVERIFY(!usedArea.intersects(windowPlacement.finalGeometry)); usedArea += windowPlacement.finalGeometry; } } void TestPlacement::testPlaceZeroCornered() { setPlacementPolicy(Placement::ZeroCornered); QScopedPointer testParent(new QObject); for (int i = 0; i < 4; i++) { PlaceWindowResult windowPlacement = createAndPlaceWindow(QSize(600, 500), testParent.data()); // smart placement shouldn't define a size on clients QCOMPARE(windowPlacement.initiallyConfiguredSize, QSize(0, 0)); // size should match our buffer QCOMPARE(windowPlacement.finalGeometry.size(), QSize(600, 500)); //and it should be in the corner QCOMPARE(windowPlacement.finalGeometry.topLeft(), QPoint(0, 0)); } } void TestPlacement::testPlaceMaximized() { setPlacementPolicy(Placement::Maximizing); // add a top panel QScopedPointer panelSurface(Test::createSurface()); QScopedPointer panelShellSurface(Test::createXdgShellStableSurface(panelSurface.data())); QScopedPointer plasmaSurface(Test::waylandPlasmaShell()->createSurface(panelSurface.data())); plasmaSurface->setRole(PlasmaShellSurface::Role::Panel); plasmaSurface->setPosition(QPoint(0, 0)); Test::renderAndWaitForShown(panelSurface.data(), QSize(1280, 20), Qt::blue); QScopedPointer testParent(new QObject); // all windows should be initially maximized with an initial configure size sent for (int i = 0; i < 4; i++) { PlaceWindowResult windowPlacement = createAndPlaceWindow(QSize(600, 500), testParent.data()); QVERIFY(windowPlacement.initiallyConfiguredStates & XdgShellSurface::State::Maximized); QCOMPARE(windowPlacement.initiallyConfiguredSize, QSize(1280, 1024 - 20)); QCOMPARE(windowPlacement.finalGeometry, QRect(0, 20, 1280, 1024 - 20)); // under the panel } } void TestPlacement::testPlaceCentered() { // This test verifies that Centered placement policy works. KConfigGroup group = kwinApp()->config()->group("Windows"); group.writeEntry("Placement", Placement::policyToString(Placement::Centered)); group.sync(); workspace()->slotReconfigure(); QScopedPointer surface(Test::createSurface()); QScopedPointer shellSurface(Test::createXdgShellStableSurface(surface.data())); ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::red); QVERIFY(client); QCOMPARE(client->geometry(), QRect(590, 487, 100, 50)); shellSurface.reset(); QVERIFY(Test::waitForWindowDestroyed(client)); } void TestPlacement::testPlaceUnderMouse() { // This test verifies that Under Mouse placement policy works. KConfigGroup group = kwinApp()->config()->group("Windows"); group.writeEntry("Placement", Placement::policyToString(Placement::UnderMouse)); group.sync(); workspace()->slotReconfigure(); KWin::Cursor::setPos(QPoint(200, 300)); QCOMPARE(KWin::Cursor::pos(), QPoint(200, 300)); QScopedPointer surface(Test::createSurface()); QScopedPointer shellSurface(Test::createXdgShellStableSurface(surface.data())); ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::red); QVERIFY(client); QCOMPARE(client->geometry(), QRect(151, 276, 100, 50)); shellSurface.reset(); QVERIFY(Test::waitForWindowDestroyed(client)); } void TestPlacement::testPlaceCascaded() { // This test verifies that Cascaded placement policy works. KConfigGroup group = kwinApp()->config()->group("Windows"); group.writeEntry("Placement", Placement::policyToString(Placement::Cascade)); group.sync(); workspace()->slotReconfigure(); QScopedPointer surface1(Test::createSurface()); QScopedPointer shellSurface1(Test::createXdgShellStableSurface(surface1.data())); ShellClient *client1 = Test::renderAndWaitForShown(surface1.data(), QSize(100, 50), Qt::red); QVERIFY(client1); QCOMPARE(client1->pos(), QPoint(0, 0)); QCOMPARE(client1->size(), QSize(100, 50)); QScopedPointer surface2(Test::createSurface()); QScopedPointer shellSurface2(Test::createXdgShellStableSurface(surface2.data())); ShellClient *client2 = Test::renderAndWaitForShown(surface2.data(), QSize(100, 50), Qt::blue); QVERIFY(client2); QCOMPARE(client2->pos(), client1->pos() + workspace()->cascadeOffset(client2)); QCOMPARE(client2->size(), QSize(100, 50)); QScopedPointer surface3(Test::createSurface()); QScopedPointer shellSurface3(Test::createXdgShellStableSurface(surface3.data())); ShellClient *client3 = Test::renderAndWaitForShown(surface3.data(), QSize(100, 50), Qt::green); QVERIFY(client3); QCOMPARE(client3->pos(), client2->pos() + workspace()->cascadeOffset(client3)); QCOMPARE(client3->size(), QSize(100, 50)); shellSurface3.reset(); QVERIFY(Test::waitForWindowDestroyed(client3)); shellSurface2.reset(); QVERIFY(Test::waitForWindowDestroyed(client2)); shellSurface1.reset(); QVERIFY(Test::waitForWindowDestroyed(client1)); } void TestPlacement::testPlaceRandom() { // This test verifies that Random placement policy works. KConfigGroup group = kwinApp()->config()->group("Windows"); group.writeEntry("Placement", Placement::policyToString(Placement::Random)); group.sync(); workspace()->slotReconfigure(); QScopedPointer surface1(Test::createSurface()); QScopedPointer shellSurface1(Test::createXdgShellStableSurface(surface1.data())); ShellClient *client1 = Test::renderAndWaitForShown(surface1.data(), QSize(100, 50), Qt::red); QVERIFY(client1); QCOMPARE(client1->size(), QSize(100, 50)); QScopedPointer surface2(Test::createSurface()); QScopedPointer shellSurface2(Test::createXdgShellStableSurface(surface2.data())); ShellClient *client2 = Test::renderAndWaitForShown(surface2.data(), QSize(100, 50), Qt::blue); QVERIFY(client2); QVERIFY(client2->pos() != client1->pos()); QCOMPARE(client2->size(), QSize(100, 50)); QScopedPointer surface3(Test::createSurface()); QScopedPointer shellSurface3(Test::createXdgShellStableSurface(surface3.data())); ShellClient *client3 = Test::renderAndWaitForShown(surface3.data(), QSize(100, 50), Qt::green); QVERIFY(client3); QVERIFY(client3->pos() != client1->pos()); QVERIFY(client3->pos() != client2->pos()); QCOMPARE(client3->size(), QSize(100, 50)); shellSurface3.reset(); QVERIFY(Test::waitForWindowDestroyed(client3)); shellSurface2.reset(); QVERIFY(Test::waitForWindowDestroyed(client2)); shellSurface1.reset(); QVERIFY(Test::waitForWindowDestroyed(client1)); } WAYLANDTEST_MAIN(TestPlacement) -#include "placement.moc" +#include "placement_test.moc"