Commit 0a0c3f23 authored by David Edmundson's avatar David Edmundson

Track surface creation/destruction inside wayland window effects

Summary:
The wayland surface is destroyed and recreated after every hide/show. As
it's a new surface, it needs a new blur attached and applied.

The best hook is the expose event on the window.

The current event filtering in Breeze operates on the QWidget which
doesn't match the window. Fixing there still introduces a second layer
of event filters on another object once the window is known.

Whilst it could be done in breeze, clients should ideally just call
KWindowEffects once per window and forget about it regardless of
the underlying state. It also fixes all other wayland users of the call
at once.

This fixes blur on context menus opened a second time.

BUG: 398899

Test Plan:
Turned on the show transparency effect in breeze
Opened a context menu multiple times
Observed that it was transparent and blurred

Reviewers: #kwin

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D20951
parent e2db5ce3
......@@ -24,6 +24,8 @@
#include <QDebug>
#include <QWidget>
#include <QGuiApplication>
#include <QExposeEvent>
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/plasmawindowmanagement.h>
......@@ -45,6 +47,71 @@ WindowEffects::WindowEffects()
WindowEffects::~WindowEffects()
{}
QWindow *WindowEffects::windowForId(WId wid)
{
QWindow *window = nullptr;
for (auto win : qApp->allWindows()) {
if (win->winId() == wid) {
window = win;
break;
}
}
return window;
}
void WindowEffects::trackWindow(QWindow *window)
{
if (!m_windowWatchers.contains(window)) {
window->installEventFilter(this);
auto conn = connect(window, &QObject::destroyed, this, [this, window]() {
m_blurRegions.remove(window);
m_backgroundConstrastRegions.remove(window);
m_windowWatchers.remove(window);
});
m_windowWatchers[window] = conn;
}
}
void WindowEffects::releaseWindow(QWindow *window)
{
if (!m_blurRegions.contains(window) && !m_backgroundConstrastRegions.contains(window)) {
disconnect(m_windowWatchers[window]);
window->removeEventFilter(this);
m_windowWatchers.remove(window);
}
}
bool WindowEffects::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::Expose) {
auto ee = static_cast<QExposeEvent*>(event);
if ((ee->region().isNull())) {
return false;
}
auto window = qobject_cast<QWindow *>(watched);
if (!window) {
return false;
}
{
auto it = m_blurRegions.constFind(window);
if (it != m_blurRegions.constEnd()) {
enableBlurBehind(window, true, *it);
}
}
{
auto it = m_backgroundConstrastRegions.constFind(window);
if (it != m_backgroundConstrastRegions.constEnd()) {
enableBackgroundContrast(window, true, it->contrast, it->intensity, it->saturation, it->region);
}
}
}
return false;
}
bool WindowEffects::isEffectAvailable(KWindowEffects::Effect effect)
{
switch (effect) {
......@@ -128,12 +195,30 @@ void WindowEffects::highlightWindows(WId controller, const QList<WId> &ids)
Q_UNUSED(ids)
}
void WindowEffects::enableBlurBehind(WId window, bool enable, const QRegion &region)
void WindowEffects::enableBlurBehind(WId winId, bool enable, const QRegion &region)
{
auto window = windowForId(winId);
if (!window) {
return;
}
if (enable) {
trackWindow(window);
m_blurRegions[window] = region;
} else {
m_blurRegions.remove(window);
releaseWindow(window);
}
enableBlurBehind(window, enable, region);
}
void WindowEffects::enableBlurBehind(QWindow *window, bool enable, const QRegion &region)
{
if (!WaylandIntegration::self()->waylandBlurManager()) {
return;
}
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromQtWinId(window);
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(window);
if (surface) {
if (enable) {
auto blur = WaylandIntegration::self()->waylandBlurManager()->createBlur(surface, surface);
......@@ -148,12 +233,32 @@ void WindowEffects::enableBlurBehind(WId window, bool enable, const QRegion &reg
}
}
void WindowEffects::enableBackgroundContrast(WId window, bool enable, qreal contrast, qreal intensity, qreal saturation, const QRegion &region)
void WindowEffects::enableBackgroundContrast(WId winId, bool enable, qreal contrast, qreal intensity, qreal saturation, const QRegion &region)
{
auto window = windowForId(winId);
if (!window) {
return;
}
if (enable) {
trackWindow(window);
m_backgroundConstrastRegions[window].contrast = contrast;
m_backgroundConstrastRegions[window].intensity = intensity;
m_backgroundConstrastRegions[window].saturation = saturation;
m_backgroundConstrastRegions[window].region = region;
} else {
m_backgroundConstrastRegions.remove(window);
releaseWindow(window);
}
enableBackgroundContrast(window, enable, contrast, intensity, saturation, region);
}
void WindowEffects::enableBackgroundContrast(QWindow *window, bool enable, qreal contrast, qreal intensity, qreal saturation, const QRegion &region)
{
if (!WaylandIntegration::self()->waylandContrastManager()) {
return;
}
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromQtWinId(window);
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(window);
if (surface) {
if (enable) {
auto backgroundContrast = WaylandIntegration::self()->waylandContrastManager()->createContrast(surface, surface);
......
......@@ -36,10 +36,17 @@ namespace KWayland
class WindowEffects : public QObject, public KWindowEffectsPrivate
{
Q_OBJECT
public:
WindowEffects();
~WindowEffects() override;
static QWindow *windowForId(WId);
bool eventFilter(QObject *watched, QEvent *event) override;
void trackWindow(QWindow *window);
void releaseWindow(QWindow *window);
bool isEffectAvailable(KWindowEffects::Effect effect) override;
void slideWindow(WId id, KWindowEffects::SlideFromLocation location, int offset) override;
void slideWindow(QWidget *widget, KWindowEffects::SlideFromLocation location) override;
......@@ -47,9 +54,22 @@ public:
void presentWindows(WId controller, const QList<WId> &ids) override;
void presentWindows(WId controller, int desktop = NET::OnAllDesktops) override;
void highlightWindows(WId controller, const QList<WId> &ids) override;
void enableBlurBehind(WId window, bool enable = true, const QRegion &region = QRegion()) override;
void enableBackgroundContrast(WId window, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion &region = QRegion()) override;
void enableBlurBehind(WId winId, bool enable = true, const QRegion &region = QRegion()) override;
void enableBlurBehind(QWindow *window, bool enable, const QRegion &region);
void enableBackgroundContrast(WId winId, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion &region = QRegion()) override;
void enableBackgroundContrast(QWindow *window, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion &region = QRegion());
void markAsDashboard(WId window) override;
private:
QHash<QWindow *, QMetaObject::Connection> m_windowWatchers;
QHash<QWindow *, QRegion> m_blurRegions;
struct BackgroundContrastData {
qreal contrast = 1;
qreal intensity = 1;
qreal saturation = 1;
QRegion region;
};
QHash<QWindow *, BackgroundContrastData> m_backgroundConstrastRegions;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment