[wayland] Flush QtWaylands wl_display and KWin's wayland server when processing events
QtWayland and mesa might dead lock KWin if we start rendering a QWindow before Qt/Mesa got the last frame callback. They perform blocking wayland event reading on the main gui thread which makes it impossible for KWin to do the compositing and send the callback. To workaround this problem we fake a frameRendered directly after each damage event for a Qt internal window. Unfortunately this is not yet completely sufficient, thus we also need to ensure that the wayland events are processed before any events are processed which would cause a repaint and block. Thus we first flush QtWayland's wl_display and then our Server connection. If there were any damage events we can be sure that the frameRendered is sent before Qt attempts to render.
This commit is contained in:
parent
29c2ae57e0
commit
74ae2f503e
3 changed files with 26 additions and 0 deletions
|
@ -324,6 +324,7 @@ EventDispatcher::~EventDispatcher() = default;
|
|||
|
||||
bool EventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
{
|
||||
waylandServer()->dispatch();
|
||||
const bool didSendEvents = QEventDispatcherUNIX::processEvents(flags);
|
||||
return QWindowSystemInterface::sendWindowSystemEvents(flags) || didSendEvents;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,13 @@ void WaylandServer::init(const QByteArray &socketName)
|
|||
fakeDummyQtWindowInput();
|
||||
return;
|
||||
}
|
||||
// HACK: in order to get Qt to not block for frame rendered, we immediatelly emit the
|
||||
// frameRendered once we get a new damage event.
|
||||
auto s = surface->surface();
|
||||
connect(s, &SurfaceInterface::damaged, this, [this, s] {
|
||||
s->frameRendered(0);
|
||||
m_qtConnection->flush();
|
||||
});
|
||||
}
|
||||
auto client = new ShellClient(surface);
|
||||
if (auto c = Compositor::self()) {
|
||||
|
@ -238,4 +245,20 @@ void WaylandServer::fakeDummyQtWindowInput()
|
|||
#endif
|
||||
}
|
||||
|
||||
void WaylandServer::dispatch()
|
||||
{
|
||||
if (!m_display) {
|
||||
return;
|
||||
}
|
||||
if (!m_qtClientConnection) {
|
||||
if (m_qtConnection && QGuiApplication::instance()) {
|
||||
m_qtClientConnection = KWayland::Client::ConnectionThread::fromApplication(this);
|
||||
}
|
||||
}
|
||||
if (m_qtClientConnection) {
|
||||
m_qtClientConnection->flush();
|
||||
}
|
||||
m_display->dispatchEvents(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ public:
|
|||
KWayland::Client::ConnectionThread *internalClientConection() {
|
||||
return m_internalConnection.client;
|
||||
}
|
||||
void dispatch();
|
||||
|
||||
Q_SIGNALS:
|
||||
void shellClientAdded(ShellClient*);
|
||||
|
@ -119,6 +120,7 @@ private:
|
|||
KWayland::Server::ShellInterface *m_shell = nullptr;
|
||||
KWayland::Server::ClientConnection *m_xwaylandConnection = nullptr;
|
||||
KWayland::Server::ClientConnection *m_qtConnection = nullptr;
|
||||
KWayland::Client::ConnectionThread *m_qtClientConnection = nullptr;
|
||||
struct {
|
||||
KWayland::Server::ClientConnection *server = nullptr;
|
||||
KWayland::Client::ConnectionThread *client = nullptr;
|
||||
|
|
Loading…
Reference in a new issue