diff --git a/autotests/integration/struts_test.cpp b/autotests/integration/struts_test.cpp index ffaca22be8..67105b9c51 100644 --- a/autotests/integration/struts_test.cpp +++ b/autotests/integration/struts_test.cpp @@ -21,6 +21,7 @@ along with this program. If not, see . #include "platform.h" #include "client.h" #include "cursor.h" +#include "deleted.h" #include "screenedge.h" #include "screens.h" #include "wayland_server.h" @@ -57,6 +58,7 @@ private Q_SLOTS: void testX11Struts_data(); void testX11Struts(); void test363804(); + void testLeftScreenSmallerBottomAligned(); private: KWayland::Client::Compositor *m_compositor = nullptr; @@ -67,6 +69,7 @@ void StrutsTest::initTestCase() { qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); @@ -695,6 +698,116 @@ void StrutsTest::test363804() QVERIFY(windowClosedSpy.wait()); } +void StrutsTest::testLeftScreenSmallerBottomAligned() +{ + // this test verifies a two screen setup with the left screen smaller than the right and bottom aligned + // the panel is on the top of the left screen, thus not at 0/0 + // what this test in addition tests is whether a window larger than the left screen is not placed into + // the dead area + const QVector geometries{QRect(0, 282, 1366, 768), QRect(1366, 0, 1680, 1050)}; + QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + Qt::DirectConnection, + Q_ARG(QVector, geometries)); + QCOMPARE(screens()->geometry(0), geometries.at(0)); + QCOMPARE(screens()->geometry(1), geometries.at(1)); + QCOMPARE(screens()->geometry(), QRect(0, 0, 3046, 1050)); + + // create the panel + QScopedPointer c(xcb_connect(nullptr, nullptr)); + QVERIFY(!xcb_connection_has_error(c.data())); + + xcb_window_t w = xcb_generate_id(c.data()); + const QRect windowGeometry(0, 282, 1366, 24); + 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); + NETWinInfo info(c.data(), w, rootWindow(), NET::WMAllProperties, NET::WM2AllProperties); + info.setWindowType(NET::Dock); + NETExtendedStrut strut; + strut.left_start = 0; + strut.left_end = 0; + strut.left_width = 0; + strut.right_start = 0; + strut.right_end = 0; + strut.right_width = 0; + strut.top_start = 0; + strut.top_end = 1365; + strut.top_width = 306; + strut.bottom_start = 0; + strut.bottom_end = 0; + strut.bottom_width = 0; + info.setExtendedStrut(strut); + 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(); + QVERIFY(client); + QCOMPARE(client->window(), w); + QVERIFY(!client->isDecorated()); + QCOMPARE(client->windowType(), NET::Dock); + QCOMPARE(client->geometry(), windowGeometry); + + // now verify the actual updated client areas + QCOMPARE(workspace()->clientArea(PlacementArea, 0, 1), QRect(0, 306, 1366, 744)); + QCOMPARE(workspace()->clientArea(MaximizeArea, 0, 1), QRect(0, 306, 1366, 744)); + QCOMPARE(workspace()->clientArea(PlacementArea, 1, 1), geometries.at(1)); + QCOMPARE(workspace()->clientArea(MaximizeArea, 1, 1), geometries.at(1)); + QCOMPARE(workspace()->clientArea(WorkArea, 0, 1), QRect(0, 0, 3046, 1050)); + + // now create a window which is larger than screen 0 + + xcb_window_t w2 = xcb_generate_id(c.data()); + const QRect windowGeometry2(0, 26, 1280, 774); + xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w2, rootWindow(), + windowGeometry2.x(), + windowGeometry2.y(), + windowGeometry2.width(), + windowGeometry2.height(), + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); + xcb_size_hints_t hints2; + memset(&hints2, 0, sizeof(hints2)); + xcb_icccm_size_hints_set_min_size(&hints2, 868, 431); + xcb_icccm_set_wm_normal_hints(c.data(), w2, &hints2); + xcb_map_window(c.data(), w2); + xcb_flush(c.data()); + QVERIFY(windowCreatedSpy.wait()); + Client *client2 = windowCreatedSpy.last().first().value(); + QVERIFY(client2); + QVERIFY(client2 != client); + QVERIFY(client2->isDecorated()); + QCOMPARE(client2->geometry(), QRect(0, 306, 1366, 744)); + QCOMPARE(client2->maximizeMode(), KWin::MaximizeFull); + // destroy window again + QSignalSpy normalWindowClosedSpy(client2, &Client::windowClosed); + QVERIFY(normalWindowClosedSpy.isValid()); + xcb_unmap_window(c.data(), w2); + xcb_destroy_window(c.data(), w2); + xcb_flush(c.data()); + QVERIFY(normalWindowClosedSpy.wait()); + + // 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::StrutsTest)