wayland: Reset Toplevel::surfaceId after surface is created
Xwayland will re-create the wl_surface object if the X11 window is unmapped and mapped. That, and the fact that the order in which the WL_SURFACE_ID client message event is received and the wl_surface object is created is undefined can cause the following bug: * WL_SURFACE_ID is received * the old wl_surface object is destroyed, m_surfaceId is reset to 0 * new wl_surface is created but because m_surfaceId is 0, it won't be associated with the x11 window This change ensures that kwin will associate the wl_surface with x11 window by making it not reset cached surface id when the old wl_surface is destroyed. However, we cannot leave m_surfaceId as is because wayland aggressively re-uses object ids so kwin can associate wrong surface with x11 window. To prevent that, this change also makes Toplevel::setSurface() reset cached surface id. CCBUG: 442936 CCBUG: 426069
This commit is contained in:
parent
61eb8ce75b
commit
52c9dbb487
4 changed files with 9 additions and 22 deletions
|
@ -1285,13 +1285,12 @@ void Toplevel::propertyNotifyEvent(xcb_property_notify_event_t *e)
|
|||
void Toplevel::clientMessageEvent(xcb_client_message_event_t *e)
|
||||
{
|
||||
if (e->type == atoms->wl_surface_id) {
|
||||
m_surfaceId = e->data.data32[0];
|
||||
m_pendingSurfaceId = e->data.data32[0];
|
||||
if (auto w = waylandServer()) {
|
||||
if (auto s = KWaylandServer::SurfaceInterface::get(m_surfaceId, w->xWaylandConnection())) {
|
||||
if (auto s = KWaylandServer::SurfaceInterface::get(m_pendingSurfaceId, w->xWaylandConnection())) {
|
||||
setSurface(s);
|
||||
}
|
||||
}
|
||||
Q_EMIT surfaceIdChanged(m_surfaceId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -615,11 +615,10 @@ void Toplevel::setSurface(KWaylandServer::SurfaceInterface *surface)
|
|||
return;
|
||||
}
|
||||
m_surface = surface;
|
||||
m_pendingSurfaceId = 0;
|
||||
connect(m_surface, &KWaylandServer::SurfaceInterface::destroyed, this, [this]() {
|
||||
m_surface = nullptr;
|
||||
m_surfaceId = 0;
|
||||
});
|
||||
m_surfaceId = surface->id();
|
||||
Q_EMIT surfaceChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -255,12 +255,6 @@ class KWIN_EXPORT Toplevel : public QObject
|
|||
*/
|
||||
Q_PROPERTY(bool skipsCloseAnimation READ skipsCloseAnimation WRITE setSkipCloseAnimation NOTIFY skipCloseAnimationChanged)
|
||||
|
||||
/**
|
||||
* The Id of the Wayland Surface associated with this Toplevel.
|
||||
* On X11 only setups the value is @c 0.
|
||||
*/
|
||||
Q_PROPERTY(quint32 surfaceId READ surfaceId NOTIFY surfaceIdChanged)
|
||||
|
||||
/**
|
||||
* Interface to the Wayland Surface.
|
||||
* Relevant only in Wayland, in X11 it will be nullptr
|
||||
|
@ -494,7 +488,7 @@ public:
|
|||
bool skipsCloseAnimation() const;
|
||||
void setSkipCloseAnimation(bool set);
|
||||
|
||||
quint32 surfaceId() const;
|
||||
quint32 pendingSurfaceId() const;
|
||||
KWaylandServer::SurfaceInterface *surface() const;
|
||||
void setSurface(KWaylandServer::SurfaceInterface *surface);
|
||||
|
||||
|
@ -615,11 +609,6 @@ Q_SIGNALS:
|
|||
* @since 5.0
|
||||
*/
|
||||
void windowClassChanged();
|
||||
/**
|
||||
* Emitted when a Wayland Surface gets associated with this Toplevel.
|
||||
* @since 5.3
|
||||
*/
|
||||
void surfaceIdChanged(quint32);
|
||||
/**
|
||||
* @since 5.4
|
||||
*/
|
||||
|
@ -728,7 +717,7 @@ private:
|
|||
mutable bool m_shapeRegionIsValid = false;
|
||||
AbstractOutput *m_output = nullptr;
|
||||
bool m_skipCloseAnimation;
|
||||
quint32 m_surfaceId = 0;
|
||||
quint32 m_pendingSurfaceId = 0;
|
||||
KWaylandServer::SurfaceInterface *m_surface = nullptr;
|
||||
// when adding new data members, check also copyToDeleted()
|
||||
qreal m_screenScale = 1.0;
|
||||
|
@ -969,9 +958,9 @@ inline const ClientMachine *Toplevel::clientMachine() const
|
|||
return m_clientMachine;
|
||||
}
|
||||
|
||||
inline quint32 Toplevel::surfaceId() const
|
||||
inline quint32 Toplevel::pendingSurfaceId() const
|
||||
{
|
||||
return m_surfaceId;
|
||||
return m_pendingSurfaceId;
|
||||
}
|
||||
|
||||
inline KWaylandServer::SurfaceInterface *Toplevel::surface() const
|
||||
|
|
|
@ -403,7 +403,7 @@ bool WaylandServer::init(InitializationFlags flags)
|
|||
}
|
||||
|
||||
X11Client *client = ws->findClient([surface](const X11Client *client) {
|
||||
return client->surfaceId() == surface->id();
|
||||
return client->pendingSurfaceId() == surface->id();
|
||||
});
|
||||
if (client) {
|
||||
client->setSurface(surface);
|
||||
|
@ -411,7 +411,7 @@ bool WaylandServer::init(InitializationFlags flags)
|
|||
}
|
||||
|
||||
Unmanaged *unmanaged = ws->findUnmanaged([surface](const Unmanaged *unmanaged) {
|
||||
return unmanaged->surfaceId() == surface->id();
|
||||
return unmanaged->pendingSurfaceId() == surface->id();
|
||||
});
|
||||
if (unmanaged) {
|
||||
unmanaged->setSurface(surface);
|
||||
|
|
Loading…
Reference in a new issue