File indexing completed on 2024-11-10 04:55:56

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2018 Martin Flöser <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "kwin_wayland_test.h"
0010 
0011 #include "cursor.h"
0012 #include "effect/effecthandler.h"
0013 #include "effect/effectloader.h"
0014 #include "wayland_server.h"
0015 #include "workspace.h"
0016 #include "x11window.h"
0017 
0018 #include <KConfigGroup>
0019 
0020 #include <KWayland/Client/connection_thread.h>
0021 #include <KWayland/Client/registry.h>
0022 #include <KWayland/Client/slide.h>
0023 #include <KWayland/Client/surface.h>
0024 
0025 #include <netwm.h>
0026 #include <xcb/xcb_icccm.h>
0027 
0028 using namespace KWin;
0029 static const QString s_socketName = QStringLiteral("wayland_test_effects_wobbly_shade-0");
0030 
0031 class WobblyWindowsShadeTest : public QObject
0032 {
0033     Q_OBJECT
0034 private Q_SLOTS:
0035     void initTestCase();
0036     void init();
0037     void cleanup();
0038 
0039     void testShadeMove();
0040 };
0041 
0042 void WobblyWindowsShadeTest::initTestCase()
0043 {
0044     if (!Test::renderNodeAvailable()) {
0045         QSKIP("no render node available");
0046         return;
0047     }
0048     qRegisterMetaType<KWin::Window *>();
0049     qRegisterMetaType<KWin::Effect *>();
0050     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0051     QVERIFY(waylandServer()->init(s_socketName));
0052     Test::setOutputConfig({
0053         QRect(0, 0, 1280, 1024),
0054         QRect(1280, 0, 1280, 1024),
0055     });
0056 
0057     // disable all effects - we don't want to have it interact with the rendering
0058     auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
0059     KConfigGroup plugins(config, QStringLiteral("Plugins"));
0060     const auto builtinNames = EffectLoader().listOfKnownEffects();
0061     for (QString name : builtinNames) {
0062         plugins.writeEntry(name + QStringLiteral("Enabled"), false);
0063     }
0064 
0065     config->sync();
0066     kwinApp()->setConfig(config);
0067 
0068     qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2"));
0069     qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", "1");
0070     kwinApp()->start();
0071     QVERIFY(applicationStartedSpy.wait());
0072 }
0073 
0074 void WobblyWindowsShadeTest::init()
0075 {
0076     QVERIFY(Test::setupWaylandConnection());
0077 }
0078 
0079 void WobblyWindowsShadeTest::cleanup()
0080 {
0081     Test::destroyWaylandConnection();
0082 
0083     effects->unloadAllEffects();
0084     QVERIFY(effects->loadedEffects().isEmpty());
0085 }
0086 
0087 void WobblyWindowsShadeTest::testShadeMove()
0088 {
0089     // this test simulates the condition from BUG 390953
0090     QVERIFY(effects->loadEffect(QStringLiteral("wobblywindows")));
0091     QVERIFY(effects->isEffectLoaded(QStringLiteral("wobblywindows")));
0092 
0093     Test::XcbConnectionPtr c = Test::createX11Connection();
0094     QVERIFY(!xcb_connection_has_error(c.get()));
0095     const QRect windowGeometry(0, 0, 100, 200);
0096     xcb_window_t windowId = xcb_generate_id(c.get());
0097     xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
0098                       windowGeometry.x(),
0099                       windowGeometry.y(),
0100                       windowGeometry.width(),
0101                       windowGeometry.height(),
0102                       0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
0103     xcb_size_hints_t hints;
0104     memset(&hints, 0, sizeof(hints));
0105     xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
0106     xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
0107     xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
0108     xcb_map_window(c.get(), windowId);
0109     xcb_flush(c.get());
0110 
0111     // we should get a window for it
0112     QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
0113     QVERIFY(windowCreatedSpy.wait());
0114     X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
0115     QVERIFY(window);
0116     QCOMPARE(window->window(), windowId);
0117     QVERIFY(window->isDecorated());
0118     QVERIFY(window->isShadeable());
0119     QVERIFY(!window->isShade());
0120     QVERIFY(window->isActive());
0121 
0122     QSignalSpy readyForPaintingChangedSpy(window, &Window::readyForPaintingChanged);
0123     QVERIFY(readyForPaintingChangedSpy.wait());
0124 
0125     // now shade the window
0126     workspace()->slotWindowShade();
0127     QVERIFY(window->isShade());
0128 
0129     QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
0130 
0131     // begin move
0132     QVERIFY(workspace()->moveResizeWindow() == nullptr);
0133     QCOMPARE(window->isInteractiveMove(), false);
0134     workspace()->slotWindowMove();
0135     QCOMPARE(workspace()->moveResizeWindow(), window);
0136     QCOMPARE(window->isInteractiveMove(), true);
0137     QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
0138 
0139     // wait for frame rendered
0140     QTest::qWait(100);
0141 
0142     // send some key events, not going through input redirection
0143     window->keyPressEvent(Qt::Key_Right);
0144     window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos());
0145 
0146     // wait for frame rendered
0147     QTest::qWait(100);
0148 
0149     window->keyPressEvent(Qt::Key_Right);
0150     window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos());
0151 
0152     // wait for frame rendered
0153     QTest::qWait(100);
0154 
0155     window->keyPressEvent(Qt::Key_Down | Qt::ALT);
0156     window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos());
0157 
0158     // wait for frame rendered
0159     QTest::qWait(100);
0160 
0161     // let's end
0162     window->keyPressEvent(Qt::Key_Enter);
0163 
0164     // wait for frame rendered
0165     QTest::qWait(100);
0166 }
0167 
0168 WAYLANDTEST_MAIN(WobblyWindowsShadeTest)
0169 #include "wobbly_shade_test.moc"