mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 10:04:19 -05:00
compositor: double buffered states needs their own bit (#15645)
6484f43 introduced state merging, which showed a flaw with mako. a
second commit with just changing geometry was handled as a "empty"
commit and ignored. all protocols that listen to commit and is double
buffered as in state applied on next commit needs their own updated.bits.flag
to ensure the statequeue knows something is pending.
synced subsurface also needs to set the parent flag, because its waiting
for it to commit.
This commit is contained in:
@@ -28,6 +28,7 @@ void CAlphaModifier::setResource(UP<CWpAlphaModifierSurfaceV1>&& resource) {
|
||||
}
|
||||
|
||||
m_alpha = alpha / sc<float>(UINT32_MAX);
|
||||
markPending();
|
||||
});
|
||||
|
||||
m_listeners.surfaceCommitted = m_surface->m_events.commit.listen([this] {
|
||||
@@ -54,11 +55,17 @@ void CAlphaModifier::setResource(UP<CWpAlphaModifierSurfaceV1>&& resource) {
|
||||
void CAlphaModifier::destroy() {
|
||||
m_resource.reset();
|
||||
m_alpha = 1.F;
|
||||
markPending();
|
||||
|
||||
if (!m_surface)
|
||||
PROTO::alphaModifier->destroyAlphaModifier(this);
|
||||
}
|
||||
|
||||
void CAlphaModifier::markPending() {
|
||||
if (m_surface)
|
||||
m_surface->m_pending.updated.bits.alphaModifier = true;
|
||||
}
|
||||
|
||||
CAlphaModifierProtocol::CAlphaModifierProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class CAlphaModifier {
|
||||
float m_alpha = 1.0;
|
||||
|
||||
void destroy();
|
||||
void markPending();
|
||||
|
||||
struct {
|
||||
CHyprSignalListener surfaceCommitted;
|
||||
|
||||
@@ -31,10 +31,12 @@ void CBackgroundEffect::setResource(SP<CExtBackgroundEffectSurfaceV1> resource)
|
||||
|
||||
if (!region) {
|
||||
m_blurRegion.clear();
|
||||
markPending();
|
||||
return;
|
||||
}
|
||||
|
||||
m_blurRegion = CWLRegionResource::fromResource(region)->m_region;
|
||||
markPending();
|
||||
});
|
||||
|
||||
m_listeners.surfaceCommitted = m_surface->m_events.commit.listen([this] {
|
||||
@@ -68,9 +70,15 @@ void CBackgroundEffect::setResource(SP<CExtBackgroundEffectSurfaceV1> resource)
|
||||
});
|
||||
}
|
||||
|
||||
void CBackgroundEffect::markPending() {
|
||||
if (m_surface)
|
||||
m_surface->m_pending.updated.bits.backgroundEffect = true;
|
||||
}
|
||||
|
||||
void CBackgroundEffect::destroy() {
|
||||
m_resource.reset();
|
||||
m_blurRegion.clear();
|
||||
markPending();
|
||||
// The spec requires effect removal to be double-buffered: state is cleared on next wl_surface commit.
|
||||
// If the surface is already destroyed, clean up immediately.
|
||||
if (!m_surface)
|
||||
|
||||
@@ -23,6 +23,7 @@ class CBackgroundEffect {
|
||||
CRegion m_blurRegion;
|
||||
|
||||
void destroy();
|
||||
void markPending();
|
||||
|
||||
struct {
|
||||
CHyprSignalListener surfaceCommitted;
|
||||
|
||||
@@ -36,6 +36,7 @@ void CHyprlandSurface::setResource(SP<CHyprlandSurfaceV1> resource) {
|
||||
}
|
||||
|
||||
m_opacity = fOpacity;
|
||||
markPending();
|
||||
});
|
||||
|
||||
m_resource->setSetVisibleRegion([this](CHyprlandSurfaceV1* resource, wl_resource* region) {
|
||||
@@ -44,11 +45,13 @@ void CHyprlandSurface::setResource(SP<CHyprlandSurfaceV1> resource) {
|
||||
m_visibleRegionChanged = true;
|
||||
|
||||
m_visibleRegion.clear();
|
||||
markPending();
|
||||
return;
|
||||
}
|
||||
|
||||
m_visibleRegionChanged = true;
|
||||
m_visibleRegion = CWLRegionResource::fromResource(region)->m_region;
|
||||
markPending();
|
||||
});
|
||||
|
||||
m_listeners.surfaceCommitted = m_surface->m_events.commit.listen([this] {
|
||||
@@ -81,11 +84,17 @@ void CHyprlandSurface::destroy() {
|
||||
m_visibleRegionChanged = true;
|
||||
|
||||
m_visibleRegion.clear();
|
||||
markPending();
|
||||
|
||||
if (!m_surface)
|
||||
PROTO::hyprlandSurface->destroySurface(this);
|
||||
}
|
||||
|
||||
void CHyprlandSurface::markPending() {
|
||||
if (m_surface)
|
||||
m_surface->m_pending.updated.bits.hyprlandSurface = true;
|
||||
}
|
||||
|
||||
CHyprlandSurfaceProtocol::CHyprlandSurfaceProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ class CHyprlandSurface {
|
||||
CRegion m_visibleRegion;
|
||||
|
||||
void destroy();
|
||||
void markPending();
|
||||
|
||||
struct {
|
||||
CHyprSignalListener surfaceCommitted;
|
||||
|
||||
@@ -83,7 +83,7 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<C
|
||||
});
|
||||
|
||||
m_resource->setSetSize([this](CZwlrLayerSurfaceV1* r, uint32_t x, uint32_t y) {
|
||||
m_pending.committed |= STATE_SIZE;
|
||||
markPending(STATE_SIZE);
|
||||
m_pending.desiredSize = {sc<int>(x), sc<int>(y)};
|
||||
});
|
||||
|
||||
@@ -93,17 +93,17 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<C
|
||||
return;
|
||||
}
|
||||
|
||||
m_pending.committed |= STATE_ANCHOR;
|
||||
markPending(STATE_ANCHOR);
|
||||
m_pending.anchor = anchor;
|
||||
});
|
||||
|
||||
m_resource->setSetExclusiveZone([this](CZwlrLayerSurfaceV1* r, int32_t zone) {
|
||||
m_pending.committed |= STATE_EXCLUSIVE;
|
||||
markPending(STATE_EXCLUSIVE);
|
||||
m_pending.exclusive = zone;
|
||||
});
|
||||
|
||||
m_resource->setSetMargin([this](CZwlrLayerSurfaceV1* r, int32_t top, int32_t right, int32_t bottom, int32_t left) {
|
||||
m_pending.committed |= STATE_MARGIN;
|
||||
markPending(STATE_MARGIN);
|
||||
m_pending.margin = {left, right, top, bottom};
|
||||
});
|
||||
|
||||
@@ -113,7 +113,7 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<C
|
||||
return;
|
||||
}
|
||||
|
||||
m_pending.committed |= STATE_INTERACTIVITY;
|
||||
markPending(STATE_INTERACTIVITY);
|
||||
m_pending.interactivity = kbi;
|
||||
});
|
||||
|
||||
@@ -149,7 +149,7 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<C
|
||||
return;
|
||||
}
|
||||
|
||||
m_pending.committed |= STATE_LAYER;
|
||||
markPending(STATE_LAYER);
|
||||
m_pending.layer = sc<zwlrLayerShellV1Layer>(layer);
|
||||
});
|
||||
|
||||
@@ -164,7 +164,7 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<C
|
||||
return;
|
||||
}
|
||||
|
||||
m_pending.committed |= STATE_EDGE;
|
||||
markPending(STATE_EDGE);
|
||||
m_pending.exclusiveEdge = anchor;
|
||||
});
|
||||
}
|
||||
@@ -179,6 +179,12 @@ bool CLayerShellResource::good() {
|
||||
return m_resource->resource();
|
||||
}
|
||||
|
||||
void CLayerShellResource::markPending(eCommittedState state) {
|
||||
m_pending.committed |= state;
|
||||
if (m_surface)
|
||||
m_surface->m_pending.updated.bits.layershell = true;
|
||||
}
|
||||
|
||||
void CLayerShellResource::sendClosed() {
|
||||
if (m_closed)
|
||||
return;
|
||||
|
||||
@@ -76,6 +76,7 @@ class CLayerShellResource {
|
||||
|
||||
private:
|
||||
SP<CZwlrLayerSurfaceV1> m_resource;
|
||||
void markPending(eCommittedState state);
|
||||
|
||||
struct {
|
||||
CHyprSignalListener commitSurface;
|
||||
|
||||
@@ -238,11 +238,15 @@ CXDGToplevelResource::CXDGToplevelResource(SP<CXdgToplevel> resource_, SP<CXDGSu
|
||||
|
||||
m_resource->setSetMaxSize([this](CXdgToplevel* r, int32_t x, int32_t y) {
|
||||
m_pending.maxSize = {x, y};
|
||||
if (m_owner && m_owner->m_surface)
|
||||
m_owner->m_surface->m_pending.updated.bits.xdgshell = true;
|
||||
m_events.sizeLimitsChanged.emit();
|
||||
});
|
||||
|
||||
m_resource->setSetMinSize([this](CXdgToplevel* r, int32_t x, int32_t y) {
|
||||
m_pending.minSize = {x, y};
|
||||
if (m_owner && m_owner->m_surface)
|
||||
m_owner->m_surface->m_pending.updated.bits.xdgshell = true;
|
||||
m_events.sizeLimitsChanged.emit();
|
||||
});
|
||||
|
||||
@@ -608,6 +612,8 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBas
|
||||
m_resource->setSetWindowGeometry([this](CXdgSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||
LOGM(Log::DEBUG, "xdg_surface {:x} requests geometry {}x{} {}x{}", (uintptr_t)this, x, y, w, h);
|
||||
m_pending.geometry = {x, y, w, h};
|
||||
if (m_surface)
|
||||
m_surface->m_pending.updated.bits.xdgshell = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,16 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
|
||||
return;
|
||||
}
|
||||
|
||||
// a synced subsurface caches its state until the parent commits, so make sure that
|
||||
// commit isnt dropped as empty. mark the t1 parent.
|
||||
if (m_role->role() == SURFACE_ROLE_SUBSURFACE) {
|
||||
const auto SUB = sc<CSubsurfaceRole*>(m_role.get())->m_subsurface.lock();
|
||||
if (SUB && SUB->m_sync && SUB->m_parent) {
|
||||
if (const auto PARENT = SUB->t1Parent())
|
||||
PARENT->m_pending.updated.bits.subsurface = true;
|
||||
}
|
||||
}
|
||||
|
||||
// null buffer attached
|
||||
if (!m_pending.buffer && m_pending.updated.bits.buffer) {
|
||||
commitState(m_pending);
|
||||
|
||||
@@ -41,7 +41,7 @@ inline eLockReason operator~(eLockReason a) {
|
||||
|
||||
struct SSurfaceState {
|
||||
union {
|
||||
uint16_t all = 0;
|
||||
uint32_t all = 0;
|
||||
struct {
|
||||
bool buffer : 1;
|
||||
bool damage : 1;
|
||||
@@ -56,6 +56,12 @@ struct SSurfaceState {
|
||||
bool frame : 1;
|
||||
bool fifo : 1;
|
||||
bool presentation : 1;
|
||||
bool xdgshell : 1;
|
||||
bool layershell : 1;
|
||||
bool subsurface : 1;
|
||||
bool alphaModifier : 1;
|
||||
bool hyprlandSurface : 1;
|
||||
bool backgroundEffect : 1;
|
||||
} bits;
|
||||
} updated;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user