Line data Source code
1 : /**
2 : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "XLInputListener.h"
25 : #include "XLDirector.h"
26 : #include "XLInputDispatcher.h"
27 : #include "XLGestureRecognizer.h"
28 : #include "XLScheduler.h"
29 : #include "XLScene.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::xenolith {
32 :
33 : InputListener::EventMask InputListener::EventMaskTouch = InputListener::makeEventMask({
34 : InputEventName::Begin,
35 : InputEventName::Move,
36 : InputEventName::End,
37 : InputEventName::Cancel,
38 : InputEventName::Scroll,
39 : });
40 :
41 : InputListener::EventMask InputListener::EventMaskKeyboard = InputListener::makeEventMask({
42 : InputEventName::KeyPressed,
43 : InputEventName::KeyRepeated,
44 : InputEventName::KeyReleased,
45 : InputEventName::KeyCanceled,
46 : });
47 :
48 1546 : InputListener::ButtonMask InputListener::makeButtonMask(std::initializer_list<InputMouseButton> &&il) {
49 1546 : ButtonMask ret;
50 3113 : for (auto &it : il) {
51 1567 : ret.set(toInt(it));
52 : }
53 1546 : return ret;
54 : }
55 :
56 126 : InputListener::EventMask InputListener::makeEventMask(std::initializer_list<InputEventName> &&il) {
57 126 : EventMask ret;
58 567 : for (auto &it : il) {
59 441 : ret.set(toInt(it));
60 : }
61 126 : return ret;
62 : }
63 :
64 63 : InputListener::KeyMask InputListener::makeKeyMask(std::initializer_list<InputKeyCode> &&il) {
65 63 : KeyMask ret;
66 126 : for (auto &it : il) {
67 63 : ret.set(toInt(it));
68 : }
69 63 : return ret;
70 : }
71 :
72 1003 : InputListener::InputListener()
73 1003 : : _enabled(true), _owner(nullptr) { }
74 :
75 1922 : InputListener::~InputListener() { }
76 :
77 1003 : bool InputListener::init(int32_t priority) {
78 1003 : _priority = priority;
79 1003 : return true;
80 : }
81 :
82 877 : void InputListener::onEnter(Scene *scene) {
83 877 : _running = true;
84 877 : _scene = scene;
85 :
86 877 : _scene->getDirector()->getScheduler()->scheduleUpdate(this);
87 :
88 3002 : for (auto &it : _recognizers) {
89 2125 : it->onEnter(this);
90 : }
91 877 : }
92 :
93 877 : void InputListener::onExit() {
94 3002 : for (auto &it : _recognizers) {
95 2125 : it->onExit();
96 : }
97 :
98 877 : _scene->getDirector()->getScheduler()->unschedule(this);
99 877 : _running = false;
100 877 : _scene = nullptr;
101 877 : }
102 :
103 151728 : void InputListener::update(UpdateTime dt) {
104 534657 : for (auto &it : _recognizers) {
105 382929 : it->update(dt.delta);
106 : }
107 151728 : }
108 :
109 1171 : void InputListener::setOwner(Node *owner) {
110 1171 : _owner = owner;
111 1171 : }
112 :
113 105 : void InputListener::setEnabled(bool b) {
114 105 : _enabled = b;
115 105 : }
116 :
117 42 : void InputListener::setPriority(int32_t p) {
118 42 : _priority = p;
119 42 : }
120 :
121 21 : void InputListener::setDedicatedFocus(uint32_t v) {
122 21 : _dedicatedFocus = v;
123 21 : }
124 :
125 21 : void InputListener::setExclusive() {
126 21 : if (_scene) {
127 21 : _scene->getDirector()->getInputDispatcher()->setListenerExclusive(this);
128 : }
129 21 : }
130 :
131 52 : void InputListener::setExclusiveForTouch(uint32_t eventId) {
132 52 : if (_scene) {
133 52 : _scene->getDirector()->getInputDispatcher()->setListenerExclusiveForTouch(this, eventId);
134 : }
135 52 : }
136 :
137 21 : void InputListener::setSwallowEvents(EventMask &&mask) {
138 21 : if (_swallowEvents.any()) {
139 21 : _swallowEvents |= mask;
140 : } else {
141 0 : _swallowEvents = move(mask);
142 : }
143 21 : }
144 :
145 367 : void InputListener::setSwallowEvents(const EventMask &mask) {
146 367 : if (_swallowEvents.any()) {
147 0 : _swallowEvents |= mask;
148 : } else {
149 367 : _swallowEvents = mask;
150 : }
151 367 : }
152 :
153 21 : void InputListener::setSwallowAllEvents() {
154 21 : _swallowEvents.set();
155 21 : }
156 :
157 21 : void InputListener::setSwallowEvent(InputEventName event) {
158 21 : _swallowEvents.set(toInt(event));
159 21 : }
160 :
161 21 : void InputListener::clearSwallowAllEvents() {
162 21 : _swallowEvents.reset();
163 21 : }
164 :
165 21 : void InputListener::clearSwallowEvent(InputEventName event) {
166 21 : _swallowEvents.reset(toInt(event));
167 21 : }
168 :
169 42 : void InputListener::clearSwallowEvents(const EventMask &event) {
170 42 : _swallowEvents &= ~event;
171 42 : }
172 :
173 21 : bool InputListener::isSwallowAllEvents() const {
174 21 : return _swallowEvents.all();
175 : }
176 :
177 21 : bool InputListener::isSwallowAllEvents(const EventMask &event) const {
178 21 : return (_swallowEvents & event) == event;
179 : }
180 :
181 21 : bool InputListener::isSwallowAnyEvents(const EventMask &event) const {
182 21 : return (_swallowEvents & event).any();
183 : }
184 :
185 21 : bool InputListener::isSwallowEvent(InputEventName name) const {
186 21 : return _swallowEvents.test(toInt(name));
187 : }
188 :
189 63 : void InputListener::setTouchFilter(const EventFilter &filter) {
190 63 : _eventFilter = filter;
191 63 : }
192 :
193 48 : bool InputListener::shouldSwallowEvent(const InputEvent &event) const {
194 48 : return _swallowEvents.test(toInt(event.data.event));
195 : }
196 :
197 12953 : bool InputListener::canHandleEvent(const InputEvent &event) const {
198 12953 : if (!_running || !_owner) {
199 2482 : return false;
200 : }
201 :
202 10471 : if (_eventMask.test(toInt(event.data.event)) && shouldProcessEvent(event)) {
203 3544 : auto it = _callbacks.find(event.data.event);
204 3544 : if (it != _callbacks.end()) {
205 3507 : return true;
206 : }
207 11535 : for (auto &it : _recognizers) {
208 11498 : if (!_running || !_owner) {
209 : break;
210 : }
211 :
212 11498 : if (it->canHandleEvent(event)) {
213 3465 : return true;
214 : }
215 : }
216 : }
217 6964 : return false;
218 : }
219 :
220 5304 : InputEventState InputListener::handleEvent(const InputEvent &event) {
221 5304 : InputEventState ret = InputEventState::Declined;
222 5304 : auto it = _callbacks.find(event.data.event);
223 5304 : if (it != _callbacks.end()) {
224 42 : ret = std::max(it->second(event.data.getValue()) ? InputEventState::Processed : InputEventState::Declined, ret);
225 : }
226 27369 : for (auto &it : _recognizers) {
227 22065 : if (!_running || !_owner) {
228 : break;
229 : }
230 :
231 22065 : ret = std::max(it->handleInputEvent(event, _density), ret);
232 : }
233 5304 : return ret;
234 : }
235 :
236 172 : GestureRecognizer *InputListener::addTouchRecognizer(InputCallback<GestureData> &&cb, ButtonMask &&buttonMask) {
237 172 : return addRecognizer(Rc<GestureTouchRecognizer>::create(move(cb), move(buttonMask)));
238 : }
239 :
240 705 : GestureRecognizer *InputListener::addTapRecognizer(InputCallback<GestureTap> &&cb, ButtonMask &&buttonMask, uint32_t maxTapCount) {
241 705 : return addRecognizer(Rc<GestureTapRecognizer>::create(move(cb), move(buttonMask), maxTapCount));
242 : }
243 :
244 111 : GestureRecognizer *InputListener::addScrollRecognizer(InputCallback<GestureScroll> &&cb) {
245 111 : return addRecognizer(Rc<GestureScrollRecognizer>::create(move(cb)));
246 : }
247 :
248 537 : GestureRecognizer *InputListener::addPressRecognizer(InputCallback<GesturePress> &&cb, TimeInterval interval, bool continuous,
249 : ButtonMask &&mask) {
250 537 : return addRecognizer(Rc<GesturePressRecognizer>::create(move(cb), interval, continuous, move(mask)));
251 : }
252 :
253 153 : GestureRecognizer *InputListener::addSwipeRecognizer(InputCallback<GestureSwipe> &&cb, float threshold, bool sendThreshold, ButtonMask &&mask) {
254 153 : return addRecognizer(Rc<GestureSwipeRecognizer>::create(move(cb), threshold, sendThreshold, move(mask)));
255 : }
256 :
257 21 : GestureRecognizer *InputListener::addPinchRecognizer(InputCallback<GesturePinch> &&cb, ButtonMask &&mask) {
258 21 : return addRecognizer(Rc<GesturePinchRecognizer>::create(move(cb), move(mask)));
259 : }
260 :
261 21 : GestureRecognizer *InputListener::addMoveRecognizer(InputCallback<GestureData> &&cb, bool withinNode) {
262 21 : return addRecognizer(Rc<GestureMoveRecognizer>::create(move(cb), withinNode));
263 : }
264 :
265 447 : GestureRecognizer *InputListener::addMouseOverRecognizer(InputCallback<GestureData> &&cb, float padding) {
266 447 : return addRecognizer(Rc<GestureMouseOverRecognizer>::create(move(cb)));
267 : }
268 :
269 105 : GestureKeyRecognizer *InputListener::addKeyRecognizer(InputCallback<GestureData> &&cb, KeyMask &&keys) {
270 105 : return (GestureKeyRecognizer *)addRecognizer(Rc<GestureKeyRecognizer>::create(move(cb), move(keys)));
271 : }
272 :
273 42 : void InputListener::setPointerEnterCallback(Function<bool(bool)> &&cb) {
274 42 : if (cb) {
275 21 : _callbacks.insert_or_assign(InputEventName::PointerEnter, move(cb));
276 21 : _eventMask.set(toInt(InputEventName::PointerEnter));
277 : } else {
278 21 : _callbacks.erase(InputEventName::PointerEnter);
279 21 : _eventMask.reset(toInt(InputEventName::PointerEnter));
280 : }
281 42 : }
282 :
283 63 : void InputListener::setBackgroudCallback(Function<bool(bool)> &&cb) {
284 63 : if (cb) {
285 42 : _callbacks.insert_or_assign(InputEventName::Background, move(cb));
286 42 : _eventMask.set(toInt(InputEventName::Background));
287 : } else {
288 21 : _callbacks.erase(InputEventName::Background);
289 21 : _eventMask.reset(toInt(InputEventName::Background));
290 : }
291 63 : }
292 :
293 42 : void InputListener::setFocusCallback(Function<bool(bool)> &&cb) {
294 42 : if (cb) {
295 21 : _callbacks.insert_or_assign(InputEventName::FocusGain, move(cb));
296 21 : _eventMask.set(toInt(InputEventName::FocusGain));
297 : } else {
298 21 : _callbacks.erase(InputEventName::FocusGain);
299 21 : _eventMask.reset(toInt(InputEventName::FocusGain));
300 : }
301 42 : }
302 :
303 21 : void InputListener::clear() {
304 21 : _eventMask.reset();
305 21 : _recognizers.clear();
306 21 : }
307 :
308 6790 : bool InputListener::shouldProcessEvent(const InputEvent &event) const {
309 6790 : if (!_eventFilter) {
310 6597 : return _shouldProcessEvent(event);
311 : } else {
312 193 : return _eventFilter(event, std::bind(&InputListener::_shouldProcessEvent, this, event));
313 : }
314 : }
315 :
316 6790 : bool InputListener::_shouldProcessEvent(const InputEvent &event) const {
317 6790 : auto node = getOwner();
318 6790 : if (node && _running) {
319 6790 : bool visible = node->isVisible();
320 6790 : auto p = node->getParent();
321 21995 : while (visible && p) {
322 15205 : visible = p->isVisible();
323 15205 : p = p->getParent();
324 : }
325 6790 : if (visible && (!event.data.hasLocation() || event.data.event == InputEventName::MouseMove
326 4847 : || node->isTouched(event.currentLocation, _touchPadding))
327 13580 : && node->getOpacity() >= _opacityFilter) {
328 3544 : return true;
329 : }
330 : }
331 3246 : return false;
332 : }
333 :
334 2272 : void InputListener::addEventMask(const EventMask &mask) {
335 34080 : for (size_t i = 0; i < mask.size(); ++ i) {
336 31808 : if (mask.test(i)) {
337 8245 : _eventMask.set(i);
338 : }
339 : }
340 2272 : }
341 :
342 2272 : GestureRecognizer *InputListener::addRecognizer(GestureRecognizer *rec) {
343 2272 : addEventMask(rec->getEventMask());
344 2272 : auto ret = _recognizers.emplace_back(move(rec)).get();
345 2272 : if (_running) {
346 0 : ret->onEnter(this);
347 : }
348 2272 : return ret;
349 : }
350 :
351 : }
|