diff --git a/src/utils/xcbutils.cpp b/src/utils/xcbutils.cpp index 337a9a07c2..a6dc48e5a0 100644 --- a/src/utils/xcbutils.cpp +++ b/src/utils/xcbutils.cpp @@ -364,6 +364,7 @@ Extensions::~Extensions() void Extensions::init() { xcb_connection_t *c = connection(); + Q_ASSERT(c); xcb_prefetch_extension_data(c, &xcb_shape_id); xcb_prefetch_extension_data(c, &xcb_randr_id); xcb_prefetch_extension_data(c, &xcb_damage_id); diff --git a/src/xwl/xwayland.cpp b/src/xwl/xwayland.cpp index 6887beaea1..3257d9bd02 100644 --- a/src/xwl/xwayland.cpp +++ b/src/xwl/xwayland.cpp @@ -22,6 +22,7 @@ #include "utils/xcbutils.h" #include "wayland_server.h" #include "xwayland_logging.h" +#include "x11eventfilter.h" #include "xwaylandsocket.h" @@ -55,6 +56,31 @@ namespace KWin namespace Xwl { +class XrandrEventFilter : public X11EventFilter +{ +public: + explicit XrandrEventFilter(Xwayland *backend); + + bool event(xcb_generic_event_t *event) override; + +private: + Xwayland *const m_backend; +}; + +XrandrEventFilter::XrandrEventFilter(Xwayland *backend) + : X11EventFilter(Xcb::Extensions::self()->randrNotifyEvent()) + , m_backend(backend) +{ +} + +bool XrandrEventFilter::event(xcb_generic_event_t *event) +{ + Q_ASSERT((event->response_type & ~0x80) == Xcb::Extensions::self()->randrNotifyEvent()); + m_backend->updatePrimary(kwinApp()->platform()->primaryOutput()); + return false; +} + + Xwayland::Xwayland(ApplicationWaylandAbstract *app, QObject *parent) : XwaylandInterface(parent) , m_app(app) @@ -221,6 +247,9 @@ void Xwayland::stopInternal() Q_ASSERT(m_xwaylandProcess); m_app->setClosingX11Connection(true); + delete m_xrandrEventsFilter; + m_xrandrEventsFilter = nullptr; + // If Xwayland has crashed, we must deactivate the socket notifier and ensure that no X11 // events will be dispatched before blocking; otherwise we will simply hang... uninstallSocketNotifier(); @@ -407,6 +436,9 @@ void Xwayland::handleXwaylandReady() updatePrimary(kwinApp()->platform()->primaryOutput()); Xcb::sync(); // Trigger possible errors, there's still a chance to abort + + delete m_xrandrEventsFilter; + m_xrandrEventsFilter = new XrandrEventFilter(this); } void Xwayland::updatePrimary(AbstractOutput *primaryOutput) diff --git a/src/xwl/xwayland.h b/src/xwl/xwayland.h index 180b527c6c..54cfb5f15d 100644 --- a/src/xwl/xwayland.h +++ b/src/xwl/xwayland.h @@ -26,6 +26,7 @@ class XwaylandSocket; namespace Xwl { +class XrandrEventFilter; class KWIN_EXPORT Xwayland : public XwaylandInterface { @@ -113,6 +114,8 @@ private Q_SLOTS: void handleSelectionClaimedOwnership(); private: + friend class XrandrEventFilter; + void installSocketNotifier(); void uninstallSocketNotifier(); void maybeDestroyReadyNotifier(); @@ -143,6 +146,7 @@ private: QString m_xAuthority; int m_crashCount = 0; + XrandrEventFilter *m_xrandrEventsFilter = nullptr; Q_DISABLE_COPY(Xwayland) };