LCOV - code coverage report
Current view: top level - xenolith/scene/input - XLGestureRecognizer.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 614 680 90.3 %
Date: 2024-05-12 00:16:13 Functions: 70 70 100.0 %

          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 "XLGestureRecognizer.h"
      25             : #include "XLInputListener.h"
      26             : #include "XLNode.h"
      27             : #include "XLDirector.h"
      28             : #include "XLInputDispatcher.h"
      29             : 
      30             : namespace STAPPLER_VERSIONIZED stappler::xenolith {
      31             : 
      32          21 : const Vec2 &GestureScroll::location() const {
      33          21 :         return pos;
      34             : }
      35             : 
      36          21 : void GestureScroll::cleanup() {
      37          21 :         pos = Vec2::ZERO;
      38          21 :         amount = Vec2::ZERO;
      39          21 : }
      40             : 
      41             : 
      42        3023 : void GestureTap::cleanup() {
      43        3023 :         id = maxOf<uint32_t>();
      44        3023 :         time.clear();
      45        3023 :         count = 0;
      46        3023 : }
      47             : 
      48         289 : void GesturePress::cleanup() {
      49         289 :         id = maxOf<uint32_t>();
      50         289 :         limit.clear();
      51         289 :         time.clear();
      52         289 :         tickCount = 0;
      53         289 : }
      54             : 
      55         176 : void GestureSwipe::cleanup() {
      56         176 :         firstTouch = Vec2::ZERO;
      57         176 :         secondTouch = Vec2::ZERO;
      58         176 :         midpoint = Vec2::ZERO;
      59         176 :         delta = Vec2::ZERO;
      60         176 :         velocity = Vec2::ZERO;
      61         176 : }
      62             : 
      63          84 : void GesturePinch::cleanup() {
      64          84 :         first = Vec2::ZERO;
      65          84 :         second = Vec2::ZERO;
      66          84 :         center = Vec2::ZERO;
      67          84 :         startDistance = 0.0f;
      68          84 :         prevDistance = 0.0f;
      69          84 :         distance = 0.0f;
      70          84 :         scale = 0.0f;
      71          84 :         velocity = 0.0f;
      72          84 : }
      73             : 
      74        2461 : bool GestureRecognizer::init() {
      75        2461 :         return true;
      76             : }
      77             : 
      78       14455 : bool GestureRecognizer::canHandleEvent(const InputEvent &event) const {
      79       14455 :         if (_eventMask.test(toInt(event.data.event))) {
      80        4849 :                 if (!_buttonMask.any() || _buttonMask.test(toInt(event.data.button))) {
      81        4849 :                         return true;
      82             :                 }
      83             :         }
      84        9606 :         return false;
      85             : }
      86             : 
      87       18903 : InputEventState GestureRecognizer::handleInputEvent(const InputEvent &event, float density) {
      88       18903 :         if (!_eventMask.test(toInt(event.data.event))) {
      89       10632 :                 return InputEventState::Declined;
      90             :         }
      91             : 
      92        8271 :         if (_buttonMask.any() && !_buttonMask.test(toInt(event.data.button))) {
      93        3262 :                 return InputEventState::Declined;
      94             :         }
      95             : 
      96        5009 :         _density = density;
      97             : 
      98        5009 :         switch (event.data.event) {
      99        1960 :         case InputEventName::Begin:
     100             :         case InputEventName::KeyPressed:
     101        1960 :                 return addEvent(event, density);
     102             :                 break;
     103        1044 :         case InputEventName::Move:
     104             :         case InputEventName::KeyRepeated:
     105        1044 :                 return renewEvent(event, density);
     106             :                 break;
     107        1788 :         case InputEventName::End:
     108             :         case InputEventName::KeyReleased:
     109        1788 :                 return removeEvent(event, true, density);
     110             :                 break;
     111         217 :         case InputEventName::Cancel:
     112             :         case InputEventName::KeyCanceled:
     113         217 :                 return removeEvent(event, false, density);
     114             :                 break;
     115           0 :         default: break;
     116             :         }
     117           0 :         return InputEventState::Processed;
     118             : }
     119             : 
     120        2125 : void GestureRecognizer::onEnter(InputListener *) {
     121             : 
     122        2125 : }
     123             : 
     124        2125 : void GestureRecognizer::onExit() {
     125             : 
     126        2125 : }
     127             : 
     128          21 : uint32_t GestureRecognizer::getEventCount() const {
     129          21 :         return (uint32_t)_events.size();
     130             : }
     131             : 
     132          42 : bool GestureRecognizer::hasEvent(const InputEvent &event) const {
     133          42 :         if (_events.size() == 0) {
     134          21 :                 return false;
     135             :         }
     136             : 
     137          21 :         for (auto & pEvent : _events) {
     138          21 :                 if (pEvent.data.id == event.data.id) {
     139          21 :                         return true;
     140             :                 }
     141             :         }
     142             : 
     143           0 :         return false;
     144             : }
     145             : 
     146        2272 : GestureRecognizer::EventMask GestureRecognizer::getEventMask() const {
     147        2272 :         return _eventMask;
     148             : }
     149             : 
     150      303030 : void GestureRecognizer::update(uint64_t dt) {
     151             : 
     152      303030 : }
     153             : 
     154          21 : Vec2 GestureRecognizer::getLocation() const {
     155          21 :         if (_events.size() > 0) {
     156          21 :                 return Vec2(_events.back().currentLocation);
     157             :         } else {
     158           0 :                 return Vec2::ZERO;
     159             :         }
     160             : }
     161             : 
     162         126 : void GestureRecognizer::cancel() {
     163         126 :         auto eventsToRemove = _events;
     164         126 :         for (auto &event : eventsToRemove) {
     165           0 :                 removeEvent(event, false, _density);
     166             :         }
     167         126 : }
     168             : 
     169         136 : bool GestureRecognizer::canAddEvent(const InputEvent &event) const {
     170         136 :         if (_events.size() < _maxEvents) {
     171         136 :                 for (auto &it : _events) {
     172           0 :                         if (event.data.id == it.data.id) {
     173           0 :                                 return false;
     174             :                         }
     175             :                 }
     176         136 :                 return true;
     177             :         } else {
     178           0 :                 return false;
     179             :         }
     180             : }
     181             : 
     182        1872 : InputEventState GestureRecognizer::addEvent(const InputEvent &event, float density) {
     183        1872 :         if (_events.size() < _maxEvents) {
     184        1914 :                 for (auto &it : _events) {
     185          42 :                         if (event.data.id == it.data.id) {
     186           0 :                                 return InputEventState::Declined;
     187             :                         }
     188             :                 }
     189        1872 :                 _events.emplace_back(event);
     190        1872 :                 return InputEventState::Processed;
     191             :         } else {
     192           0 :                 return InputEventState::Declined;
     193             :         }
     194             : }
     195             : 
     196        2009 : InputEventState GestureRecognizer::removeEvent(const InputEvent &event, bool success, float density) {
     197        2009 :         if (_events.size() == 0) {
     198         179 :                 return InputEventState::Declined;
     199             :         }
     200             : 
     201        1830 :         uint32_t index = maxOf<uint32_t>();
     202        1830 :         auto pEvent = getTouchById(event.data.id, &index);
     203        1830 :         if (pEvent && index < _events.size()) {
     204        1830 :                 _events.erase(_events.begin() + index);
     205        1830 :                 return InputEventState::Processed;
     206             :         } else {
     207           0 :                 return InputEventState::Declined;
     208             :         }
     209             : }
     210             : 
     211        1023 : InputEventState GestureRecognizer::renewEvent(const InputEvent &event, float density) {
     212        1023 :         if (_events.size() == 0) {
     213         496 :                 return InputEventState::Declined;
     214             :         }
     215             : 
     216         527 :         uint32_t index = maxOf<uint32_t>();
     217         527 :         auto pEvent = getTouchById(event.data.id, &index);
     218         527 :         if (pEvent && index < _events.size()) {
     219         527 :                 _events[index] = event;
     220         527 :                 return InputEventState::Processed;
     221             :         } else {
     222           0 :                 return InputEventState::Declined;
     223             :         }
     224             : }
     225             : 
     226        2357 : InputEvent *GestureRecognizer::getTouchById(uint32_t id, uint32_t *index) {
     227        2357 :         InputEvent *pTouch = nullptr; uint32_t i = 0;
     228        2399 :         for (i = 0; i < _events.size(); i ++) {
     229        2399 :                 pTouch = &_events.at(i);
     230        2399 :                 if (pTouch->data.id == id) {
     231        2357 :                         if (index) {
     232        2357 :                                 *index = i;
     233             :                         }
     234        2357 :                         return pTouch;
     235             :                 }
     236             :         }
     237           0 :         return nullptr;
     238             : }
     239             : 
     240         193 : bool GestureTouchRecognizer::init(InputCallback &&cb, ButtonMask &&mask) {
     241         193 :         if (!GestureRecognizer::init()) {
     242           0 :                 return false;
     243             :         }
     244             : 
     245         193 :         if (cb) {
     246         193 :                 _maxEvents = 10;
     247         193 :                 _buttonMask = move(mask);
     248         193 :                 _callback = move(cb);
     249         193 :                 _eventMask.set(toInt(InputEventName::Begin));
     250         193 :                 _eventMask.set(toInt(InputEventName::Move));
     251         193 :                 _eventMask.set(toInt(InputEventName::End));
     252         193 :                 _eventMask.set(toInt(InputEventName::Cancel));
     253         193 :                 return true;
     254             :         }
     255           0 :         return false;
     256             : }
     257             : 
     258        1258 : bool GestureTouchRecognizer::canHandleEvent(const InputEvent &event) const {
     259        1258 :         if (GestureRecognizer::canHandleEvent(event)) {
     260           0 :                 if (_buttonMask.test(toInt(event.data.button))) {
     261           0 :                         return true;
     262             :                 }
     263             :         }
     264        1258 :         return false;
     265             : }
     266             : 
     267          42 : void GestureTouchRecognizer::removeRecognizedEvent(uint32_t id) {
     268          42 :         for (auto it = _events.begin(); it != _events.end(); it ++) {
     269          42 :                 if ((*it).data.id == id) {
     270          42 :                         _events.erase(it);
     271          42 :                         break;
     272             :                 }
     273             :         }
     274          42 : }
     275             : 
     276          63 : InputEventState GestureTouchRecognizer::addEvent(const InputEvent &event, float density) {
     277          63 :         if (!_buttonMask.test(toInt(event.data.button))) {
     278           0 :                 return InputEventState::Declined;
     279             :         }
     280             : 
     281          63 :         if (GestureRecognizer::addEvent(event, density) != InputEventState::Declined) {
     282          63 :                 _event.event = GestureEvent::Began;
     283          63 :                 _event.input = &event;
     284          63 :                 if (!_callback(_event)) {
     285          21 :                         removeRecognizedEvent(event.data.id);
     286          21 :                         _event.event = GestureEvent::Cancelled;
     287          21 :                         _event.input = nullptr;
     288          21 :                         return InputEventState::Declined;
     289             :                 }
     290          42 :                 return InputEventState::Captured;
     291             :         }
     292           0 :         return InputEventState::Declined;
     293             : }
     294             : 
     295          63 : InputEventState GestureTouchRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
     296          63 :         if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
     297          21 :                 _event.event = successful ? GestureEvent::Ended : GestureEvent::Cancelled;
     298          21 :                 _event.input = &event;
     299          21 :                 _callback(_event);
     300          21 :                 _event.event = GestureEvent::Cancelled;
     301          21 :                 _event.input = nullptr;
     302          21 :                 return InputEventState::Processed;
     303             :         }
     304          42 :         return InputEventState::Declined;
     305             : }
     306             : 
     307          63 : InputEventState GestureTouchRecognizer::renewEvent(const InputEvent &event, float density) {
     308          63 :         if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
     309          42 :                 _event.event = GestureEvent::Activated;
     310          42 :                 _event.input = &event;
     311          42 :                 if (!_callback(_event)) {
     312          21 :                         removeRecognizedEvent(event.data.id);
     313          21 :                         _event.event = GestureEvent::Cancelled;
     314          21 :                         _event.input = nullptr;
     315          21 :                         return InputEventState::Declined;
     316             :                 }
     317          21 :                 return InputEventState::Processed;
     318             :         }
     319          21 :         return InputEventState::Declined;
     320             : }
     321             : 
     322             : 
     323         726 : bool GestureTapRecognizer::init(InputCallback &&cb, ButtonMask &&mask, uint32_t maxTapCount) {
     324         726 :         if (!GestureRecognizer::init()) {
     325           0 :                 return false;
     326             :         }
     327             : 
     328         726 :         if (cb) {
     329         726 :                 _maxEvents = 1;
     330         726 :                 _maxTapCount = maxTapCount;
     331         726 :                 _callback = move(cb);
     332         726 :                 _buttonMask = move(mask);
     333         726 :                 _eventMask.set(toInt(InputEventName::Begin));
     334         726 :                 _eventMask.set(toInt(InputEventName::Move));
     335         726 :                 _eventMask.set(toInt(InputEventName::End));
     336         726 :                 _eventMask.set(toInt(InputEventName::Cancel));
     337         726 :                 return true;
     338             :         }
     339           0 :         return false;
     340             : }
     341             : 
     342      109153 : void GestureTapRecognizer::update(uint64_t dt) {
     343      109153 :         GestureRecognizer::update(dt);
     344             : 
     345      109153 :         auto now = Time::now();
     346      109153 :         if (_gesture.count > 0 && _gesture.time - now > TapIntervalAllowed) {
     347           6 :                 _gesture.event = GestureEvent::Activated;
     348           6 :                 _gesture.input = _events.empty() ? &_tmpEvent : &_events.front();
     349           6 :                 _callback(_gesture);
     350           6 :                 _gesture.event = GestureEvent::Cancelled;
     351           6 :                 _gesture.input = nullptr;
     352           6 :                 _gesture.cleanup();
     353             :         }
     354      109153 : }
     355             : 
     356          21 : void GestureTapRecognizer::cancel() {
     357          21 :         GestureRecognizer::cancel();
     358          21 :         _gesture.cleanup();
     359          21 : }
     360             : 
     361        1568 : InputEventState GestureTapRecognizer::addEvent(const InputEvent &ev, float density) {
     362        1568 :         if (_gesture.count > 0 && _gesture.pos.distance(ev.currentLocation) > TapDistanceAllowedMulti * density) {
     363           0 :                 return InputEventState::Declined;
     364             :         }
     365        1568 :         if (GestureRecognizer::addEvent(ev, density) != InputEventState::Declined) {
     366        1568 :                 auto count = _gesture.count;
     367        1568 :                 auto time = _gesture.time;
     368        1568 :                 _gesture.cleanup();
     369        1568 :                 if (time - Time::now() < TapIntervalAllowed) {
     370           0 :                         _gesture.count = count;
     371           0 :                         _gesture.time = time;
     372             :                 }
     373        1568 :                 _gesture.id = ev.data.id;
     374        1568 :                 _gesture.pos = ev.currentLocation;
     375        1568 :                 return InputEventState::Processed;
     376             :         }
     377           0 :         return InputEventState::Declined;
     378             : }
     379             : 
     380        1626 : InputEventState GestureTapRecognizer::removeEvent(const InputEvent &ev, bool successful, float density) {
     381        1626 :         InputEventState ret = InputEventState::Declined;
     382        1626 :         if (GestureRecognizer::removeEvent(ev, successful, density) != InputEventState::Declined) {
     383        1568 :                 _tmpEvent = ev;
     384        1568 :                 if (successful && _gesture.pos.distance(ev.currentLocation) <= TapDistanceAllowed * density) {
     385        1476 :                         registerTap();
     386        1476 :                         ret = InputEventState::Processed;
     387             :                 } else {
     388          92 :                         ret = InputEventState::Processed;
     389             :                 }
     390             :         }
     391        1626 :         return ret;
     392             : }
     393             : 
     394         292 : InputEventState GestureTapRecognizer::renewEvent(const InputEvent &ev, float density) {
     395         292 :         auto ret = GestureRecognizer::renewEvent(ev, density);
     396         292 :         if (ret != InputEventState::Declined) {
     397          67 :                 if (_gesture.pos.distance(ev.currentLocation) > TapDistanceAllowed * density) {
     398          25 :                         return removeEvent(ev, false, density);
     399             :                 }
     400             :         }
     401         267 :         return ret;
     402             : }
     403             : 
     404        1476 : void GestureTapRecognizer::registerTap() {
     405        1476 :         auto currentTime = Time::now();
     406             : 
     407        1476 :         if (currentTime < _gesture.time + TapIntervalAllowed) {
     408           0 :                 _gesture.count ++;
     409             :         } else {
     410        1476 :                 _gesture.count = 1;
     411             :         }
     412             : 
     413        1476 :         _gesture.time = currentTime;
     414        1476 :         if (_gesture.count == _maxTapCount) {
     415        1407 :                 _gesture.event = GestureEvent::Activated;
     416        1407 :                 _gesture.input = _events.empty() ? &_tmpEvent : &_events.front();
     417        1407 :                 _callback(_gesture);
     418        1407 :                 _gesture.event = GestureEvent::Cancelled;
     419        1407 :                 _gesture.input = nullptr;
     420        1407 :                 _gesture.cleanup();
     421             :         }
     422        1476 : }
     423             : 
     424         558 : bool GesturePressRecognizer::init(InputCallback &&cb, TimeInterval interval, bool continuous, ButtonMask &&btn) {
     425         558 :         if (!GestureRecognizer::init()) {
     426           0 :                 return false;
     427             :         }
     428             : 
     429         558 :         if (cb) {
     430         558 :                 _maxEvents = 1;
     431         558 :                 _callback = move(cb);
     432         558 :                 _interval = interval;
     433         558 :                 _continuous = continuous;
     434         558 :                 _buttonMask = move(btn);
     435             : 
     436             :                 // enable all touch events
     437         558 :                 _eventMask.set(toInt(InputEventName::Begin));
     438         558 :                 _eventMask.set(toInt(InputEventName::Move));
     439         558 :                 _eventMask.set(toInt(InputEventName::End));
     440         558 :                 _eventMask.set(toInt(InputEventName::Cancel));
     441         558 :                 return true;
     442             :         }
     443           0 :         return false;
     444             : }
     445             : 
     446          42 : void GesturePressRecognizer::cancel() {
     447          42 :         GestureRecognizer::cancel();
     448          42 :         _gesture.cleanup();
     449          42 :         _lastTime.clear();
     450          42 : }
     451             : 
     452       79983 : void GesturePressRecognizer::update(uint64_t dt) {
     453       79983 :         if ((!_notified || _continuous) && _lastTime && _events.size() > 0) {
     454          84 :                 auto time = Time::now() - _lastTime;
     455          84 :                 if (_gesture.time.mksec() / _interval.mksec() != time.mksec() / _interval.mksec()) {
     456          84 :                         _gesture.time = time;
     457          84 :                         ++ _gesture.tickCount;
     458          84 :                         _gesture.event = GestureEvent::Activated;
     459          84 :                         _gesture.input = &_events.front();
     460          84 :                         if (!_callback(_gesture)) {
     461           0 :                                 cancel();
     462             :                         }
     463          84 :                         _notified = true;
     464             :                 }
     465             :         }
     466       79983 : }
     467             : 
     468         136 : InputEventState GesturePressRecognizer::addEvent(const InputEvent &event, float density) {
     469         136 :         if (GestureRecognizer::canAddEvent(event)) {
     470         136 :                 _gesture.cleanup();
     471         136 :                 _gesture.pos = event.currentLocation;
     472         136 :                 _gesture.time.clear();
     473         136 :                 _gesture.limit = _interval;
     474         136 :                 _gesture.event = GestureEvent::Began;
     475         136 :                 _gesture.input = &event;
     476         136 :                 if (_callback(_gesture)) {
     477          90 :                         GestureRecognizer::addEvent(event, density);
     478          90 :                         _lastTime = Time::now();
     479          90 :                         _notified = false;
     480          90 :                         return InputEventState::Captured;
     481             :                 }
     482             :         }
     483          46 :         return InputEventState::Declined;
     484             : }
     485             : 
     486         163 : InputEventState GesturePressRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
     487         163 :         if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
     488          90 :                 float distance = event.originalLocation.distance(event.currentLocation);
     489          90 :                 _gesture.time = Time::now() - _lastTime;
     490          90 :                 _gesture.event = (successful && distance <= TapDistanceAllowed * density) ? GestureEvent::Ended : GestureEvent::Cancelled;
     491          90 :                 _gesture.input = &event;
     492          90 :                 _callback(_gesture);
     493          90 :                 _gesture.event = GestureEvent::Cancelled;
     494          90 :                 _gesture.input = nullptr;
     495          90 :                 _lastTime.clear();
     496          90 :                 _gesture.cleanup();
     497          90 :                 _notified = true;
     498          90 :                 return InputEventState::Processed;
     499             :         }
     500          73 :         return InputEventState::Declined;
     501             : }
     502             : 
     503         292 : InputEventState GesturePressRecognizer::renewEvent(const InputEvent &event, float density) {
     504         292 :         if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
     505          42 :                 if (event.originalLocation.distance(event.currentLocation) > TapDistanceAllowed * density) {
     506          21 :                         return removeEvent(event, false, density);
     507             :                 }
     508          21 :                 return InputEventState::Processed;
     509             :         }
     510         250 :         return InputEventState::Declined;
     511             : }
     512             : 
     513         174 : bool GestureSwipeRecognizer::init(InputCallback &&cb, float threshold, bool includeThreshold, ButtonMask &&btn) {
     514         174 :         if (!GestureRecognizer::init()) {
     515           0 :                 return false;
     516             :         }
     517             : 
     518         174 :         if (cb) {
     519         174 :                 _maxEvents = 2;
     520         174 :                 _callback = move(cb);
     521         174 :                 _threshold = threshold;
     522         174 :                 _includeThreshold = includeThreshold;
     523         174 :                 _buttonMask = move(btn);
     524             : 
     525             :                 // enable all touch events
     526         174 :                 _eventMask.set(toInt(InputEventName::Begin));
     527         174 :                 _eventMask.set(toInt(InputEventName::Move));
     528         174 :                 _eventMask.set(toInt(InputEventName::End));
     529         174 :                 _eventMask.set(toInt(InputEventName::Cancel));
     530         174 :                 return true;
     531             :         }
     532           0 :         return false;
     533             : }
     534             : 
     535          21 : void GestureSwipeRecognizer::cancel() {
     536          21 :         GestureRecognizer::cancel();
     537          21 :         _gesture.cleanup();
     538          21 :         _swipeBegin = false;
     539          21 :         _lastTime.clear();
     540          21 :         _currentTouch = maxOf<uint32_t>();
     541          21 : }
     542             : 
     543         109 : InputEventState GestureSwipeRecognizer::addEvent(const InputEvent &event, float density) {
     544         109 :         if (GestureRecognizer::addEvent(event, density) != InputEventState::Declined) {
     545         109 :                 Vec2 accum;
     546         239 :                 for (auto &it : _events) {
     547         130 :                         accum = accum + it.currentLocation;
     548             :                 }
     549         109 :                 accum /= float(_events.size());
     550             : 
     551         109 :                 _gesture.midpoint = accum;
     552         109 :                 _currentTouch = event.data.id;
     553         109 :                 _lastTime = Time::now();
     554         109 :                 return InputEventState::Processed;
     555             :         } else {
     556           0 :                 return InputEventState::Declined;
     557             :         }
     558             : }
     559             : 
     560         115 : InputEventState GestureSwipeRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
     561         115 :         if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
     562         109 :                 if (_events.size() > 0) {
     563          21 :                         _currentTouch = _events.back().data.id;
     564          21 :             _lastTime = Time::now();
     565             :                 } else {
     566          88 :                         if (_swipeBegin) {
     567          46 :                                 _gesture.event = successful ? GestureEvent::Ended : GestureEvent::Cancelled;
     568          46 :                                 _gesture.input = &event;
     569          46 :                                 _callback(_gesture);
     570             :                         }
     571             : 
     572          88 :                         _gesture.event = GestureEvent::Cancelled;
     573          88 :                         _gesture.input = nullptr;
     574          88 :                         _gesture.cleanup();
     575          88 :                         _swipeBegin = false;
     576             : 
     577          88 :                         _currentTouch = maxOf<uint32_t>();
     578             : 
     579          88 :                         _velocityX.dropValues();
     580          88 :                         _velocityY.dropValues();
     581             : 
     582          88 :             _lastTime.clear();
     583             :                 }
     584         109 :                 return InputEventState::Processed;
     585             :         }
     586           6 :         return InputEventState::Declined;
     587             : }
     588             : 
     589         334 : InputEventState GestureSwipeRecognizer::renewEvent(const InputEvent &event, float density) {
     590         334 :         if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
     591         334 :                 if (_events.size() == 1) {
     592         292 :                         Vec2 current = event.currentLocation;
     593         292 :                         Vec2 prev = (_swipeBegin)?event.previousLocation:event.originalLocation;
     594             : 
     595         292 :                         _gesture.secondTouch = _gesture.firstTouch = current;
     596         292 :                         _gesture.midpoint = current;
     597             : 
     598         292 :                         _gesture.delta = current - prev;
     599         292 :                         _gesture.density = density;
     600             : 
     601         292 :                         if (!_swipeBegin && _gesture.delta.length() > _threshold * density) {
     602          25 :                                 _gesture.cleanup();
     603          25 :                                 if (_includeThreshold) {
     604          25 :                                         _gesture.delta = current - prev;
     605             :                                 } else {
     606           0 :                                         _gesture.delta = current - event.previousLocation;
     607             :                                 }
     608          25 :                                 _gesture.secondTouch = _gesture.firstTouch = current;
     609          25 :                                 _gesture.midpoint = current;
     610             : 
     611          25 :                                 _swipeBegin = true;
     612          25 :                                 _gesture.event = GestureEvent::Began;
     613          25 :                                 _gesture.input = &event;
     614          25 :                                 if (!_callback(_gesture)) {
     615           0 :                                         _swipeBegin = false;
     616           0 :                                         cancel();
     617           0 :                                         return InputEventState::Declined;
     618             :                                 }
     619             : 
     620          25 :                                 if (_includeThreshold) {
     621          25 :                                         _gesture.delta = current - event.previousLocation;
     622             :                                 }
     623             :                         }
     624             : 
     625         292 :                         if (_swipeBegin /* && _gesture.delta.length() > 0.01f */) {
     626         271 :                                 auto t = Time::now();
     627         271 :                                 float tm = (float)1000000LL / (float)((t - _lastTime).toMicroseconds());
     628         271 :                                 if (tm > 80) {
     629          24 :                                         tm = 80;
     630             :                                 }
     631             : 
     632         271 :                                 float velX = _velocityX.step(_gesture.delta.x * tm);
     633         271 :                                 float velY = _velocityY.step(_gesture.delta.y * tm);
     634             : 
     635         271 :                                 _gesture.velocity = Vec2(velX, velY);
     636         271 :                                 _gesture.event = GestureEvent::Activated;
     637         271 :                                 _gesture.input = &event;
     638         271 :                                 if (!_callback(_gesture)) {
     639           0 :                                         cancel();
     640           0 :                                         return InputEventState::Declined;
     641             :                                 }
     642             : 
     643         271 :                                 _lastTime = t;
     644             :                         }
     645          42 :                 } else if (_events.size() == 2) {
     646          42 :                         Vec2 current = event.currentLocation;
     647          42 :                         Vec2 second = _gesture.secondTouch;
     648          42 :                         Vec2 prev = _gesture.midpoint;
     649             : 
     650          42 :                         _gesture.density = density;
     651             : 
     652          42 :                         if (event.data.id != _currentTouch) {
     653          21 :                                 second = _gesture.secondTouch = current;
     654          21 :                         } else if (event.data.id == _currentTouch) {
     655          21 :                                 _gesture.firstTouch = current;
     656          21 :                                 _gesture.midpoint = _gesture.secondTouch.getMidpoint(_gesture.firstTouch);
     657          21 :                                 _gesture.delta = _gesture.midpoint - prev;
     658             : 
     659          21 :                                 if (!_swipeBegin && _gesture.delta.length() > _threshold * density) {
     660          21 :                                         _gesture.cleanup();
     661          21 :                                         _gesture.firstTouch = current;
     662          21 :                                         _gesture.secondTouch = current;
     663          21 :                                         _gesture.midpoint = _gesture.secondTouch.getMidpoint(_gesture.firstTouch);
     664          21 :                                         _gesture.delta = _gesture.midpoint - prev;
     665             : 
     666          21 :                                         _swipeBegin = true;
     667          21 :                                         _gesture.event = GestureEvent::Began;
     668          21 :                                         _gesture.input = &event;
     669          21 :                                         if (!_callback(_gesture)) {
     670           0 :                                                 cancel();
     671           0 :                                                 return InputEventState::Declined;
     672             :                                         }
     673             :                                 }
     674             : 
     675          21 :                                 if (_swipeBegin /* && _gesture.delta.length() > 0.01f */ ) {
     676          21 :                                         auto t = Time::now();
     677          21 :                                         float tm = (float)1000000LL / (float)((t - _lastTime).toMicroseconds());
     678          21 :                                         if (tm > 80) {
     679          21 :                                                 tm = 80;
     680             :                                         }
     681             : 
     682          21 :                                         float velX = _velocityX.step(_gesture.delta.x * tm);
     683          21 :                                         float velY = _velocityY.step(_gesture.delta.y * tm);
     684             : 
     685          21 :                                         _gesture.velocity = Vec2(velX, velY);
     686          21 :                                         _gesture.event = GestureEvent::Activated;
     687          21 :                                         _gesture.input = &event;
     688          21 :                                         if (!_callback(_gesture)) {
     689           0 :                                                 cancel();
     690           0 :                                                 return InputEventState::Declined;
     691             :                                         }
     692             : 
     693          21 :                                         _lastTime = t;
     694             :                                 }
     695             :                         }
     696             :                 }
     697         334 :                 return _swipeBegin ? InputEventState::Captured : InputEventState::Processed;
     698             :         } else {
     699           0 :                 return InputEventState::Declined;
     700             :         }
     701             : }
     702             : 
     703          42 : bool GesturePinchRecognizer::init(InputCallback &&cb, ButtonMask &&btn) {
     704          42 :         if (!GestureRecognizer::init()) {
     705           0 :                 return false;
     706             :         }
     707             : 
     708          42 :         if (cb) {
     709          42 :                 _maxEvents = 2;
     710          42 :                 _callback = move(cb);
     711          42 :                 _buttonMask = move(btn);
     712             : 
     713             :                 // enable all touch events
     714          42 :                 _eventMask.set(toInt(InputEventName::Begin));
     715          42 :                 _eventMask.set(toInt(InputEventName::Move));
     716          42 :                 _eventMask.set(toInt(InputEventName::End));
     717          42 :                 _eventMask.set(toInt(InputEventName::Cancel));
     718          42 :                 return true;
     719             :         }
     720           0 :         return false;
     721             : }
     722             : 
     723          21 : void GesturePinchRecognizer::cancel() {
     724          21 :         GestureRecognizer::cancel();
     725          21 :         _gesture.cleanup();
     726          21 :         _velocity.dropValues();
     727          21 :         _lastTime.clear();
     728          21 : }
     729             : 
     730          42 : InputEventState GesturePinchRecognizer::addEvent(const InputEvent &event, float density) {
     731          42 :         if (GestureRecognizer::addEvent(event, density) != InputEventState::Declined) {
     732          42 :                 if (_events.size() == 2) {
     733          21 :                         _gesture.cleanup();
     734          21 :                         _gesture.first = _events.at(0).currentLocation;
     735          21 :                         _gesture.second = _events.at(1).currentLocation;
     736          21 :                         _gesture.center = _gesture.first.getMidpoint(_gesture.second);
     737          21 :                         _gesture.distance = _gesture.prevDistance = _gesture.startDistance = _gesture.first.distance(_gesture.second);
     738          21 :                         _gesture.scale = _gesture.distance / _gesture.startDistance;
     739          21 :                         _gesture.event = GestureEvent::Began;
     740          21 :                         _gesture.input = &_events.at(0);
     741          21 :                         _gesture.density = density;
     742          21 :                         _lastTime = Time::now();
     743          21 :                         if (_callback) {
     744          21 :                                 _callback(_gesture);
     745             :                         }
     746          21 :                         return InputEventState::Captured;
     747             :                 }
     748          21 :                 return InputEventState::Processed;
     749             :         } else {
     750           0 :                 return InputEventState::Declined;
     751             :         }
     752             : }
     753             : 
     754          42 : InputEventState GesturePinchRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
     755          42 :         if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
     756          42 :                 if (_events.size() == 1) {
     757          21 :                         _gesture.event = successful ? GestureEvent::Ended : GestureEvent::Cancelled;
     758          21 :                         if (_callback) {
     759          21 :                                 _callback(_gesture);
     760             :                         }
     761          21 :             _gesture.cleanup();
     762          21 :                         _lastTime.clear();
     763          21 :                         _velocity.dropValues();
     764             :                 }
     765          42 :                 return InputEventState::Processed;
     766             :         }
     767           0 :         return InputEventState::Declined;
     768             : }
     769             : 
     770          42 : InputEventState GesturePinchRecognizer::renewEvent(const InputEvent &event, float density) {
     771          42 :         if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
     772          42 :                 if (_events.size() == 2) {
     773          42 :                         auto &first = _events.at(0);
     774          42 :                         auto &second = _events.at(1);
     775          42 :                         if (event.data.id == first.data.id || event.data.id == second.data.id) {
     776          42 :                                 auto scale = _gesture.scale;
     777             : 
     778          42 :                                 _gesture.first = _events.at(0).currentLocation;
     779          42 :                                 _gesture.second = _events.at(1).currentLocation;
     780          42 :                                 _gesture.center = _gesture.first.getMidpoint(_gesture.second);
     781          42 :                                 _gesture.prevDistance = _events.at(0).previousLocation.distance(_events.at(1).previousLocation);
     782          42 :                                 _gesture.distance = _gesture.first.distance(_gesture.second);
     783          42 :                                 _gesture.scale = _gesture.distance / _gesture.startDistance;
     784          42 :                                 _gesture.density = density;
     785             : 
     786          42 :                                 auto t = Time::now();
     787          42 :                                 float tm = (float)1000000LL / (float)((t - _lastTime).toMicroseconds());
     788          42 :                                 if (tm > 80) {
     789          42 :                                         tm = 80;
     790             :                                 }
     791          42 :                                 _velocity.addValue((scale - _gesture.scale) * tm);
     792          42 :                                 _gesture.velocity = _velocity.getAverage();
     793             : 
     794          42 :                                 _gesture.event = GestureEvent::Activated;
     795          42 :                                 if (_callback) {
     796          42 :                                         _callback(_gesture);
     797             :                                 }
     798             : 
     799          42 :                                 _lastTime = t;
     800             :                         }
     801          42 :                         return InputEventState::Captured;
     802             :                 }
     803           0 :                 return InputEventState::Processed;
     804             :         }
     805           0 :         return InputEventState::Declined;
     806             : }
     807             : 
     808         132 : bool GestureScrollRecognizer::init(InputCallback &&cb) {
     809         132 :         if (!GestureRecognizer::init()) {
     810           0 :                 return false;
     811             :         }
     812             : 
     813         132 :         if (cb) {
     814         132 :                 _callback = move(cb);
     815         132 :                 _eventMask.set(toInt(InputEventName::Scroll));
     816         132 :                 return true;
     817             :         }
     818             : 
     819           0 :         return false;
     820             : }
     821             : 
     822         369 : InputEventState GestureScrollRecognizer::handleInputEvent(const InputEvent &event, float density) {
     823         369 :         if (!_eventMask.test(toInt(event.data.event))) {
     824         348 :                 return InputEventState::Declined;
     825             :         }
     826             : 
     827          21 :         _gesture.event = GestureEvent::Activated;
     828          21 :         _gesture.input = &event;
     829          21 :         _gesture.pos = event.currentLocation;
     830          21 :         _gesture.amount = Vec2(event.data.point.valueX, event.data.point.valueY);
     831          21 :         if (_callback) {
     832          21 :                 _callback(_gesture);
     833             :         }
     834          21 :         _gesture.event = GestureEvent::Cancelled;
     835          21 :         return InputEventState::Captured;
     836             : }
     837             : 
     838             : 
     839          42 : bool GestureMoveRecognizer::init(InputCallback &&cb, bool withinNode) {
     840          42 :         if (!GestureRecognizer::init()) {
     841           0 :                 return false;
     842             :         }
     843             : 
     844          42 :         if (cb) {
     845          42 :                 _callback = move(cb);
     846          42 :                 _eventMask.set(toInt(InputEventName::MouseMove));
     847          42 :                 _onlyWithinNode = withinNode;
     848          42 :                 return true;
     849             :         }
     850             : 
     851           0 :         return false;
     852             : }
     853             : 
     854        4152 : bool GestureMoveRecognizer::canHandleEvent(const InputEvent &event) const {
     855        4152 :         if (GestureRecognizer::canHandleEvent(event)) {
     856        4958 :                 if (!_onlyWithinNode || (_listener && _listener->getOwner()
     857        2458 :                                 && _listener->getOwner()->isTouched(event.currentLocation, _listener->getTouchPadding()))) {
     858        2484 :                         return true;
     859             :                 }
     860             :         }
     861        1668 :         return false;
     862             : }
     863             : 
     864        2873 : InputEventState GestureMoveRecognizer::handleInputEvent(const InputEvent &event, float density) {
     865        2873 :         if (!canHandleEvent(event)) {
     866        1631 :                 return InputEventState::Declined;
     867             :         }
     868             : 
     869        1242 :         if (!_eventMask.test(toInt(event.data.event))) {
     870           0 :                 return InputEventState::Declined;
     871             :         }
     872             : 
     873        1242 :         _event.event = GestureEvent::Activated;
     874        1242 :         _event.input = &event;
     875        1242 :         if (_callback) {
     876        1242 :                 _callback(_event);
     877             :         }
     878        1242 :         _event.input = nullptr;
     879        1242 :         _event.event = GestureEvent::Cancelled;
     880        1242 :         return InputEventState::Processed;
     881             : }
     882             : 
     883          21 : void GestureMoveRecognizer::onEnter(InputListener *l) {
     884          21 :         GestureRecognizer::onEnter(l);
     885          21 :         _listener = l;
     886          21 : }
     887             : 
     888          21 : void GestureMoveRecognizer::onExit() {
     889          21 :         _listener = nullptr;
     890          21 :         GestureRecognizer::onExit();
     891          21 : }
     892             : 
     893         126 : bool GestureKeyRecognizer::init(InputCallback &&cb, KeyMask &&mask) {
     894         126 :         if (!GestureRecognizer::init()) {
     895           0 :                 return false;
     896             :         }
     897             : 
     898         126 :         if (cb && mask.any()) {
     899         126 :                 _callback = move(cb);
     900         126 :                 _keyMask = mask;
     901         126 :                 _eventMask.set(toInt(InputEventName::KeyPressed));
     902         126 :                 _eventMask.set(toInt(InputEventName::KeyRepeated));
     903         126 :                 _eventMask.set(toInt(InputEventName::KeyReleased));
     904         126 :                 _eventMask.set(toInt(InputEventName::KeyCanceled));
     905         126 :                 return true;
     906             :         }
     907             : 
     908           0 :         log::error("GestureKeyRecognizer", "Callback or key mask is not defined");
     909           0 :         return false;
     910             : }
     911             : 
     912        4258 : bool GestureKeyRecognizer::canHandleEvent(const InputEvent &ev) const {
     913        4258 :         if (GestureRecognizer::canHandleEvent(ev)) {
     914         126 :                 if (_keyMask.test(toInt(ev.data.key.keycode))) {
     915          84 :                         return true;
     916             :                 }
     917             :         }
     918        4174 :         return false;
     919             : }
     920             : 
     921          42 : bool GestureKeyRecognizer::isKeyPressed(InputKeyCode code) const {
     922          42 :         if (_pressedKeys.test(toInt(code))) {
     923          21 :                 return true;
     924             :         }
     925          21 :         return false;
     926             : }
     927             : 
     928          42 : InputEventState GestureKeyRecognizer::addEvent(const InputEvent &event, float density) {
     929          42 :         if (_keyMask.test(toInt(event.data.key.keycode))) {
     930          42 :                 _pressedKeys.set(toInt(event.data.key.keycode));
     931          42 :                 return _callback(GestureData{GestureEvent::Began, &event}) ? InputEventState::Captured : InputEventState::Declined;
     932             :         }
     933           0 :         return InputEventState::Declined;
     934             : }
     935             : 
     936          42 : InputEventState GestureKeyRecognizer::removeEvent(const InputEvent &event, bool success, float density) {
     937          42 :         if (_pressedKeys.test(toInt(event.data.key.keycode))) {
     938          42 :                 _callback(GestureData{success ? GestureEvent::Ended : GestureEvent::Cancelled, &event});
     939          42 :                 _pressedKeys.reset(toInt(event.data.key.keycode));
     940          42 :                 return InputEventState::Processed;
     941             :         }
     942           0 :         return InputEventState::Declined;
     943             : }
     944             : 
     945          21 : InputEventState GestureKeyRecognizer::renewEvent(const InputEvent &event, float density) {
     946          21 :         if (_pressedKeys.test(toInt(event.data.key.keycode))) {
     947          21 :                 _callback(GestureData{GestureEvent::Activated, &event});
     948          21 :                 return InputEventState::Processed;
     949             :         }
     950           0 :         return InputEventState::Declined;
     951             : }
     952             : 
     953         447 : bool GestureMouseOverRecognizer::init(InputCallback &&cb, float padding) {
     954         447 :         if (!GestureRecognizer::init()) {
     955           0 :                 return false;
     956             :         }
     957             : 
     958         447 :         if (cb) {
     959         447 :                 _callback = move(cb);
     960         447 :                 _eventMask.set(toInt(InputEventName::MouseMove));
     961         447 :                 _eventMask.set(toInt(InputEventName::FocusGain));
     962         447 :                 _eventMask.set(toInt(InputEventName::PointerEnter));
     963         447 :                 return true;
     964             :         }
     965             : 
     966           0 :         log::error("GestureKeyRecognizer", "Callback or key mask is not defined");
     967           0 :         return false;
     968             : }
     969             : 
     970         760 : InputEventState GestureMouseOverRecognizer::handleInputEvent(const InputEvent &event, float density) {
     971         760 :         switch (event.data.event) {
     972          43 :         case InputEventName::FocusGain:
     973          43 :                 if (_viewHasFocus != event.data.getValue()) {
     974          41 :                         _viewHasFocus = event.data.getValue();
     975          41 :                         updateState(event);
     976             :                 }
     977          43 :                 break;
     978          49 :         case InputEventName::PointerEnter:
     979          49 :                 if (_viewHasPointer != event.data.getValue()) {
     980          45 :                         _viewHasPointer = event.data.getValue();
     981          45 :                         updateState(event);
     982             :                 }
     983          49 :                 break;
     984         572 :         case InputEventName::MouseMove:
     985         572 :                 if (auto tar = _listener->getOwner()) {
     986         572 :                         auto v = tar->isTouched(event.currentLocation, _padding);
     987         572 :                         if (_hasMouseOver != v) {
     988          21 :                                 _hasMouseOver = v;
     989          21 :                                 updateState(event);
     990             :                         }
     991             :                 } else {
     992           0 :                         if (_hasMouseOver) {
     993           0 :                                 _hasMouseOver = false;
     994           0 :                                 updateState(event);
     995             :                         }
     996             :                 }
     997         572 :                 break;
     998          96 :         default:
     999          96 :                 break;
    1000             :         }
    1001         760 :         return InputEventState::Processed;
    1002             : }
    1003             : 
    1004         426 : void GestureMouseOverRecognizer::onEnter(InputListener *l) {
    1005         426 :         GestureRecognizer::onEnter(l);
    1006         426 :         _listener = l;
    1007             : 
    1008         426 :         auto dispatcher = l->getOwner()->getDirector()->getInputDispatcher();
    1009             : 
    1010         426 :         _viewHasPointer = dispatcher->isPointerWithinWindow();
    1011         426 :         _viewHasFocus = dispatcher->hasFocus();
    1012         426 : }
    1013             : 
    1014         426 : void GestureMouseOverRecognizer::onExit() {
    1015         426 :         _listener = nullptr;
    1016         426 :         GestureRecognizer::onExit();
    1017         426 : }
    1018             : 
    1019         107 : void GestureMouseOverRecognizer::updateState(const InputEvent &event) {
    1020         107 :         auto value = _viewHasFocus && _viewHasPointer && _hasMouseOver;
    1021         107 :         if (value != _value) {
    1022           4 :                 _value = value;
    1023           4 :                 _event.input = &event;
    1024           4 :                 _event.event = _value ? GestureEvent::Began : GestureEvent::Ended;
    1025           4 :                 _callback(_event);
    1026             :         }
    1027         107 : }
    1028             : 
    1029          84 : std::ostream &operator<<(std::ostream &stream, GestureEvent ev) {
    1030          84 :         switch (ev) {
    1031          21 :         case GestureEvent::Began: stream << "GestureEvent::Began"; break;
    1032          21 :         case GestureEvent::Activated: stream << "GestureEvent::Activated"; break;
    1033          21 :         case GestureEvent::Ended: stream << "GestureEvent::Ended"; break;
    1034          21 :         case GestureEvent::Cancelled: stream << "GestureEvent::Cancelled"; break;
    1035             :         }
    1036          84 :         return stream;
    1037             : }
    1038             : 
    1039             : }

Generated by: LCOV version 1.14