xdgshell: Use killPingTimeout option

This makes it consistent with the timeout used on X11.

The current ping timeout was also generally quite short, causing apps
to desaturate for brief moments when they were busy e.g. starting up
or loading large files.
This commit is contained in:
Kai Uwe Broulik 2023-11-23 14:48:04 +01:00 committed by Vlad Zahorodnii
parent 28c1545beb
commit 2b868edb9e
7 changed files with 56 additions and 7 deletions

View file

@ -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()

View file

@ -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)
{

View file

@ -10,6 +10,8 @@
#include <QObject>
#include <QSharedDataPointer>
#include <chrono>
#include <memory>
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.

View file

@ -31,6 +31,7 @@ public:
XdgShellInterface *q;
Display *display = nullptr;
QMap<quint32, QTimer *> pings;
std::chrono::milliseconds pingTimeout = std::chrono::milliseconds(1000);
protected:
void xdg_wm_base_destroy_resource(Resource *resource) override;

View file

@ -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);

View file

@ -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

View file

@ -8,9 +8,12 @@
#include "waylandshellintegration.h"
#include <chrono>
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