File: lambda-rules-registration.hpp

package info (click to toggle)
wayfire 0.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,764 kB
  • sloc: cpp: 52,464; xml: 2,987; ansic: 699; makefile: 161
file content (220 lines) | stat: -rw-r--r-- 6,969 bytes parent folder | download | duplicates (3)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#ifndef LAMBDARULESREGISTRATION_HPP
#define LAMBDARULESREGISTRATION_HPP

#include <map>
#include <memory>
#include <string>
#include <tuple>

#include "wayfire/core.hpp"
#include "wayfire/object.hpp"
#include "wayfire/nonstd/observer_ptr.h"
#include "wayfire/parser/lambda_rule_parser.hpp"
#include "wayfire/rule/lambda_rule.hpp"
#include "wayfire/util/log.hpp"
#include "wayfire/view.hpp"

class wayfire_window_rules_t;

namespace wf
{
struct lambda_rule_registration_t;

using map_type = std::map<std::string, std::shared_ptr<lambda_rule_registration_t>>;

using lambda_reg_t = std::function<bool (std::string, wayfire_view)>;

/**
 * @brief The lambda_rule_registration_t struct represents registration information
 * for a single lambda rule.
 *
 * To make a registration, create one of these structures in a shared_ptr, fill in
 * the appropriate values and
 * register it on the lambda_rules_registrations_t singleton instance.
 *
 * At minimum, the rule string and if_lambda need to be set.
 *
 * The rule text defines the condition that will will be matched by window-rules. If
 * the condition described
 * in the rule text evaluates to true (using access_interface to determine the
 * current values of variables),
 * the if_lambda function will be executed. If the condition evaluates to false, the
 * else_lambda (if not
 * nullptr) will be executed.
 */
struct lambda_rule_registration_t
{
  public:
    /**
     * @brief rule This is the rule text.
     *
     * @note The registering plugin is supposed to set this value before registering.
     */
    std::string rule;

    /**
     * @brief if_lambda This is the lambda method to be executed if the specified
     * condition holds.
     *
     * @note The registering plugin is supposed to set this value before registering.
     */
    wf::lambda_reg_t if_lambda;

    /**
     * @brief else_lambda This is the lambda method to be executed if the specified
     * condition does not hold.
     *
     * @note The registering plugin is supposed to set this value before registering.
     * @note In most cases this should be left blank.
     *
     * @attention: Be very careful with this lambda because it will be executed on
     * the signal for each view
     *             that did NOT match the condition.
     */
    wf::lambda_reg_t else_lambda;

    /**
     * @brief access_interface Access interface to be used when evaluating the rule.
     *
     * @note If this is left blank (nullptr), the standard view_access_interface_t
     * instance will be used.
     */
    std::shared_ptr<wf::access_interface_t> access_interface;

  private:
    /**
     * @brief rule_instance Pointer to the parsed rule object.
     *
     * @attention You should not set this. Leave it at nullptr, the registration
     * process will fill in this
     *            variable. Window rules can then use this cached rule instance on
     * each signal occurrence.
     */
    std::shared_ptr<wf::lambda_rule_t> rule_instance;

    // Friendship for window rules to be able to execute the rules.
    friend class ::wayfire_window_rules_t;

    // Friendship for the rules registrations to be able to modify the rule set.
    friend class lambda_rules_registrations_t;
};

/**
 * @brief The lambda_rules_registrations_t class is a helper class for easy
 * registration and unregistration of
 *        lambda rules for the window rules plugin.
 *
 * This class is a singleton and can only be used via the getInstance() method.
 *
 * The instance is stored in wf::core. The getInstance() method will fetch from
 * wf:core, and lazy-init if the
 * instance is not yet present.
 */
class lambda_rules_registrations_t : public custom_data_t
{
  public:
    /**
     * @brief getInstance Static accessor for the singleton.
     *
     * @return Observer pointer to the singleton instance, fetched from wf::core.
     */
    static nonstd::observer_ptr<lambda_rules_registrations_t> get_instance()
    {
        auto instance = get_core().get_data<lambda_rules_registrations_t>();
        if (instance == nullptr)
        {
            get_core().store_data(std::unique_ptr<lambda_rules_registrations_t>(
                new lambda_rules_registrations_t()));
            instance = get_core().get_data<lambda_rules_registrations_t>();

            if (instance == nullptr)
            {
                LOGE("Window lambda rules: Lazy-init of lambda registrations failed.");
            } else
            {
                LOGD(
                    "Window lambda rules: Lazy-init of lambda registrations succeeded.");
            }
        }

        return instance;
    }

    /**
     * @brief registerLambdaRule Registers a lambda rule with its associated key.
     *
     * This method will return error result if the key is not unique or the
     * registration struct is incomplete.
     *
     * @param[in] key Unique key for the registration.
     * @param[in] registration The registration structure.
     *
     * @return <code>True</code> in case of error, <code>false</code> if ok.
     */
    bool register_lambda_rule(std::string key,
        std::shared_ptr<lambda_rule_registration_t> registration)
    {
        if (_registrations.find(key) != _registrations.end())
        {
            return true; // Error, key already exists.
        }

        if (registration->if_lambda == nullptr)
        {
            return true; // Error, no if lambda specified.
        }

        registration->rule_instance = lambda_rule_parser_t().parse(
            registration->rule, nullptr, nullptr);
        if (registration->rule_instance == nullptr)
        {
            return true; // Error, failed to parse rule.
        }

        _registrations.emplace(key, registration);

        return false;
    }

    /**
     * @brief unregisterLambdaRule Unregisters a lambda rule with its associated key.
     *
     * Has no effect if no rule is registered with this key.
     *
     * @param[in] key Unique key for the registration.
     */
    void unregister_lambda_rule(std::string key)
    {
        _registrations.erase(key);
    }

    /**
     * @brief rules Gets the boundaries of the rules map as a tuple of cbegin() and
     * cend() const_iterators.
     *
     * @return Boundaries of the rules map.
     */
    std::tuple<map_type::const_iterator, map_type::const_iterator> rules()
    {
        return std::tuple(_registrations.cbegin(), _registrations.cend());
    }

  private:
    /**
     * @brief lambda_rules_registrations_t Constructor, private to enforce singleton
     * design pattern.
     */
    lambda_rules_registrations_t() = default;

    /**
     * @brief _registrations The map holding all the current registrations.
     */
    map_type _registrations;

    // Necessary for window-rules to manage the lifetime of the object
    uint32_t window_rule_instances = 0;
    friend class ::wayfire_window_rules_t;
};
} // End namespace wf.

#endif // LAMBDARULESREGISTRATION_HPP