1 #include "bindings-repository.hpp"
2 #include <wayfire/core.hpp>
3 #include <algorithm>
4 
handle_key(const wf::keybinding_t & pressed,uint32_t mod_binding_key)5 bool wf::bindings_repository_t::handle_key(const wf::keybinding_t& pressed,
6     uint32_t mod_binding_key)
7 {
8     std::vector<std::function<bool()>> callbacks;
9     for (auto& binding : this->keys)
10     {
11         if (binding->activated_by->get_value() == pressed)
12         {
13             /* We must be careful because the callback might be erased,
14              * so force copy the callback into the lambda */
15             auto callback = binding->callback;
16             callbacks.emplace_back([pressed, callback] ()
17             {
18                 return (*callback)(pressed);
19             });
20         }
21     }
22 
23     for (auto& binding : this->activators)
24     {
25         if (binding->activated_by->get_value().has_match(pressed))
26         {
27             /* We must be careful because the callback might be erased,
28              * so force copy the callback into the lambda */
29             auto callback = binding->callback;
30             callbacks.emplace_back([pressed, callback, mod_binding_key] ()
31             {
32                 wf::activator_data_t ev = {
33                     .source = activator_source_t::KEYBINDING,
34                     .activation_data = pressed.get_key()
35                 };
36 
37                 if (mod_binding_key)
38                 {
39                     ev.source = activator_source_t::MODIFIERBINDING;
40                     ev.activation_data = mod_binding_key;
41                 }
42 
43                 return (*callback)(ev);
44             });
45         }
46     }
47 
48     bool handled = false;
49     for (auto& cb : callbacks)
50     {
51         handled |= cb();
52     }
53 
54     return handled;
55 }
56 
handle_axis(uint32_t modifiers,wlr_event_pointer_axis * ev)57 bool wf::bindings_repository_t::handle_axis(uint32_t modifiers,
58     wlr_event_pointer_axis *ev)
59 {
60     std::vector<wf::axis_callback*> callbacks;
61 
62     for (auto& binding : this->axes)
63     {
64         if (binding->activated_by->get_value() == wf::keybinding_t{modifiers, 0})
65         {
66             callbacks.push_back(binding->callback);
67         }
68     }
69 
70     for (auto call : callbacks)
71     {
72         (*call)(ev);
73     }
74 
75     return !callbacks.empty();
76 }
77 
handle_button(const wf::buttonbinding_t & pressed)78 bool wf::bindings_repository_t::handle_button(const wf::buttonbinding_t& pressed)
79 {
80     std::vector<std::function<bool()>> callbacks;
81     for (auto& binding : this->buttons)
82     {
83         if (binding->activated_by->get_value() == pressed)
84         {
85             /* We must be careful because the callback might be erased,
86              * so force copy the callback into the lambda */
87             auto callback = binding->callback;
88             callbacks.emplace_back([=] ()
89             {
90                 return (*callback)(pressed);
91             });
92         }
93     }
94 
95     for (auto& binding : this->activators)
96     {
97         if (binding->activated_by->get_value().has_match(pressed))
98         {
99             /* We must be careful because the callback might be erased,
100              * so force copy the callback into the lambda */
101             auto callback = binding->callback;
102             callbacks.emplace_back([=] ()
103             {
104                 wf::activator_data_t data = {
105                     .source = activator_source_t::BUTTONBINDING,
106                     .activation_data = pressed.get_button(),
107                 };
108                 return (*callback)(data);
109             });
110         }
111     }
112 
113     bool binding_handled = false;
114     for (auto call : callbacks)
115     {
116         binding_handled |= call();
117     }
118 
119     return binding_handled;
120 }
121 
handle_gesture(const wf::touchgesture_t & gesture)122 void wf::bindings_repository_t::handle_gesture(const wf::touchgesture_t& gesture)
123 {
124     std::vector<std::function<void()>> callbacks;
125     for (auto& binding : this->activators)
126     {
127         if (binding->activated_by->get_value().has_match(gesture))
128         {
129             /* We must be careful because the callback might be erased,
130              * so force copy the callback into the lambda */
131             auto callback = binding->callback;
132             callbacks.emplace_back([=] ()
133             {
134                 wf::activator_data_t data = {
135                     .source = activator_source_t::GESTURE,
136                     .activation_data = 0
137                 };
138                 (*callback)(data);
139             });
140         }
141     }
142 
143     for (auto& cb : callbacks)
144     {
145         cb();
146     }
147 }
148 
handle_activator(const std::string & activator,const wf::activator_data_t & data)149 bool wf::bindings_repository_t::handle_activator(
150     const std::string& activator, const wf::activator_data_t& data)
151 {
152     auto opt = wf::get_core().config.get_option(activator);
153     for (auto& act : this->activators)
154     {
155         if (act->activated_by == opt)
156         {
157             return (*act->callback)(data);
158         }
159     }
160 
161     return false;
162 }
163 
rem_binding(void * callback)164 void wf::bindings_repository_t::rem_binding(void *callback)
165 {
166     const auto& erase = [callback] (auto& container)
167     {
168         auto it = std::remove_if(container.begin(), container.end(),
169             [callback] (const auto& ptr)
170         {
171             return ptr->callback == callback;
172         });
173         container.erase(it, container.end());
174     };
175 
176     erase(keys);
177     erase(buttons);
178     erase(axes);
179     erase(activators);
180 
181     recreate_hotspots();
182 }
183 
rem_binding(binding_t * binding)184 void wf::bindings_repository_t::rem_binding(binding_t *binding)
185 {
186     const auto& erase = [binding] (auto& container)
187     {
188         auto it = std::remove_if(container.begin(), container.end(),
189             [binding] (const auto& ptr)
190         {
191             return ptr.get() == binding;
192         });
193         container.erase(it, container.end());
194     };
195 
196     erase(keys);
197     erase(buttons);
198     erase(axes);
199     erase(activators);
200 
201     recreate_hotspots();
202 }
203 
bindings_repository_t(wf::output_t * output)204 wf::bindings_repository_t::bindings_repository_t(wf::output_t *output) :
205     hotspot_mgr(output)
206 {
207     on_config_reload.set_callback([=] (wf::signal_data_t*)
208     {
209         recreate_hotspots();
210     });
211 
212     wf::get_core().connect_signal("reload-config", &on_config_reload);
213 }
214 
recreate_hotspots()215 void wf::bindings_repository_t::recreate_hotspots()
216 {
217     this->idle_recreate_hotspots.run_once([=] ()
218     {
219         hotspot_mgr.update_hotspots(activators);
220     });
221 }
222