diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 8873d7f2..abfa8d84 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -3090,7 +3090,7 @@ SImageDescription CCompositor::getPreferredImageDescription() { } Debug::log(WARN, "FIXME: color management protocol is enabled, determine correct preferred image description"); // should determine some common settings to avoid unnecessary transformations while keeping maximum displayable precision - return SImageDescription{.primaries = NColorPrimaries::BT709}; + return m_monitors.size() == 1 ? m_monitors[0]->m_imageDescription : SImageDescription{.primaries = NColorPrimaries::BT709}; } bool CCompositor::shouldChangePreferredImageDescription() { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 3b440e56..4e5c4080 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -412,6 +412,7 @@ void CMonitor::onDisconnect(bool destroy) { } void CMonitor::applyCMType(eCMType cmType) { + auto oldImageDescription = m_imageDescription; switch (cmType) { case CM_SRGB: m_imageDescription = {}; break; // assumes SImageDescirption defaults to sRGB case CM_WIDE: @@ -461,6 +462,11 @@ void CMonitor::applyCMType(eCMType cmType) { m_imageDescription.luminances.max = m_maxLuminance; if (m_maxAvgLuminance >= 0) m_imageDescription.luminances.reference = m_maxAvgLuminance; + + if (oldImageDescription != m_imageDescription) { + m_imageDescription.updateId(); + PROTO::colorManagement->onMonitorImageDescriptionChanged(m_self); + } } bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { @@ -783,8 +789,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { m_supportsWideColor = RULE->supportsHDR; m_supportsHDR = RULE->supportsHDR; - auto oldImageDescription = m_imageDescription; - m_cmType = RULE->cmType; + m_cmType = RULE->cmType; switch (m_cmType) { case CM_AUTO: m_cmType = m_enabled10bit && supportsWideColor() ? CM_WIDE : CM_SRGB; break; case CM_EDID: m_cmType = m_output->parsedEDID.chromaticityCoords.has_value() ? CM_EDID : CM_SRGB; break; @@ -801,8 +806,6 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) { m_maxAvgLuminance = RULE->maxAvgLuminance; applyCMType(m_cmType); - if (oldImageDescription != m_imageDescription) - PROTO::colorManagement->onMonitorImageDescriptionChanged(m_self); m_sdrSaturation = RULE->sdrSaturation; m_sdrBrightness = RULE->sdrBrightness; diff --git a/src/protocols/ColorManagement.cpp b/src/protocols/ColorManagement.cpp index 502fbe45..aa01a365 100644 --- a/src/protocols/ColorManagement.cpp +++ b/src/protocols/ColorManagement.cpp @@ -410,14 +410,27 @@ CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SPm_settings = m_surface->getPreferredImageDescription(); - if (!PROTO::colorManagement->m_debug && m_currentPreferred->m_settings.icc.fd) { + m_currentPreferredId = m_currentPreferred->m_settings.updateId(); + + if (!PROTO::colorManagement->m_debug && m_currentPreferred->m_settings.icc.fd >= 0) { LOGM(ERR, "FIXME: parse icc profile"); r->error(WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported"); return; } - RESOURCE->resource()->sendReady(m_currentPreferred->m_settings.updateId()); + RESOURCE->resource()->sendReady(m_currentPreferredId); }); + + m_listeners.enter = m_surface->m_events.enter.listen([this](const auto& monitor) { onPreferredChanged(); }); + m_listeners.leave = m_surface->m_events.leave.listen([this](const auto& monitor) { onPreferredChanged(); }); +} + +void CColorManagementFeedbackSurface::onPreferredChanged() { + if (m_surface->m_enteredOutputs.size() == 1) { + const auto newId = m_surface->getPreferredImageDescription().updateId(); + if (m_currentPreferredId != newId) + m_resource->sendPreferredChanged(newId); + } } bool CColorManagementFeedbackSurface::good() { @@ -796,6 +809,9 @@ void CColorManagementProtocol::onMonitorImageDescriptionChanged(WP mon if (output->m_monitor == monitor) output->m_resource->sendImageDescriptionChanged(); } + // recheck feedbacks + for (auto const& feedback : m_feedbackSurfaces) + feedback->onPreferredChanged(); } void CColorManagementProtocol::destroyResource(CColorManager* resource) { diff --git a/src/protocols/ColorManagement.hpp b/src/protocols/ColorManagement.hpp index fc3a8d54..1d2795ed 100644 --- a/src/protocols/ColorManagement.hpp +++ b/src/protocols/ColorManagement.hpp @@ -89,6 +89,14 @@ class CColorManagementFeedbackSurface { wl_client* m_client = nullptr; WP m_currentPreferred; + uint32_t m_currentPreferredId = 0; + + struct { + CHyprSignalListener enter; + CHyprSignalListener leave; + } m_listeners; + + void onPreferredChanged(); friend class CColorManagementProtocol; }; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 58d7810c..21f9e0a7 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -307,6 +307,7 @@ void CWLSurfaceResource::enter(PHLMONITOR monitor) { m_enteredOutputs.emplace_back(monitor); m_resource->sendEnter(output->getResource().get()); + m_events.enter.emit(monitor); } void CWLSurfaceResource::leave(PHLMONITOR monitor) { @@ -323,6 +324,7 @@ void CWLSurfaceResource::leave(PHLMONITOR monitor) { std::erase(m_enteredOutputs, monitor); m_resource->sendLeave(output->getResource().get()); + m_events.leave.emit(monitor); } void CWLSurfaceResource::sendPreferredTransform(wl_output_transform t) { @@ -539,7 +541,18 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) { } SImageDescription CWLSurfaceResource::getPreferredImageDescription() { - return m_enteredOutputs.size() == 1 ? m_enteredOutputs[0]->m_imageDescription : g_pCompositor->getPreferredImageDescription(); + auto parent = m_self; + if (parent->m_role->role() == SURFACE_ROLE_SUBSURFACE) { + auto subsurface = ((CSubsurfaceRole*)parent->m_role.get())->m_subsurface.lock(); + parent = subsurface->t1Parent(); + } + WP monitor; + if (parent->m_enteredOutputs.size() == 1) + monitor = parent->m_enteredOutputs[0]; + else if (m_hlSurface.valid() && m_hlSurface->getWindow()) + monitor = m_hlSurface->getWindow()->m_monitor; + + return monitor ? monitor->m_imageDescription : g_pCompositor->getPreferredImageDescription(); } void CWLSurfaceResource::updateCursorShm(CRegion damage) { diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 8f1f8064..cfbc3ea8 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -87,6 +87,8 @@ class CWLSurfaceResource { CSignalT<> unmap; CSignalT> newSubsurface; CSignalT<> destroy; + CSignalT> enter; + CSignalT> leave; } m_events; SSurfaceState m_current;