From 9acf04e2b741a851ffef88b3eadb5402d659dde8 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 6 Feb 2021 00:18:45 +0200 Subject: [PATCH] Refactor Toplevel::opacity The major difference between this version and the previous is that kwin no longer forwards the opacity to the app window if it runs as a window window manager and a compositing manager. As Keith Packard said [1] > The window manager support is only needed to forward the property from the > application window to the frame; with the Composite extension, a > compositing manager can then take that value into account when > constructing the desktop image. Any X server can implement the Composite > extension; the one in the X server project at freedesktop.org is just one > such. It would be trivial to implement this extension in a direct FB > based X server, or any other X server which places windows in off-screen > images. There are a couple of reasons to do so: (a) simplifies code, (b) we don't temper with opacities on override-redirect windows. [1] https://listman.redhat.com/archives/xdg-list/2003-December/msg00153.html --- deleted.cpp | 6 ------ deleted.h | 2 -- events.cpp | 8 ++------ internal_client.cpp | 19 ------------------- internal_client.h | 3 --- toplevel.cpp | 23 ++++++++--------------- toplevel.h | 5 +++-- waylandclient.cpp | 17 ----------------- waylandclient.h | 3 --- x11client.cpp | 3 ++- 10 files changed, 15 insertions(+), 74 deletions(-) diff --git a/deleted.cpp b/deleted.cpp index a93fa8da50..1e3d3b9013 100644 --- a/deleted.cpp +++ b/deleted.cpp @@ -95,7 +95,6 @@ void Deleted::copyToDeleted(Toplevel* c) transparent_rect = c->transparentRect(); m_layer = c->layer(); m_frame = c->frameId(); - m_opacity = c->opacity(); m_type = c->windowType(); m_windowRole = c->windowRole(); if (WinInfo* cinfo = dynamic_cast< WinInfo* >(info)) @@ -252,11 +251,6 @@ xcb_window_t Deleted::frameId() const return m_frame; } -double Deleted::opacity() const -{ - return m_opacity; -} - QByteArray Deleted::windowRole() const { return m_windowRole; diff --git a/deleted.h b/deleted.h index 3d545894cf..8e7d34c4dd 100644 --- a/deleted.h +++ b/deleted.h @@ -64,7 +64,6 @@ public: bool wasClient() const { return m_wasClient; } - double opacity() const override; QByteArray windowRole() const override; const Decoration::Renderer *decorationRenderer() const { @@ -206,7 +205,6 @@ private: QList m_mainClients; bool m_wasClient; Decoration::Renderer *m_decorationRenderer; - double m_opacity; NET::WindowType m_type = NET::Unknown; QByteArray m_windowRole; bool m_fullscreen; diff --git a/events.cpp b/events.cpp index 7f5b2f585b..8963856bfc 100644 --- a/events.cpp +++ b/events.cpp @@ -446,7 +446,6 @@ bool X11Client::windowEvent(xcb_generic_event_t *e) if (findEventWindow(e) == window()) { // avoid doing stuff on frame or wrapper NET::Properties dirtyProperties; NET::Properties2 dirtyProperties2; - double old_opacity = opacity(); info->event(e, &dirtyProperties, &dirtyProperties2); // pass through the NET stuff if ((dirtyProperties & NET::WMName) != 0) @@ -470,8 +469,7 @@ bool X11Client::windowEvent(xcb_generic_event_t *e) startupIdChanged(); if (dirtyProperties2 & NET::WM2Opacity) { if (compositing()) { - addRepaintFull(); - emit opacityChanged(this, old_opacity); + setOpacity(info->opacityF()); } else { // forward to the frame if there's possibly another compositing manager running NETWinInfo i(connection(), frameId(), rootWindow(), NET::Properties(), NET::Properties2()); @@ -1298,14 +1296,12 @@ void X11Client::keyPressEvent(uint key_code, xcb_timestamp_t time) bool Unmanaged::windowEvent(xcb_generic_event_t *e) { - double old_opacity = opacity(); NET::Properties dirtyProperties; NET::Properties2 dirtyProperties2; info->event(e, &dirtyProperties, &dirtyProperties2); // pass through the NET stuff if (dirtyProperties2 & NET::WM2Opacity) { if (compositing()) { - addRepaintFull(); - emit opacityChanged(this, old_opacity); + setOpacity(info->opacityF()); } } if (dirtyProperties2 & NET::WM2OpaqueRegion) { diff --git a/internal_client.cpp b/internal_client.cpp index 02fd1d0a77..3b9e05dd86 100644 --- a/internal_client.cpp +++ b/internal_client.cpp @@ -38,8 +38,6 @@ InternalClient::InternalClient(QWindow *window) connect(m_internalWindow, &QWindow::opacityChanged, this, &InternalClient::setOpacity); connect(m_internalWindow, &QWindow::destroyed, this, &InternalClient::destroyClient); - connect(this, &InternalClient::opacityChanged, this, &InternalClient::addRepaintFull); - const QVariant windowType = m_internalWindow->property("kwin_windowType"); if (!windowType.isNull()) { m_windowType = windowType.value(); @@ -149,23 +147,6 @@ NET::WindowType InternalClient::windowType(bool direct, int supported_types) con return m_windowType; } -qreal InternalClient::opacity() const -{ - return m_opacity; -} - -void InternalClient::setOpacity(qreal opacity) -{ - if (m_opacity == opacity) { - return; - } - - const double oldOpacity = m_opacity; - m_opacity = opacity; - - emit opacityChanged(this, oldOpacity); -} - void InternalClient::killWindow() { // We don't kill our internal windows. diff --git a/internal_client.h b/internal_client.h index 49d9f916a4..27820e6696 100644 --- a/internal_client.h +++ b/internal_client.h @@ -35,8 +35,6 @@ public: QSize maxSize() const override; QRect transparentRect() const override; NET::WindowType windowType(bool direct = false, int supported_types = 0) const override; - qreal opacity() const override; - void setOpacity(qreal opacity) override; void killWindow() override; bool isPopupWindow() const override; QByteArray windowRole() const override; @@ -88,7 +86,6 @@ private: QWindow *m_internalWindow = nullptr; QString m_captionNormal; QString m_captionSuffix; - qreal m_opacity = 1.0; NET::WindowType m_windowType = NET::Normal; Qt::WindowFlags m_internalWindowFlags = Qt::WindowFlags(); bool m_userNoBorder = false; diff --git a/toplevel.cpp b/toplevel.cpp index e1ad28a6e0..8fad16c88d 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -129,6 +129,7 @@ void Toplevel::copyToDeleted(Toplevel* c) m_skipCloseAnimation = c->m_skipCloseAnimation; m_internalFBO = c->m_internalFBO; m_internalImage = c->m_internalImage; + m_opacity = c->m_opacity; } // before being deleted, remove references to everything that's now @@ -249,28 +250,20 @@ bool Toplevel::resourceMatch(const Toplevel *c1, const Toplevel *c2) qreal Toplevel::opacity() const { - if (!info) { - return 1.0; - } - if (info->opacity() == 0xffffffff) - return 1.0; - return info->opacity() * 1.0 / 0xffffffff; + return m_opacity; } -void Toplevel::setOpacity(qreal new_opacity) +void Toplevel::setOpacity(qreal opacity) { - if (!info) { + opacity = qBound(0.0, opacity, 1.0); + if (m_opacity == opacity) { return; } - - qreal old_opacity = opacity(); - new_opacity = qBound(0.0, new_opacity, 1.0); - if (old_opacity == new_opacity) - return; - info->setOpacity(static_cast< unsigned long >(new_opacity * 0xffffffff)); + const qreal oldOpacity = m_opacity; + m_opacity = opacity; if (compositing()) { addRepaintFull(); - emit opacityChanged(this, old_opacity); + emit opacityChanged(this, oldOpacity); } } diff --git a/toplevel.h b/toplevel.h index 0f9f7fe0f6..c87bfdef7b 100644 --- a/toplevel.h +++ b/toplevel.h @@ -448,8 +448,8 @@ public: xcb_visualid_t visual() const; bool shape() const; QRegion inputShape() const; - virtual void setOpacity(qreal opacity); - virtual qreal opacity() const; + void setOpacity(qreal opacity); + qreal opacity() const; int depth() const; bool hasAlpha() const; virtual bool setupCompositing(); @@ -756,6 +756,7 @@ private: KWaylandServer::SurfaceInterface *m_surface = nullptr; // when adding new data members, check also copyToDeleted() qreal m_screenScale = 1.0; + qreal m_opacity = 1.0; }; inline xcb_window_t Toplevel::window() const diff --git a/waylandclient.cpp b/waylandclient.cpp index d5a9dd7245..637eaeafc9 100644 --- a/waylandclient.cpp +++ b/waylandclient.cpp @@ -107,23 +107,6 @@ bool WaylandClient::isLocalhost() const return true; } -qreal WaylandClient::opacity() const -{ - return m_opacity; -} - -void WaylandClient::setOpacity(qreal opacity) -{ - const qreal newOpacity = qBound(0.0, opacity, 1.0); - if (newOpacity == m_opacity) { - return; - } - const qreal oldOpacity = m_opacity; - m_opacity = newOpacity; - addRepaintFull(); - emit opacityChanged(this, oldOpacity); -} - AbstractClient *WaylandClient::findModal(bool allow_itself) { Q_UNUSED(allow_itself) diff --git a/waylandclient.h b/waylandclient.h index 2694fe8e69..f3117210dd 100644 --- a/waylandclient.h +++ b/waylandclient.h @@ -34,8 +34,6 @@ public: pid_t pid() const override; bool isLockScreen() const override; bool isLocalhost() const override; - qreal opacity() const override; - void setOpacity(qreal opacity) override; AbstractClient *findModal(bool allow_itself = false) override; void resizeWithChecks(const QSize &size, ForceGeometry_t force = NormalGeometrySet) override; void setFrameGeometry(const QRect &rect, ForceGeometry_t force = NormalGeometrySet) override; @@ -81,7 +79,6 @@ private: QString m_captionNormal; QString m_captionSuffix; - qreal m_opacity = 1.0; QRect m_requestedFrameGeometry; QRect m_bufferGeometry; QRect m_requestedClientGeometry; diff --git a/x11client.cpp b/x11client.cpp index 960fc24c41..fe5a0abebd 100644 --- a/x11client.cpp +++ b/x11client.cpp @@ -777,6 +777,7 @@ bool X11Client::manage(xcb_window_t w, bool isMapped) demandAttention(); if (info->state() & NET::Modal) setModal(true); + setOpacity(info->opacityF()); setFullScreen(rules()->checkFullScreen(info->state() & NET::FullScreen, !isMapped), false); } @@ -876,7 +877,7 @@ bool X11Client::manage(xcb_window_t w, bool isMapped) return; } NETWinInfo info(connection(), frameId(), rootWindow(), NET::Properties(), NET::Properties2()); - info.setOpacity(static_cast(opacity() * 0xffffffff)); + info.setOpacityF(opacity()); } );