From ffd6cf65e40a7140e82dc6e076c90b5119d41a54 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Tue, 15 Apr 2025 23:00:40 +0000 Subject: windowrules: allow incrementing window props (#9566) --- src/desktop/WindowOverridableVar.hpp | 132 +++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/desktop/WindowOverridableVar.hpp (limited to 'src/desktop/WindowOverridableVar.hpp') diff --git a/src/desktop/WindowOverridableVar.hpp b/src/desktop/WindowOverridableVar.hpp new file mode 100644 index 00000000..ea113d3e --- /dev/null +++ b/src/desktop/WindowOverridableVar.hpp @@ -0,0 +1,132 @@ +#pragma once + +#include +#include +#include +#include "../config/ConfigValue.hpp" + +enum eOverridePriority : uint8_t { + PRIORITY_LAYOUT = 0, + PRIORITY_WORKSPACE_RULE, + PRIORITY_WINDOW_RULE, + PRIORITY_SET_PROP, +}; + +template +T clampOptional(T const& value, std::optional const& min, std::optional const& max) { + return std::clamp(value, min.value_or(std::numeric_limits::min()), max.value_or(std::numeric_limits::max())); +} + +template || std::is_same_v || std::is_same_v> +class CWindowOverridableVar { + public: + CWindowOverridableVar(T const& value, eOverridePriority priority) { + m_values[priority] = value; + } + + CWindowOverridableVar(T const& value) : m_defaultValue{value} {} + CWindowOverridableVar(T const& value, std::optional const& min, std::optional const& max = std::nullopt) : m_defaultValue{value}, m_minValue{min}, m_maxValue{max} {} + CWindowOverridableVar(std::string const& value) + requires(Extended && !std::is_same_v) + : m_configValue(SP>(new CConfigValue(value))) {} + CWindowOverridableVar(std::string const& value, std::optional const& min, std::optional const& max = std::nullopt) + requires(Extended && !std::is_same_v) + : m_minValue(min), m_maxValue(max), m_configValue(SP>(new CConfigValue(value))) {} + + CWindowOverridableVar() = default; + ~CWindowOverridableVar() = default; + + CWindowOverridableVar& operator=(CWindowOverridableVar const& other) { + // Self-assignment check + if (this == &other) + return *this; + + for (auto const& value : other.m_values) { + if constexpr (Extended && !std::is_same_v) + m_values[value.first] = clampOptional(value.second, m_minValue, m_maxValue); + else + m_values[value.first] = value.second; + } + + return *this; + } + + void unset(eOverridePriority priority) { + m_values.erase(priority); + } + + bool hasValue() { + return !m_values.empty(); + } + + T value() { + if (!m_values.empty()) + return std::prev(m_values.end())->second; + else + throw std::bad_optional_access(); + } + + T valueOr(T const& other) { + if (hasValue()) + return value(); + else + return other; + } + + T valueOrDefault() + requires(Extended && !std::is_same_v) + { + if (hasValue()) + return value(); + else if (m_defaultValue.has_value()) + return m_defaultValue.value(); + else + return **std::any_cast>>(m_configValue); + } + + T valueOrDefault() + requires(!Extended || std::is_same_v) + { + if (hasValue()) + return value(); + else if (!m_defaultValue.has_value()) + throw std::bad_optional_access(); + else + return m_defaultValue.value(); + } + + eOverridePriority getPriority() { + if (!m_values.empty()) + return std::prev(m_values.end())->first; + else + throw std::bad_optional_access(); + } + + void increment(T const& other, eOverridePriority priority) { + if constexpr (std::is_same_v) + m_values[priority] = valueOr(false) ^ other; + else + m_values[priority] = clampOptional(valueOrDefault() + other, m_minValue, m_maxValue); + } + + void matchOptional(std::optional const& optValue, eOverridePriority priority) { + if (optValue.has_value()) + m_values[priority] = optValue.value(); + else + unset(priority); + } + + operator std::optional() { + if (hasValue()) + return value(); + else + return std::nullopt; + } + + private: + std::map m_values; + std::optional m_defaultValue; // used for toggling, so required for bool + std::optional m_minValue; + std::optional m_maxValue; + std::any m_configValue; // only there for select variables +}; -- cgit v1.2.3