Changeset View
Changeset View
Standalone View
Standalone View
autotests/wayland/dont_crash_aurorae_destroy_deco.cpp
- This file was added.
1 | /******************************************************************** | ||||
---|---|---|---|---|---|
2 | KWin - the KDE window manager | ||||
3 | This file is part of the KDE project. | ||||
4 | | ||||
5 | Copyright (C) 2016 Martin Gräßlin <mgraesslin@kde.org> | ||||
6 | | ||||
7 | This program is free software; you can redistribute it and/or modify | ||||
8 | it under the terms of the GNU General Public License as published by | ||||
9 | the Free Software Foundation; either version 2 of the License, or | ||||
10 | (at your option) any later version. | ||||
11 | | ||||
12 | This program is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | GNU General Public License for more details. | ||||
16 | | ||||
17 | You should have received a copy of the GNU General Public License | ||||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | *********************************************************************/ | ||||
20 | #include "kwin_wayland_test.h" | ||||
21 | #include "abstract_backend.h" | ||||
22 | #include "client.h" | ||||
23 | #include "cursor.h" | ||||
24 | #include "screenedge.h" | ||||
25 | #include "screens.h" | ||||
26 | #include "wayland_server.h" | ||||
27 | #include "workspace.h" | ||||
28 | #include "shell_client.h" | ||||
29 | #include <kwineffects.h> | ||||
30 | | ||||
31 | #include <KDecoration2/Decoration> | ||||
32 | | ||||
33 | #include <QQuickItem> | ||||
34 | | ||||
35 | #include <linux/input.h> | ||||
36 | | ||||
37 | namespace KWin | ||||
38 | { | ||||
39 | | ||||
40 | static const QString s_socketName = QStringLiteral("wayland_test_kwin_dont_crash_aurorae_destroy_deco-0"); | ||||
41 | | ||||
42 | class DontCrashAuroraeDestroyDecoTest : public QObject | ||||
43 | { | ||||
44 | Q_OBJECT | ||||
45 | private Q_SLOTS: | ||||
46 | void initTestCase(); | ||||
47 | void init(); | ||||
48 | void testBorderlessMaximizedWindows(); | ||||
49 | | ||||
50 | }; | ||||
51 | | ||||
52 | void DontCrashAuroraeDestroyDecoTest::initTestCase() | ||||
53 | { | ||||
54 | if (!QFile::exists(QStringLiteral("/dev/dri/card0"))) { | ||||
55 | QSKIP("Needs a dri device"); | ||||
56 | } | ||||
57 | qRegisterMetaType<KWin::ShellClient*>(); | ||||
58 | qRegisterMetaType<KWin::AbstractClient*>(); | ||||
59 | QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); | ||||
60 | QVERIFY(workspaceCreatedSpy.isValid()); | ||||
61 | waylandServer()->backend()->setInitialWindowSize(QSize(1280, 1024)); | ||||
62 | QMetaObject::invokeMethod(waylandServer()->backend(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); | ||||
63 | waylandServer()->init(s_socketName.toLocal8Bit()); | ||||
64 | | ||||
65 | KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); | ||||
66 | config->group("org.kde.kdecoration2").writeEntry("library", "org.kde.kwin.aurorae"); | ||||
67 | config->sync(); | ||||
68 | kwinApp()->setConfig(config); | ||||
69 | | ||||
70 | // this test needs to enforce OpenGL compositing to get into the crashy condition | ||||
71 | qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2")); | ||||
72 | kwinApp()->start(); | ||||
73 | QVERIFY(workspaceCreatedSpy.wait()); | ||||
74 | QCOMPARE(screens()->count(), 2); | ||||
75 | QCOMPARE(screens()->geometry(0), QRect(0, 0, 1280, 1024)); | ||||
76 | QCOMPARE(screens()->geometry(1), QRect(1280, 0, 1280, 1024)); | ||||
77 | setenv("QT_QPA_PLATFORM", "wayland", true); | ||||
78 | waylandServer()->initWorkspace(); | ||||
79 | } | ||||
80 | | ||||
81 | void DontCrashAuroraeDestroyDecoTest::init() | ||||
82 | { | ||||
83 | screens()->setCurrent(0); | ||||
84 | Cursor::setPos(QPoint(640, 512)); | ||||
85 | } | ||||
86 | | ||||
87 | void DontCrashAuroraeDestroyDecoTest::testBorderlessMaximizedWindows() | ||||
88 | { | ||||
89 | // this test verifies that Aurorae doesn't crash when clicking the maximize button | ||||
90 | // with kwin config option BorderlessMaximizedWindows | ||||
91 | // see BUG 362772 | ||||
92 | | ||||
93 | // first adjust the config | ||||
94 | KConfigGroup group = kwinApp()->config()->group("Windows"); | ||||
95 | group.writeEntry("BorderlessMaximizedWindows", true); | ||||
96 | group.sync(); | ||||
97 | workspace()->slotReconfigure(); | ||||
98 | QCOMPARE(options->borderlessMaximizedWindows(), true); | ||||
99 | | ||||
100 | // create an xcb window | ||||
101 | xcb_connection_t *c = xcb_connect(nullptr, nullptr); | ||||
102 | QVERIFY(!xcb_connection_has_error(c)); | ||||
103 | | ||||
104 | xcb_window_t w = xcb_generate_id(c); | ||||
105 | xcb_create_window(c, XCB_COPY_FROM_PARENT, w, rootWindow(), 0, 0, 100, 200, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); | ||||
106 | xcb_map_window(c, w); | ||||
107 | xcb_flush(c); | ||||
108 | | ||||
109 | // we should get a client for it | ||||
110 | QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded); | ||||
111 | QVERIFY(windowCreatedSpy.isValid()); | ||||
112 | QVERIFY(windowCreatedSpy.wait()); | ||||
113 | Client *client = windowCreatedSpy.first().first().value<Client*>(); | ||||
114 | QVERIFY(client); | ||||
115 | QCOMPARE(client->window(), w); | ||||
116 | QVERIFY(client->isDecorated()); | ||||
117 | QCOMPARE(client->maximizeMode(), MaximizeRestore); | ||||
118 | QCOMPARE(client->noBorder(), false); | ||||
119 | // verify that the deco is Aurorae | ||||
120 | QCOMPARE(qstrcmp(client->decoration()->metaObject()->className(), "Aurorae::Decoration"), 0); | ||||
121 | // find the maximize button | ||||
122 | QQuickItem *item = client->decoration()->findChild<QQuickItem*>("maximizeButton"); | ||||
123 | QVERIFY(item); | ||||
124 | const QPointF scenePoint = item->mapToScene(QPoint(0, 0)); | ||||
125 | | ||||
126 | // mark the window as ready for painting, otherwise it doesn't get input events | ||||
127 | QMetaObject::invokeMethod(client, "setReadyForPainting"); | ||||
128 | QVERIFY(client->readyForPainting()); | ||||
129 | | ||||
130 | // simulate click on maximize button | ||||
131 | QSignalSpy maximizedStateChangedSpy(client, static_cast<void (AbstractClient::*)(KWin::AbstractClient*, MaximizeMode)>(&AbstractClient::clientMaximizedStateChanged)); | ||||
132 | QVERIFY(maximizedStateChangedSpy.isValid()); | ||||
133 | quint32 timestamp = 1; | ||||
134 | waylandServer()->backend()->pointerMotion(client->geometry().topLeft() + scenePoint.toPoint(), timestamp++); | ||||
135 | waylandServer()->backend()->pointerButtonPressed(BTN_LEFT, timestamp++); | ||||
136 | waylandServer()->backend()->pointerButtonReleased(BTN_LEFT, timestamp++); | ||||
137 | QVERIFY(maximizedStateChangedSpy.wait()); | ||||
138 | QCOMPARE(client->maximizeMode(), MaximizeFull); | ||||
139 | QCOMPARE(client->noBorder(), true); | ||||
140 | | ||||
141 | // and destroy the window again | ||||
142 | xcb_unmap_window(c, w); | ||||
143 | xcb_destroy_window(c, w); | ||||
144 | xcb_flush(c); | ||||
145 | xcb_disconnect(c); | ||||
146 | | ||||
147 | QSignalSpy windowClosedSpy(client, &Client::windowClosed); | ||||
148 | QVERIFY(windowClosedSpy.isValid()); | ||||
149 | QVERIFY(windowClosedSpy.wait()); | ||||
150 | } | ||||
151 | | ||||
152 | } | ||||
153 | | ||||
154 | WAYLANDTEST_MAIN(KWin::DontCrashAuroraeDestroyDecoTest) | ||||
155 | #include "dont_crash_aurorae_destroy_deco.moc" |