summaryrefslogtreecommitdiff
path: root/src/desktop/rule/layerRule/LayerRuleApplicator.cpp
blob: 4237e4f7ce9ed6597d40bf9aed7cdad87db9c0e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "LayerRuleApplicator.hpp"
#include "LayerRule.hpp"
#include "../Engine.hpp"
#include "../../view/LayerSurface.hpp"
#include "../../types/OverridableVar.hpp"
#include "../../../helpers/MiscFunctions.hpp"

using namespace Desktop;
using namespace Desktop::Rule;

CLayerRuleApplicator::CLayerRuleApplicator(PHLLS ls) : m_ls(ls) {
    ;
}

void CLayerRuleApplicator::resetProps(std::underlying_type_t<eRuleProperty> props, Types::eOverridePriority prio) {
    // TODO: fucking kill me, is there a better way to do this?

#define UNSET(x)                                                                                                                                                                   \
    if (m_##x.second & props) {                                                                                                                                                    \
        if (prio == Types::PRIORITY_WINDOW_RULE)                                                                                                                                   \
            m_##x.second &= ~props;                                                                                                                                                \
        m_##x.first.unset(prio);                                                                                                                                                   \
    }

    UNSET(noanim)
    UNSET(blur)
    UNSET(blurPopups)
    UNSET(dimAround)
    UNSET(xray)
    UNSET(noScreenShare)
    UNSET(order)
    UNSET(aboveLock)
    UNSET(ignoreAlpha)
    UNSET(animationStyle)
}

void CLayerRuleApplicator::applyDynamicRule(const SP<CLayerRule>& rule) {
    for (const auto& [key, effect] : rule->effects()) {
        switch (key) {
            case LAYER_RULE_EFFECT_NONE: {
                Log::logger->log(Log::ERR, "CLayerRuleApplicator::applyDynamicRule: BUG THIS: LAYER_RULE_EFFECT_NONE??");
                break;
            }
            case LAYER_RULE_EFFECT_NO_ANIM: {
                m_noanim.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
                m_noanim.second |= rule->getPropertiesMask();
                break;
            }
            case LAYER_RULE_EFFECT_BLUR: {
                m_blur.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
                m_blur.second |= rule->getPropertiesMask();
                break;
            }
            case LAYER_RULE_EFFECT_BLUR_POPUPS: {
                m_blurPopups.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
                m_blurPopups.second |= rule->getPropertiesMask();
                break;
            }
            case LAYER_RULE_EFFECT_DIM_AROUND: {
                m_dimAround.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
                m_dimAround.second |= rule->getPropertiesMask();
                break;
            }
            case LAYER_RULE_EFFECT_XRAY: {
                m_xray.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
                m_xray.second |= rule->getPropertiesMask();
                break;
            }
            case LAYER_RULE_EFFECT_NO_SCREEN_SHARE: {
                m_noScreenShare.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
                m_noScreenShare.second |= rule->getPropertiesMask();
                break;
            }
            case LAYER_RULE_EFFECT_ORDER: {
                try {
                    m_order.first.set(std::stoi(effect), Types::PRIORITY_WINDOW_RULE);
                    m_order.second |= rule->getPropertiesMask();
                } catch (...) { Log::logger->log(Log::ERR, "CLayerRuleApplicator::applyDynamicRule: invalid order {}", effect); }
                break;
            }
            case LAYER_RULE_EFFECT_ABOVE_LOCK: {
                try {
                    m_aboveLock.first.set(std::clamp(std::stoull(effect), 0ULL, 2ULL), Types::PRIORITY_WINDOW_RULE);
                    m_aboveLock.second |= rule->getPropertiesMask();
                } catch (...) { Log::logger->log(Log::ERR, "CLayerRuleApplicator::applyDynamicRule: invalid order {}", effect); }
                break;
            }
            case LAYER_RULE_EFFECT_IGNORE_ALPHA: {
                try {
                    m_ignoreAlpha.first.set(std::clamp(std::stof(effect), 0.F, 1.F), Types::PRIORITY_WINDOW_RULE);
                    m_ignoreAlpha.second |= rule->getPropertiesMask();
                } catch (...) { Log::logger->log(Log::ERR, "CLayerRuleApplicator::applyDynamicRule: invalid order {}", effect); }
                break;
            }
            case LAYER_RULE_EFFECT_ANIMATION: {
                m_animationStyle.first.set(effect, Types::PRIORITY_WINDOW_RULE);
                m_animationStyle.second |= rule->getPropertiesMask();
                break;
            }
        }
    }
}

void CLayerRuleApplicator::propertiesChanged(std::underlying_type_t<eRuleProperty> props) {
    if (!m_ls)
        return;

    resetProps(props);

    // FIXME: this will not update properties correctly if we implement dynamic rules for
    // layers, due to effects overlapping on 0 prop intersection.
    // See WindowRule.cpp, and ::propertiesChanged there.

    for (const auto& r : ruleEngine()->rules()) {
        if (r->type() != RULE_TYPE_LAYER)
            continue;

        if (!(r->getPropertiesMask() & props))
            continue;

        auto wr = reinterpretPointerCast<CLayerRule>(r);

        if (!wr->matches(m_ls.lock()))
            continue;

        applyDynamicRule(wr);
    }
}