KWin
Loading...
Searching...
No Matches
translucency_test.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "kwin_wayland_test.h"
10
11#include "compositor.h"
13#include "effect/effectloader.h"
14#include "pointer_input.h"
15#include "virtualdesktops.h"
16#include "wayland_server.h"
17#include "workspace.h"
18#include "x11window.h"
19
20#include <KConfigGroup>
21
22#include <netwm.h>
23#include <xcb/xcb_icccm.h>
24
25using namespace KWin;
26static const QString s_socketName = QStringLiteral("wayland_test_effects_translucency-0");
27
28class TranslucencyTest : public QObject
29{
30 Q_OBJECT
31private Q_SLOTS:
32 void initTestCase();
33 void init();
34 void cleanup();
35
36 void testMoveAfterDesktopChange();
37 void testDialogClose();
38
39private:
40 Effect *m_translucencyEffect = nullptr;
41};
42
43void TranslucencyTest::initTestCase()
44{
45 qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8());
46 qRegisterMetaType<KWin::Window *>();
47 qRegisterMetaType<KWin::Effect *>();
48 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
49 QVERIFY(waylandServer()->init(s_socketName));
51 QRect(0, 0, 1280, 1024),
52 QRect(1280, 0, 1280, 1024),
53 });
54
55 // disable all effects - we don't want to have it interact with the rendering
56 auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
57 KConfigGroup plugins(config, QStringLiteral("Plugins"));
58 const auto builtinNames = EffectLoader().listOfKnownEffects();
59 for (QString name : builtinNames) {
60 plugins.writeEntry(name + QStringLiteral("Enabled"), false);
61 }
62 config->group(QStringLiteral("Outline")).writeEntry(QStringLiteral("QmlPath"), QString("/does/not/exist.qml"));
63 config->group(QStringLiteral("Effect-translucency")).writeEntry(QStringLiteral("Dialogs"), 90);
64
65 config->sync();
66 kwinApp()->setConfig(config);
67
68 qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", "1");
69 kwinApp()->start();
70 QVERIFY(applicationStartedSpy.wait());
71 QVERIFY(Compositor::self());
72}
73
74void TranslucencyTest::init()
75{
76 // find the effectsloader
77 auto effectloader = effects->findChild<AbstractEffectLoader *>();
78 QVERIFY(effectloader);
79 QSignalSpy effectLoadedSpy(effectloader, &AbstractEffectLoader::effectLoaded);
80
81 QVERIFY(!effects->isEffectLoaded(QStringLiteral("translucency")));
82 QVERIFY(effects->loadEffect(QStringLiteral("translucency")));
83 QVERIFY(effects->isEffectLoaded(QStringLiteral("translucency")));
84
85 QCOMPARE(effectLoadedSpy.count(), 1);
86 m_translucencyEffect = effectLoadedSpy.first().first().value<Effect *>();
87 QVERIFY(m_translucencyEffect);
88}
89
90void TranslucencyTest::cleanup()
91{
92 if (effects->isEffectLoaded(QStringLiteral("translucency"))) {
93 effects->unloadEffect(QStringLiteral("translucency"));
94 }
95 QVERIFY(!effects->isEffectLoaded(QStringLiteral("translucency")));
96 m_translucencyEffect = nullptr;
97}
98
99void TranslucencyTest::testMoveAfterDesktopChange()
100{
101 // test tries to simulate the condition of bug 366081
102 QVERIFY(!m_translucencyEffect->isActive());
103
104 QSignalSpy windowAddedSpy(effects, &EffectsHandler::windowAdded);
105
106 // create an xcb window
108 QVERIFY(!xcb_connection_has_error(c.get()));
109 const QRect windowGeometry(0, 0, 100, 200);
110 xcb_window_t windowId = xcb_generate_id(c.get());
111 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
112 windowGeometry.x(),
113 windowGeometry.y(),
114 windowGeometry.width(),
115 windowGeometry.height(),
116 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
117 xcb_size_hints_t hints;
118 memset(&hints, 0, sizeof(hints));
119 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
120 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
121 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
122 xcb_map_window(c.get(), windowId);
123 xcb_flush(c.get());
124
125 // we should get a window for it
126 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
127 QVERIFY(windowCreatedSpy.wait());
128 X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
129 QVERIFY(window);
130 QCOMPARE(window->window(), windowId);
131 QVERIFY(window->isDecorated());
132
133 QCOMPARE(windowAddedSpy.count(), 1);
134 QVERIFY(!m_translucencyEffect->isActive());
135 // let's send the window to desktop 2
136 VirtualDesktopManager *vds = VirtualDesktopManager::self();
137 vds->setCount(2);
138 const QList<VirtualDesktop *> desktops = vds->desktops();
139 workspace()->sendWindowToDesktops(window, {desktops[1]}, false);
140 vds->setCurrent(desktops[1]);
141 QVERIFY(!m_translucencyEffect->isActive());
142 KWin::input()->pointer()->warp(window->frameGeometry().center());
144 QVERIFY(m_translucencyEffect->isActive());
145 QTest::qWait(200);
146 QVERIFY(m_translucencyEffect->isActive());
147 // now end move resize
148 window->endInteractiveMoveResize();
149 QVERIFY(m_translucencyEffect->isActive());
150 QTest::qWait(500);
151 QTRY_VERIFY(!m_translucencyEffect->isActive());
152
153 // and destroy the window again
154 xcb_unmap_window(c.get(), windowId);
155 xcb_flush(c.get());
156
157 QSignalSpy windowClosedSpy(window, &X11Window::closed);
158 QVERIFY(windowClosedSpy.wait());
159 xcb_destroy_window(c.get(), windowId);
160 c.reset();
161}
162
163void TranslucencyTest::testDialogClose()
164{
165 // this test simulates the condition of BUG 342716
166 // with translucency settings for window type dialog the effect never ends when the window gets destroyed
167 QVERIFY(!m_translucencyEffect->isActive());
168 QSignalSpy windowAddedSpy(effects, &EffectsHandler::windowAdded);
169
170 // create an xcb window
172 QVERIFY(!xcb_connection_has_error(c.get()));
173 const QRect windowGeometry(0, 0, 100, 200);
174 xcb_window_t windowId = xcb_generate_id(c.get());
175 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
176 windowGeometry.x(),
177 windowGeometry.y(),
178 windowGeometry.width(),
179 windowGeometry.height(),
180 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
181 xcb_size_hints_t hints;
182 memset(&hints, 0, sizeof(hints));
183 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
184 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
185 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
186 NETWinInfo winInfo(c.get(), windowId, rootWindow(), NET::Properties(), NET::Properties2());
187 winInfo.setWindowType(NET::Dialog);
188 xcb_map_window(c.get(), windowId);
189 xcb_flush(c.get());
190
191 // we should get a window for it
192 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
193 QVERIFY(windowCreatedSpy.wait());
194 X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
195 QVERIFY(window);
196 QCOMPARE(window->window(), windowId);
197 QVERIFY(window->isDecorated());
198 QVERIFY(window->isDialog());
199
200 QCOMPARE(windowAddedSpy.count(), 1);
201 QTRY_VERIFY(m_translucencyEffect->isActive());
202 // and destroy the window again
203 xcb_unmap_window(c.get(), windowId);
204 xcb_flush(c.get());
205
206 QSignalSpy windowClosedSpy(window, &X11Window::closed);
207
208 QSignalSpy windowDeletedSpy(effects, &EffectsHandler::windowDeleted);
209 QVERIFY(windowClosedSpy.wait());
210 if (windowDeletedSpy.isEmpty()) {
211 QVERIFY(windowDeletedSpy.wait());
212 }
213 QCOMPARE(windowDeletedSpy.count(), 1);
214 QTRY_VERIFY(!m_translucencyEffect->isActive());
215 xcb_destroy_window(c.get(), windowId);
216 c.reset();
217}
218
220#include "translucency_test.moc"
Interface to describe how an effect loader has to function.
void effectLoaded(KWin::Effect *effect, const QString &name)
The loader emits this signal when it successfully loaded an effect.
static Compositor * self()
Base class for all KWin effects.
Definition effect.h:535
QStringList listOfKnownEffects() const override
All the Effects this loader knows of.
Q_SCRIPTABLE void unloadEffect(const QString &name)
void windowDeleted(KWin::EffectWindow *w)
Q_SCRIPTABLE bool loadEffect(const QString &name)
Q_SCRIPTABLE bool isEffectLoaded(const QString &name) const
void windowAdded(KWin::EffectWindow *w)
PointerInputRedirection * pointer() const
Definition input.h:220
void warp(const QPointF &pos)
Manages the number of available virtual desktops, the layout of those and which virtual desktop is th...
QList< VirtualDesktop * > desktops() const
QRectF frameGeometry
Definition window.h:431
bool isDialog() const
Definition window.h:1952
void endInteractiveMoveResize()
Definition window.cpp:2614
bool isDecorated() const
Definition window.h:1162
void performWindowOperation(KWin::Window *window, Options::WindowOperation op)
void windowAdded(KWin::Window *)
void sendWindowToDesktops(Window *window, const QList< VirtualDesktop * > &desktops, bool dont_activate)
xcb_window_t window() const
virtual bool isActive() const
Definition effect.cpp:447
#define WAYLANDTEST_MAIN(TestObject)
void setOutputConfig(const QList< QRect > &geometries)
XcbConnectionPtr createX11Connection()
std::unique_ptr< xcb_connection_t, XcbConnectionDeleter > XcbConnectionPtr
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
InputRedirection * input()
Definition input.h:549
EffectsHandler * effects