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)
|
void Toplevel::clientMessageEvent(xcb_client_message_event_t *e)
|
||||||
{
|
{
|
||||||
if (e->type == atoms->wl_surface_id) {
|
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 w = waylandServer()) {
|
||||||
if (auto s = KWaylandServer::SurfaceInterface::get(m_surfaceId, w->xWaylandConnection())) {
|
if (auto s = KWaylandServer::SurfaceInterface::get(m_pendingSurfaceId, w->xWaylandConnection())) {
|
||||||
setSurface(s);
|
setSurface(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Q_EMIT surfaceIdChanged(m_surfaceId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -615,11 +615,10 @@ void Toplevel::setSurface(KWaylandServer::SurfaceInterface *surface)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_surface = surface;
|
m_surface = surface;
|
||||||
|
m_pendingSurfaceId = 0;
|
||||||
connect(m_surface, &KWaylandServer::SurfaceInterface::destroyed, this, [this]() {
|
connect(m_surface, &KWaylandServer::SurfaceInterface::destroyed, this, [this]() {
|
||||||
m_surface = nullptr;
|
m_surface = nullptr;
|
||||||
m_surfaceId = 0;
|
|
||||||
});
|
});
|
||||||
m_surfaceId = surface->id();
|
|
||||||
Q_EMIT surfaceChanged();
|
Q_EMIT surfaceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,12 +255,6 @@ class KWIN_EXPORT Toplevel : public QObject
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(bool skipsCloseAnimation READ skipsCloseAnimation WRITE setSkipCloseAnimation NOTIFY skipCloseAnimationChanged)
|
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.
|
* Interface to the Wayland Surface.
|
||||||
* Relevant only in Wayland, in X11 it will be nullptr
|
* Relevant only in Wayland, in X11 it will be nullptr
|
||||||
|
@ -494,7 +488,7 @@ public:
|
||||||
bool skipsCloseAnimation() const;
|
bool skipsCloseAnimation() const;
|
||||||
void setSkipCloseAnimation(bool set);
|
void setSkipCloseAnimation(bool set);
|
||||||
|
|
||||||
quint32 surfaceId() const;
|
quint32 pendingSurfaceId() const;
|
||||||
KWaylandServer::SurfaceInterface *surface() const;
|
KWaylandServer::SurfaceInterface *surface() const;
|
||||||
void setSurface(KWaylandServer::SurfaceInterface *surface);
|
void setSurface(KWaylandServer::SurfaceInterface *surface);
|
||||||
|
|
||||||
|
@ -615,11 +609,6 @@ Q_SIGNALS:
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
void windowClassChanged();
|
void windowClassChanged();
|
||||||
/**
|
|
||||||
* Emitted when a Wayland Surface gets associated with this Toplevel.
|
|
||||||
* @since 5.3
|
|
||||||
*/
|
|
||||||
void surfaceIdChanged(quint32);
|
|
||||||
/**
|
/**
|
||||||
* @since 5.4
|
* @since 5.4
|
||||||
*/
|
*/
|
||||||
|
@ -728,7 +717,7 @@ private:
|
||||||
mutable bool m_shapeRegionIsValid = false;
|
mutable bool m_shapeRegionIsValid = false;
|
||||||
AbstractOutput *m_output = nullptr;
|
AbstractOutput *m_output = nullptr;
|
||||||
bool m_skipCloseAnimation;
|
bool m_skipCloseAnimation;
|
||||||
quint32 m_surfaceId = 0;
|
quint32 m_pendingSurfaceId = 0;
|
||||||
KWaylandServer::SurfaceInterface *m_surface = nullptr;
|
KWaylandServer::SurfaceInterface *m_surface = nullptr;
|
||||||
// when adding new data members, check also copyToDeleted()
|
// when adding new data members, check also copyToDeleted()
|
||||||
qreal m_screenScale = 1.0;
|
qreal m_screenScale = 1.0;
|
||||||
|
@ -969,9 +958,9 @@ inline const ClientMachine *Toplevel::clientMachine() const
|
||||||
return m_clientMachine;
|
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
|
inline KWaylandServer::SurfaceInterface *Toplevel::surface() const
|
||||||
|
|
|
@ -403,7 +403,7 @@ bool WaylandServer::init(InitializationFlags flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
X11Client *client = ws->findClient([surface](const X11Client *client) {
|
X11Client *client = ws->findClient([surface](const X11Client *client) {
|
||||||
return client->surfaceId() == surface->id();
|
return client->pendingSurfaceId() == surface->id();
|
||||||
});
|
});
|
||||||
if (client) {
|
if (client) {
|
||||||
client->setSurface(surface);
|
client->setSurface(surface);
|
||||||
|
@ -411,7 +411,7 @@ bool WaylandServer::init(InitializationFlags flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
Unmanaged *unmanaged = ws->findUnmanaged([surface](const Unmanaged *unmanaged) {
|
Unmanaged *unmanaged = ws->findUnmanaged([surface](const Unmanaged *unmanaged) {
|
||||||
return unmanaged->surfaceId() == surface->id();
|
return unmanaged->pendingSurfaceId() == surface->id();
|
||||||
});
|
});
|
||||||
if (unmanaged) {
|
if (unmanaged) {
|
||||||
unmanaged->setSurface(surface);
|
unmanaged->setSurface(surface);
|
||||||
|
|
Loading…
Reference in a new issue