[autotests/integration] Test another multi-screen setup

The struts test is extended by a setup containing two horizontal
screens, bottom aligned with the left screen smaller than the right.
Thus there is a dead area in the top left corner. In addition there's
a panel on top left screen.

Apparently KWin allowed windows to open in the dead area. The test
case reconstructs this by opening a window with the same size hints,
but in the test it's working correctly.
This commit is contained in:
Martin Gräßlin 2016-07-13 07:59:18 +02:00
parent 231132ea30
commit f8d556e630

View file

@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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<KWin::ShellClient*>();
qRegisterMetaType<KWin::AbstractClient*>();
qRegisterMetaType<KWin::Deleted*>();
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<QRect> geometries{QRect(0, 282, 1366, 768), QRect(1366, 0, 1680, 1050)};
QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged",
Qt::DirectConnection,
Q_ARG(QVector<QRect>, 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<xcb_connection_t, XcbConnectionDeleter> 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<Client*>();
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<Client*>();
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)