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)