From 769f2659ddfff8096b826238595a26e5f21c39ad Mon Sep 17 00:00:00 2001 From: Vlad Zagorodniy Date: Mon, 8 Oct 2018 21:08:13 +0300 Subject: [PATCH] [effects] Make Scale and Glide effects Wayland-friendly Summary: The Scale effect and the Glide effect have to animate only ordinary windows(i.e. the ones that are considered to be apps). On X11, in order to distinguish ordinary windows from combo box popups, popup menus, and other popups, those effects check whether given window is managed. On Wayland, there is no concept of managed/unmanaged windows. XDG Shell protocol defines 2 surface roles: * xdg_toplevel; * and, xdg_popup. The former can be used to implement typical windows, the ones that can be minimized, maximized, etc. The latter can be used to implement tooltips, popup menus, etc. Thus, that's a good criteria to filter popup windows. CCBUG: 398100 Reviewers: #kwin, graesslin, davidedmundson Reviewed By: #kwin, graesslin, davidedmundson Subscribers: davidedmundson, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D15117 --- effects/glide/glide.cpp | 9 +++++++- effects/scale/scale.cpp | 9 +++++++- libkwineffects/kwineffects.cpp | 21 +++++++++++++++++++ libkwineffects/kwineffects.h | 38 ++++++++++++++++++++++++++++++++++ shell_client.cpp | 11 ++++++++++ shell_client.h | 2 ++ toplevel.h | 28 +++++++++++++++++++++++++ 7 files changed, 116 insertions(+), 2 deletions(-) diff --git a/effects/glide/glide.cpp b/effects/glide/glide.cpp index 6962d1374f..7a63ee01f4 100644 --- a/effects/glide/glide.cpp +++ b/effects/glide/glide.cpp @@ -313,7 +313,14 @@ bool GlideEffect::isGlideWindow(EffectWindow *w) const return true; } - if (!w->isManaged()) { + // Don't animate combobox popups, tooltips, popup menus, etc. + if (w->isPopupWindow()) { + return false; + } + + // Override-redirect windows are usually used for user interface + // concepts that are not expected to be animated by this effect. + if (w->isX11Client() && !w->isManaged()) { return false; } diff --git a/effects/scale/scale.cpp b/effects/scale/scale.cpp index f3d41c0167..6584de0fe4 100644 --- a/effects/scale/scale.cpp +++ b/effects/scale/scale.cpp @@ -274,7 +274,14 @@ bool ScaleEffect::isScaleWindow(EffectWindow *w) const return true; } - if (!w->isManaged()) { + // Don't animate combobox popups, tooltips, popup menus, etc. + if (w->isPopupWindow()) { + return false; + } + + // Override-redirect windows are usually used for user interface + // concepts that are not expected to be animated by this effect. + if (w->isX11Client() && !w->isManaged()) { return false; } diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp index 437e662567..197136b8e4 100644 --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -776,6 +776,9 @@ public: EffectWindow *q; bool managed = false; + bool waylandClient; + bool x11Client; + bool popupWindow; }; EffectWindow::Private::Private(EffectWindow *q) @@ -795,6 +798,10 @@ EffectWindow::EffectWindow(QObject *parent) // an instance of Deleted becomes parent of the EffectWindow, effects // can still figure out whether it is/was a managed window. d->managed = parent->property("managed").value(); + + d->waylandClient = parent->inherits("KWin::ShellClient"); + d->x11Client = !d->waylandClient; + d->popupWindow = parent->property("popupWindow").value(); } EffectWindow::~EffectWindow() @@ -992,6 +999,20 @@ bool EffectWindow::isManaged() const return d->managed; } +bool EffectWindow::isWaylandClient() const +{ + return d->waylandClient; +} + +bool EffectWindow::isX11Client() const +{ + return d->x11Client; +} + +bool EffectWindow::isPopupWindow() const +{ + return d->popupWindow; +} //**************************************** // EffectWindowGroup diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index 6246eb8291..dd14ec2b6f 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1979,6 +1979,29 @@ class KWINEFFECTS_EXPORT EffectWindow : public QObject * @since 5.10 */ Q_PROPERTY(bool unresponsive READ isUnresponsive) + + /** + * Whether this is a Wayland client. + * @since 5.15 + **/ + Q_PROPERTY(bool waylandClient READ isWaylandClient CONSTANT) + + /** + * Whether this is an X11 client. + * @since 5.15 + **/ + Q_PROPERTY(bool x11Client READ isX11Client CONSTANT) + + /** + * Whether the window is a popup. + * + * A popup is a window that can be used to implement tooltips, combo box popups, + * popup menus and other similar user interface concepts. + * + * @since 5.15 + **/ + Q_PROPERTY(bool popupWindow READ isPopupWindow CONSTANT) + public: /** Flags explaining why painting should be disabled */ enum { @@ -2230,6 +2253,21 @@ public: */ bool isUnresponsive() const; + /** + * @since 5.15 + **/ + bool isWaylandClient() const; + + /** + * @since 5.15 + **/ + bool isX11Client() const; + + /** + * @since 5.15 + **/ + bool isPopupWindow() const; + /** * Can be used to by effects to store arbitrary data in the EffectWindow. * diff --git a/shell_client.cpp b/shell_client.cpp index ace5697520..af019c7a73 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -1768,4 +1768,15 @@ void ShellClient::updateClientOutputs() surface()->setOutputs(clientOutputs); } +bool ShellClient::isPopupWindow() const +{ + if (m_shellSurface != nullptr) { + return m_shellSurface->isPopup(); + } + if (m_xdgShellPopup != nullptr) { + return true; + } + return false; +} + } diff --git a/shell_client.h b/shell_client.h index f9ea0e65e8..4c28e92e23 100644 --- a/shell_client.h +++ b/shell_client.h @@ -166,6 +166,8 @@ public: void updateColorScheme() override; + bool isPopupWindow() const override; + protected: void addDamage(const QRegion &damage) override; bool belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const override; diff --git a/toplevel.h b/toplevel.h index 77ad278bd7..be8542d3d2 100644 --- a/toplevel.h +++ b/toplevel.h @@ -210,6 +210,11 @@ class KWIN_EXPORT Toplevel */ Q_PROPERTY(KWayland::Server::SurfaceInterface *surface READ surface) + /** + * Whether the window is a popup. + **/ + Q_PROPERTY(bool popupWindow READ isPopupWindow) + public: explicit Toplevel(); virtual xcb_window_t frameId() const; @@ -443,6 +448,15 @@ public: template static T *findInList(const QList &list, std::function func); + /** + * Whether the window is a popup. + * + * Popups can be used to implement popup menus, tooltips, combo boxes, etc. + * + * @since 5.15 + **/ + virtual bool isPopupWindow() const; + Q_SIGNALS: void opacityChanged(KWin::Toplevel* toplevel, qreal oldOpacity); void damaged(KWin::Toplevel* toplevel, const QRect& damage); @@ -846,6 +860,20 @@ inline T *Toplevel::findInList(const QList &list, std::function