Skip to content

Commit 6dce34a

Browse files
MightyPlazaaphelei
authored andcommitted
windowrules: allow incrementing window props (hyprwm#9566)
1 parent 3105f21 commit 6dce34a

21 files changed

+191
-102
lines changed

src/config/ConfigValue.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "ConfigValue.hpp"
2+
#include "ConfigManager.hpp"
3+
#include "../macros.hpp"
4+
5+
void local__configValuePopulate(void* const** p, const std::string& val) {
6+
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val);
7+
8+
*p = PVHYPRLANG->getDataStaticPtr();
9+
}
10+
11+
std::type_index local__configValueTypeIdx(const std::string& val) {
12+
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val);
13+
const auto ANY = PVHYPRLANG->getValue();
14+
return std::type_index(ANY.type());
15+
}

src/config/ConfigValue.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,28 @@
44
#include <typeindex>
55
#include <hyprlang.hpp>
66
#include "../macros.hpp"
7-
#include "ConfigManager.hpp"
7+
8+
// giga hack to avoid including configManager here
9+
// NOLINTNEXTLINE
10+
void local__configValuePopulate(void* const** p, const std::string& val);
11+
std::type_index local__configValueTypeIdx(const std::string& val);
812

913
template <typename T>
1014
class CConfigValue {
1115
public:
1216
CConfigValue(const std::string& val) {
13-
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val);
14-
15-
// NOLINTNEXTLINE
16-
p_ = PVHYPRLANG->getDataStaticPtr();
17-
1817
#ifdef HYPRLAND_DEBUG
1918
// verify type
20-
const auto ANY = PVHYPRLANG->getValue();
21-
const auto TYPE = std::type_index(ANY.type());
19+
const auto TYPE = local__configValueTypeIdx(val);
2220

2321
// exceptions
2422
const bool STRINGEX = (typeid(T) == typeid(std::string) && TYPE == typeid(Hyprlang::STRING));
2523
const bool CUSTOMEX = (typeid(T) == typeid(Hyprlang::CUSTOMTYPE) && (TYPE == typeid(Hyprlang::CUSTOMTYPE*) || TYPE == typeid(void*) /* dunno why it does this? */));
2624

2725
RASSERT(typeid(T) == TYPE || STRINGEX || CUSTOMEX, "Mismatched type in CConfigValue<T>, got {} but has {}", typeid(T).name(), TYPE.name());
2826
#endif
27+
28+
local__configValuePopulate(&p_, val);
2929
}
3030

3131
T* ptr() const {

src/desktop/Window.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
1212
#include "../render/decorations/CHyprBorderDecoration.hpp"
1313
#include "../config/ConfigValue.hpp"
14+
#include "../config/ConfigManager.hpp"
1415
#include "../managers/TokenManager.hpp"
1516
#include "../managers/AnimationManager.hpp"
1617
#include "../managers/ANRManager.hpp"
@@ -780,7 +781,7 @@ void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
780781
const CVarList VARS(r->szRule, 0, ' ');
781782
if (auto search = NWindowProperties::intWindowProperties.find(VARS[1]); search != NWindowProperties::intWindowProperties.end()) {
782783
try {
783-
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(std::stoi(VARS[2]), priority);
784+
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(Hyprlang::INT(std::stoi(VARS[2])), priority);
784785
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->szRule, e.what()); }
785786
} else if (auto search = NWindowProperties::floatWindowProperties.find(VARS[1]); search != NWindowProperties::floatWindowProperties.end()) {
786787
try {

src/desktop/Window.hpp

Lines changed: 8 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "WLSurface.hpp"
2020
#include "Workspace.hpp"
2121
#include "WindowRule.hpp"
22+
#include "WindowOverridableVar.hpp"
2223
#include "../protocols/types/ContentType.hpp"
2324

2425
class CXDGSurfaceResource;
@@ -77,88 +78,6 @@ struct SAlphaValue {
7778
};
7879
};
7980

80-
enum eOverridePriority : uint8_t {
81-
PRIORITY_LAYOUT = 0,
82-
PRIORITY_WORKSPACE_RULE,
83-
PRIORITY_WINDOW_RULE,
84-
PRIORITY_SET_PROP,
85-
};
86-
87-
template <typename T>
88-
class CWindowOverridableVar {
89-
public:
90-
CWindowOverridableVar(T const& value, eOverridePriority priority) {
91-
values[priority] = value;
92-
}
93-
CWindowOverridableVar(T const& value) : defaultValue{value} {}
94-
95-
CWindowOverridableVar() = default;
96-
~CWindowOverridableVar() = default;
97-
98-
CWindowOverridableVar<T>& operator=(CWindowOverridableVar<T> const& other) {
99-
// Self-assignment check
100-
if (this == &other)
101-
return *this;
102-
103-
for (auto const& value : other.values) {
104-
values[value.first] = value.second;
105-
}
106-
107-
return *this;
108-
}
109-
110-
void unset(eOverridePriority priority) {
111-
values.erase(priority);
112-
}
113-
114-
bool hasValue() {
115-
return !values.empty();
116-
}
117-
118-
T value() {
119-
if (!values.empty())
120-
return std::prev(values.end())->second;
121-
else
122-
throw std::bad_optional_access();
123-
}
124-
125-
T valueOr(T const& other) {
126-
if (hasValue())
127-
return value();
128-
else
129-
return other;
130-
}
131-
132-
T valueOrDefault() {
133-
return valueOr(defaultValue);
134-
}
135-
136-
eOverridePriority getPriority() {
137-
if (!values.empty())
138-
return std::prev(values.end())->first;
139-
else
140-
throw std::bad_optional_access();
141-
}
142-
143-
void matchOptional(std::optional<T> const& optValue, eOverridePriority priority) {
144-
if (optValue.has_value())
145-
values[priority] = optValue.value();
146-
else
147-
unset(priority);
148-
}
149-
150-
operator std::optional<T>() {
151-
if (hasValue())
152-
return value();
153-
else
154-
return std::nullopt;
155-
}
156-
157-
private:
158-
std::map<eOverridePriority, T> values;
159-
T defaultValue; // used for toggling, so required for bool
160-
};
161-
16281
struct SWindowData {
16382
CWindowOverridableVar<SAlphaValue> alpha = SAlphaValue{1.f, false};
16483
CWindowOverridableVar<SAlphaValue> alphaInactive = SAlphaValue{1.f, false};
@@ -186,12 +105,12 @@ struct SWindowData {
186105
CWindowOverridableVar<bool> xray = false;
187106
CWindowOverridableVar<bool> renderUnfocused = false;
188107

189-
CWindowOverridableVar<int> rounding;
190-
CWindowOverridableVar<float> roundingPower;
191-
CWindowOverridableVar<int> borderSize;
108+
CWindowOverridableVar<Hyprlang::INT> borderSize = {std::string("general:border_size"), Hyprlang::INT(0), std::nullopt};
109+
CWindowOverridableVar<Hyprlang::INT> rounding = {std::string("decoration:rounding"), Hyprlang::INT(0), std::nullopt};
192110

193-
CWindowOverridableVar<float> scrollMouse;
194-
CWindowOverridableVar<float> scrollTouchpad;
111+
CWindowOverridableVar<Hyprlang::FLOAT> roundingPower = {std::string("decoration:rounding_power")};
112+
CWindowOverridableVar<Hyprlang::FLOAT> scrollMouse = {std::string("input:scroll_factor")};
113+
CWindowOverridableVar<Hyprlang::FLOAT> scrollTouchpad = {std::string("input:touchpad:scroll_factor")};
195114

196115
CWindowOverridableVar<std::string> animationStyle;
197116
CWindowOverridableVar<Vector2D> maxSize;
@@ -567,12 +486,12 @@ namespace NWindowProperties {
567486
{"xray", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.xray; }},
568487
};
569488

570-
const std::unordered_map<std::string, std::function<CWindowOverridableVar<int>*(const PHLWINDOW&)>> intWindowProperties = {
489+
const std::unordered_map<std::string, std::function<CWindowOverridableVar<Hyprlang::INT>*(const PHLWINDOW&)>> intWindowProperties = {
571490
{"rounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.rounding; }},
572491
{"bordersize", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.borderSize; }},
573492
};
574493

575-
const std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> floatWindowProperties = {
494+
const std::unordered_map<std::string, std::function<CWindowOverridableVar<Hyprlang::FLOAT>*(PHLWINDOW)>> floatWindowProperties = {
576495
{"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }},
577496
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
578497
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }},

src/desktop/WindowOverridableVar.hpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <type_traits>
5+
#include <any>
6+
#include "../config/ConfigValue.hpp"
7+
8+
enum eOverridePriority : uint8_t {
9+
PRIORITY_LAYOUT = 0,
10+
PRIORITY_WORKSPACE_RULE,
11+
PRIORITY_WINDOW_RULE,
12+
PRIORITY_SET_PROP,
13+
};
14+
15+
template <typename T>
16+
T clampOptional(T const& value, std::optional<T> const& min, std::optional<T> const& max) {
17+
return std::clamp(value, min.value_or(std::numeric_limits<T>::min()), max.value_or(std::numeric_limits<T>::max()));
18+
}
19+
20+
template <typename T, bool Extended = std::is_same_v<T, bool> || std::is_same_v<T, Hyprlang::INT> || std::is_same_v<T, Hyprlang::FLOAT>>
21+
class CWindowOverridableVar {
22+
public:
23+
CWindowOverridableVar(T const& value, eOverridePriority priority) {
24+
m_values[priority] = value;
25+
}
26+
27+
CWindowOverridableVar(T const& value) : m_defaultValue{value} {}
28+
CWindowOverridableVar(T const& value, std::optional<T> const& min, std::optional<T> const& max = std::nullopt) : m_defaultValue{value}, m_minValue{min}, m_maxValue{max} {}
29+
CWindowOverridableVar(std::string const& value)
30+
requires(Extended && !std::is_same_v<T, bool>)
31+
: m_configValue(SP<CConfigValue<T>>(new CConfigValue<T>(value))) {}
32+
CWindowOverridableVar(std::string const& value, std::optional<T> const& min, std::optional<T> const& max = std::nullopt)
33+
requires(Extended && !std::is_same_v<T, bool>)
34+
: m_minValue(min), m_maxValue(max), m_configValue(SP<CConfigValue<T>>(new CConfigValue<T>(value))) {}
35+
36+
CWindowOverridableVar() = default;
37+
~CWindowOverridableVar() = default;
38+
39+
CWindowOverridableVar& operator=(CWindowOverridableVar<T> const& other) {
40+
// Self-assignment check
41+
if (this == &other)
42+
return *this;
43+
44+
for (auto const& value : other.m_values) {
45+
if constexpr (Extended && !std::is_same_v<T, bool>)
46+
m_values[value.first] = clampOptional(value.second, m_minValue, m_maxValue);
47+
else
48+
m_values[value.first] = value.second;
49+
}
50+
51+
return *this;
52+
}
53+
54+
void unset(eOverridePriority priority) {
55+
m_values.erase(priority);
56+
}
57+
58+
bool hasValue() {
59+
return !m_values.empty();
60+
}
61+
62+
T value() {
63+
if (!m_values.empty())
64+
return std::prev(m_values.end())->second;
65+
else
66+
throw std::bad_optional_access();
67+
}
68+
69+
T valueOr(T const& other) {
70+
if (hasValue())
71+
return value();
72+
else
73+
return other;
74+
}
75+
76+
T valueOrDefault()
77+
requires(Extended && !std::is_same_v<T, bool>)
78+
{
79+
if (hasValue())
80+
return value();
81+
else if (m_defaultValue.has_value())
82+
return m_defaultValue.value();
83+
else
84+
return **std::any_cast<SP<CConfigValue<T>>>(m_configValue);
85+
}
86+
87+
T valueOrDefault()
88+
requires(!Extended || std::is_same_v<T, bool>)
89+
{
90+
if (hasValue())
91+
return value();
92+
else if (!m_defaultValue.has_value())
93+
throw std::bad_optional_access();
94+
else
95+
return m_defaultValue.value();
96+
}
97+
98+
eOverridePriority getPriority() {
99+
if (!m_values.empty())
100+
return std::prev(m_values.end())->first;
101+
else
102+
throw std::bad_optional_access();
103+
}
104+
105+
void increment(T const& other, eOverridePriority priority) {
106+
if constexpr (std::is_same_v<T, bool>)
107+
m_values[priority] = valueOr(false) ^ other;
108+
else
109+
m_values[priority] = clampOptional(valueOrDefault() + other, m_minValue, m_maxValue);
110+
}
111+
112+
void matchOptional(std::optional<T> const& optValue, eOverridePriority priority) {
113+
if (optValue.has_value())
114+
m_values[priority] = optValue.value();
115+
else
116+
unset(priority);
117+
}
118+
119+
operator std::optional<T>() {
120+
if (hasValue())
121+
return value();
122+
else
123+
return std::nullopt;
124+
}
125+
126+
private:
127+
std::map<eOverridePriority, T> m_values;
128+
std::optional<T> m_defaultValue; // used for toggling, so required for bool
129+
std::optional<T> m_minValue;
130+
std::optional<T> m_maxValue;
131+
std::any m_configValue; // only there for select variables
132+
};

src/events/Windows.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "../managers/SeatManager.hpp"
88
#include "../render/Renderer.hpp"
99
#include "../config/ConfigValue.hpp"
10+
#include "../config/ConfigManager.hpp"
1011
#include "../protocols/LayerShell.hpp"
1112
#include "../protocols/XDGShell.hpp"
1213
#include "../protocols/core/Compositor.hpp"

src/helpers/Monitor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "sync/SyncReleaser.hpp"
77
#include "../Compositor.hpp"
88
#include "../config/ConfigValue.hpp"
9+
#include "../config/ConfigManager.hpp"
910
#include "../protocols/GammaControl.hpp"
1011
#include "../devices/ITouch.hpp"
1112
#include "../protocols/LayerShell.hpp"

src/hyprerror/HyprError.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "HyprError.hpp"
33
#include "../Compositor.hpp"
44
#include "../config/ConfigValue.hpp"
5+
#include "../config/ConfigManager.hpp"
56
#include "../render/pass/TexPassElement.hpp"
67
#include "../managers/AnimationManager.hpp"
78
#include "../render/Renderer.hpp"

src/layout/DwindleLayout.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "DwindleLayout.hpp"
22
#include "../Compositor.hpp"
33
#include "../config/ConfigValue.hpp"
4+
#include "../config/ConfigManager.hpp"
45
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
56
#include "../render/Renderer.hpp"
67
#include "../managers/input/InputManager.hpp"

src/layout/IHyprLayout.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "../Compositor.hpp"
44
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
55
#include "../config/ConfigValue.hpp"
6+
#include "../config/ConfigManager.hpp"
67
#include "../desktop/Window.hpp"
78
#include "../protocols/XDGShell.hpp"
89
#include "../protocols/core/Compositor.hpp"

src/layout/MasterLayout.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "config/ConfigDataValues.hpp"
55
#include <ranges>
66
#include "../config/ConfigValue.hpp"
7+
#include "../config/ConfigManager.hpp"
78
#include "../render/Renderer.hpp"
89
#include "../managers/input/InputManager.hpp"
910
#include "../managers/LayoutManager.hpp"

src/managers/CursorManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "PointerManager.hpp"
55
#include "../xwayland/XWayland.hpp"
66
#include "../managers/HookSystemManager.hpp"
7+
#include "../helpers/Monitor.hpp"
78

89
static int cursorAnimTimer(SP<CEventLoopTimer> self, void* data) {
910
const auto cursorMgr = reinterpret_cast<CCursorManager*>(data);

0 commit comments

Comments
 (0)