Fix xrandr primary when the new screen is the connected one

We'd trigger updatePrimary before Xwayland had reacted to the new output
so we wouldn't end up calling xcb_randr_set_output_primary() as
necessary.

BUG: 449099
This commit is contained in:
Aleix Pol 2022-01-25 15:17:51 +01:00 committed by Aleix Pol Gonzalez
parent b3abe7526b
commit d1698e1270
3 changed files with 37 additions and 0 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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)
};