From 76af96bcc9b6948440c328f169607cf925702adf Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Mon, 27 Apr 2020 21:44:12 +0300 Subject: [PATCH] [x11] Disable synchronized resizing for Xwayland < 1.21 In case Xwayland does not use multiple buffers, the currently attached buffer is going to be destroyed if the frame window is resized. It may render the previous and the current window pixmap invalid and thus result in visual artifacts when an X11 client is being interactively resized. In order to avoid the visual artifacts, this change disables support for synchronized resizing for X11 clients if the version of Xwayland is less than the version in which Xwayland started using multiple buffers, i.e. 1.21. Differential Revision: https://phabricator.kde.org/D29250 --- CMakeLists.txt | 1 + workspace.cpp | 8 +++++++- x11client.cpp | 10 ++++++++++ x11client.h | 6 +++--- xwaylandclient.cpp | 37 +++++++++++++++++++++++++++++++++++++ xwaylandclient.h | 39 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 xwaylandclient.cpp create mode 100644 xwaylandclient.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 897224c8d4..f9a40ee43a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -509,6 +509,7 @@ set(kwin_SRCS xcbutils.cpp xdgshellclient.cpp xkb.cpp + xwaylandclient.cpp xwl/xwayland_interface.cpp ) diff --git a/workspace.cpp b/workspace.cpp index 6f9cf8429a..cba14d24a0 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -62,6 +62,7 @@ along with this program. If not, see . #include "xcbutils.h" #include "main.h" #include "decorations/decorationbridge.h" +#include "xwaylandclient.h" // KDE #include #include @@ -528,7 +529,12 @@ void Workspace::setupClientConnections(AbstractClient *c) X11Client *Workspace::createClient(xcb_window_t w, bool is_mapped) { StackingUpdatesBlocker blocker(this); - X11Client *c = new X11Client(); + X11Client *c = nullptr; + if (kwinApp()->operationMode() == Application::OperationModeX11) { + c = new X11Client(); + } else { + c = new XwaylandClient(); + } setupClientConnections(c); if (X11Compositor *compositor = X11Compositor::self()) { connect(c, &X11Client::blockingCompositingChanged, compositor, &X11Compositor::updateClientCompositeBlocking); diff --git a/x11client.cpp b/x11client.cpp index 7322902d21..77b157a146 100644 --- a/x11client.cpp +++ b/x11client.cpp @@ -2342,10 +2342,20 @@ void X11Client::getIcons() setIcon(icon); } +/** + * Returns \c true if X11Client wants to throttle resizes; otherwise returns \c false. + */ +bool X11Client::wantsSyncCounter() const +{ + return true; +} + void X11Client::getSyncCounter() { if (!Xcb::Extensions::self()->isSyncAvailable()) return; + if (!wantsSyncCounter()) + return; Xcb::Property syncProp(false, window(), atoms->net_wm_sync_request_counter, XCB_ATOM_CARDINAL, 0, 1); const xcb_sync_counter_t counter = syncProp.value(XCB_NONE); diff --git a/x11client.h b/x11client.h index 0bc52ce19b..45ddce691d 100644 --- a/x11client.h +++ b/x11client.h @@ -85,6 +85,8 @@ class KWIN_EXPORT X11Client : public AbstractClient Q_PROPERTY(bool clientSideDecorated READ isClientSideDecorated NOTIFY clientSideDecoratedChanged) public: explicit X11Client(); + ~X11Client() override; ///< Use destroyClient() or releaseWindow() + xcb_window_t wrapperId() const; xcb_window_t inputId() const { return m_decoInputExtent; } xcb_window_t frameId() const override; @@ -320,6 +322,7 @@ public: const SyncRequest &syncRequest() const { return m_syncRequest; } + virtual bool wantsSyncCounter() const; void handleSync(); static void cleanupX11(); @@ -333,9 +336,6 @@ private Q_SLOTS: void shadeUnhover(); private: - // Use Workspace::createClient() - ~X11Client() override; ///< Use destroyClient() or releaseWindow() - // Handlers for X11 events bool mapRequestEvent(xcb_map_request_event_t *e); void unmapNotifyEvent(xcb_unmap_notify_event_t *e); diff --git a/xwaylandclient.cpp b/xwaylandclient.cpp new file mode 100644 index 0000000000..f0376f302e --- /dev/null +++ b/xwaylandclient.cpp @@ -0,0 +1,37 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2020 Vlad Zahorodnii + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "xwaylandclient.h" + +namespace KWin +{ + +bool XwaylandClient::wantsSyncCounter() const +{ + // When the frame window is resized, the attached buffer will be destroyed by + // Xwayland, causing unexpected invalid previous and current window pixmaps. + // With the addition of multiple window buffers in Xwayland 1.21, X11 clients + // are no longer able to destroy the buffer after it's been committed and not + // released by the compositor yet. + static const quint32 xwaylandVersion = xcb_get_setup(connection())->release_number; + return xwaylandVersion >= 12100000; +} + +} // namespace KWin diff --git a/xwaylandclient.h b/xwaylandclient.h new file mode 100644 index 0000000000..2560918921 --- /dev/null +++ b/xwaylandclient.h @@ -0,0 +1,39 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2020 Vlad Zahorodnii + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#pragma once + +#include "x11client.h" + +namespace KWin +{ + +/** + * The XwaylandClient class represents a managed Xwayland client. + */ +class XwaylandClient : public X11Client +{ + Q_OBJECT + +public: + bool wantsSyncCounter() const override; +}; + +} // namespace KWin