diff --git a/autotests/integration/xdgshellwindow_test.cpp b/autotests/integration/xdgshellwindow_test.cpp index ee16edb79d..7f9d657f36 100644 --- a/autotests/integration/xdgshellwindow_test.cpp +++ b/autotests/integration/xdgshellwindow_test.cpp @@ -822,7 +822,8 @@ void TestXdgShellWindow::testUnresponsiveWindow() QVERIFY(unresponsiveSpy.wait()); // window should be marked unresponsive but not killed auto elapsed1 = QDateTime::currentMSecsSinceEpoch() - startTime; - QVERIFY(elapsed1 > 900 && elapsed1 < 1200); // ping timer is 1s, but coarse timers on a test across two processes means we need a fuzzy compare + const int timeout = options->killPingTimeout() / 2; + QVERIFY(elapsed1 > timeout - 200 && elapsed1 < timeout + 200); // coarse timers on a test across two processes means we need a fuzzy compare QVERIFY(killWindow->unresponsive()); QVERIFY(killedSpy.isEmpty()); @@ -833,7 +834,7 @@ void TestXdgShellWindow::testUnresponsiveWindow() } auto elapsed2 = QDateTime::currentMSecsSinceEpoch() - startTime; - QVERIFY(elapsed2 > 1800); // second ping comes in a second later + QVERIFY(elapsed2 > timeout * 2 - 200); // second ping comes in later } void TestXdgShellWindow::testAppMenu() diff --git a/src/wayland/xdgshell.cpp b/src/wayland/xdgshell.cpp index 3a587692a0..a371f4db1b 100644 --- a/src/wayland/xdgshell.cpp +++ b/src/wayland/xdgshell.cpp @@ -41,7 +41,8 @@ void XdgShellInterfacePrivate::unregisterXdgSurface(XdgSurfaceInterface *surface void XdgShellInterfacePrivate::registerPing(quint32 serial) { QTimer *timer = new QTimer(q); - timer->setInterval(1000); + // we'll run the timer twice. + timer->setInterval(pingTimeout / 2); QObject::connect(timer, &QTimer::timeout, q, [this, serial, attempt = 0]() mutable { ++attempt; if (attempt == 1) { @@ -134,6 +135,16 @@ quint32 XdgShellInterface::ping(XdgSurfaceInterface *surface) return serial; } +std::chrono::milliseconds XdgShellInterface::pingTimeoutInterval() const +{ + return d->pingTimeout; +} + +void XdgShellInterface::setPingTimeoutInterval(std::chrono::milliseconds pingTimeout) +{ + d->pingTimeout = pingTimeout; +} + XdgSurfaceInterfacePrivate::XdgSurfaceInterfacePrivate(XdgSurfaceInterface *xdgSurface) : q(xdgSurface) { diff --git a/src/wayland/xdgshell.h b/src/wayland/xdgshell.h index c4822f8f5c..72e6536190 100644 --- a/src/wayland/xdgshell.h +++ b/src/wayland/xdgshell.h @@ -10,6 +10,8 @@ #include #include + +#include #include struct wl_resource; @@ -65,6 +67,16 @@ public: */ quint32 ping(XdgSurfaceInterface *surface); + /** + * Returns the ping timeout. + */ + std::chrono::milliseconds pingTimeoutInterval() const; + + /** + * Set the ping timeout. + */ + void setPingTimeoutInterval(std::chrono::milliseconds pingTimeout); + Q_SIGNALS: /** * This signal is emitted when a new XdgToplevelInterface object is created. diff --git a/src/wayland/xdgshell_p.h b/src/wayland/xdgshell_p.h index 8b79d3f9b5..8e9329ae0a 100644 --- a/src/wayland/xdgshell_p.h +++ b/src/wayland/xdgshell_p.h @@ -31,6 +31,7 @@ public: XdgShellInterface *q; Display *display = nullptr; QMap pings; + std::chrono::milliseconds pingTimeout = std::chrono::milliseconds(1000); protected: void xdg_wm_base_destroy_resource(Resource *resource) override; diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp index 3feb35f121..aa8790c7ae 100644 --- a/src/wayland_server.cpp +++ b/src/wayland_server.cpp @@ -18,6 +18,7 @@ #include "layershellv1integration.h" #include "layershellv1window.h" #include "main.h" +#include "options.h" #include "utils/serviceutils.h" #include "virtualdesktops.h" #include "wayland/appmenu.h" @@ -519,6 +520,12 @@ void WaylandServer::initWorkspace() connect(xdgShellIntegration, &XdgShellIntegration::windowCreated, this, &WaylandServer::registerXdgGenericWindow); + auto setPingTimeout = [xdgShellIntegration] { + xdgShellIntegration->setPingTimeout(std::chrono::milliseconds(options->killPingTimeout())); + }; + connect(options, &Options::killPingTimeoutChanged, xdgShellIntegration, setPingTimeout); + setPingTimeout(); + auto layerShellV1Integration = new LayerShellV1Integration(this); connect(layerShellV1Integration, &LayerShellV1Integration::windowCreated, this, &WaylandServer::registerWindow); diff --git a/src/xdgshellintegration.cpp b/src/xdgshellintegration.cpp index 205163294e..6791de402f 100644 --- a/src/xdgshellintegration.cpp +++ b/src/xdgshellintegration.cpp @@ -28,15 +28,24 @@ namespace KWin XdgShellIntegration::XdgShellIntegration(QObject *parent) : WaylandShellIntegration(parent) + , m_shell(new XdgShellInterface(waylandServer()->display(), this)) { - XdgShellInterface *shell = new XdgShellInterface(waylandServer()->display(), this); - - connect(shell, &XdgShellInterface::toplevelCreated, + connect(m_shell, &XdgShellInterface::toplevelCreated, this, &XdgShellIntegration::registerXdgToplevel); - connect(shell, &XdgShellInterface::popupCreated, + connect(m_shell, &XdgShellInterface::popupCreated, this, &XdgShellIntegration::registerXdgPopup); } +std::chrono::milliseconds XdgShellIntegration::pingTimeout() const +{ + return m_shell->pingTimeoutInterval(); +} + +void XdgShellIntegration::setPingTimeout(std::chrono::milliseconds pingTimeout) +{ + m_shell->setPingTimeoutInterval(pingTimeout); +} + void XdgShellIntegration::registerXdgToplevel(XdgToplevelInterface *toplevel) { // Note that the window is going to be destroyed and immediately re-created when the diff --git a/src/xdgshellintegration.h b/src/xdgshellintegration.h index 78c9a4fe62..50db9baf8d 100644 --- a/src/xdgshellintegration.h +++ b/src/xdgshellintegration.h @@ -8,9 +8,12 @@ #include "waylandshellintegration.h" +#include + namespace KWin { +class XdgShellInterface; class XdgToplevelInterface; class XdgPopupInterface; @@ -21,10 +24,15 @@ class XdgShellIntegration : public WaylandShellIntegration public: explicit XdgShellIntegration(QObject *parent = nullptr); + std::chrono::milliseconds pingTimeout() const; + void setPingTimeout(std::chrono::milliseconds pingTimeout); + private: void registerXdgToplevel(XdgToplevelInterface *toplevel); void registerXdgPopup(XdgPopupInterface *popup); void createXdgToplevelWindow(XdgToplevelInterface *surface); + + XdgShellInterface *m_shell; }; } // namespace KWin