Commit d7c29096 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

Fix shadowless context menus

QtWayland doesn't attach a null buffer to a wl_surface to unmap it,
instead it destroys the wl_surface. This is not wrong, but it breaks a
lot of assumptions about the way how the qpa manages window system
resources.

With this change, KWindowShadow will start using heuristics to keep
track of window system resources and when needed, re-create shadow
objects. We need to use heuristics because there is nothing in public
API that we can use.

It's worth noting that QtWayland provides a private API that you could
use to get notified when the wl_surface object has been destroyed. But
we should use private APIs only if there is no other way around. In
this particular case, we have one (QEvent::Expose and QEvent::Hide).


(cherry picked from commit 3667c199)
parent b856124d
......@@ -19,11 +19,15 @@
*/
#include "windowshadow.h"
#include "logging.h"
#include "waylandintegration.h"
#include <KWayland/Client/shm_pool.h>
#include <KWayland/Client/surface.h>
#include <QDebug>
#include <QExposeEvent>
bool WindowShadowTile::create()
{
KWayland::Client::ShmPool *shmPool = WaylandIntegration::self()->waylandShmPool();
......@@ -54,8 +58,27 @@ static KWayland::Client::Buffer::Ptr bufferForTile(const KWindowShadowTile::Ptr
return d->buffer;
}
bool WindowShadow::create()
bool WindowShadow::eventFilter(QObject *watched, QEvent *event)
{
Q_UNUSED(watched)
if (event->type() == QEvent::Expose) {
QExposeEvent *exposeEvent = static_cast<QExposeEvent *>(event);
if (!exposeEvent->region().isNull()) {
if (!internalCreate()) {
qCWarning(KWAYLAND_KWS) << "Failed to recreate shadow for" << window;
}
}
} else if (event->type() == QEvent::Hide) {
internalDestroy();
}
return false;
}
bool WindowShadow::internalCreate()
{
if (shadow) {
return true;
}
KWayland::Client::ShadowManager *shadowManager = WaylandIntegration::self()->waylandShadowManager();
if (!shadowManager) {
return false;
......@@ -83,20 +106,28 @@ bool WindowShadow::create()
return true;
}
void WindowShadow::destroy()
bool WindowShadow::create()
{
if (!shadow) {
return;
if (!internalCreate()) {
return false;
}
KWayland::Client::ShadowManager *shadowManager = WaylandIntegration::self()->waylandShadowManager();
if (!shadowManager) {
return;
window->installEventFilter(this);
return true;
}
void WindowShadow::internalDestroy()
{
delete shadow;
shadow = nullptr;
if (window) {
window->requestUpdate();
}
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(window);
if (!surface) {
return;
}
void WindowShadow::destroy()
{
if (window) {
window->removeEventFilter(this);
}
shadowManager->removeShadow(surface);
shadow = nullptr;
window->requestUpdate();
internalDestroy();
}
......@@ -36,12 +36,19 @@ public:
KWayland::Client::Buffer::Ptr buffer;
};
class WindowShadow final : public KWindowShadowPrivate
class WindowShadow final : public QObject, public KWindowShadowPrivate
{
public:
bool create() override;
void destroy() override;
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
private:
bool internalCreate();
void internalDestroy();
QPointer<KWayland::Client::Shadow> shadow;
};
......
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