From 2d2c7ee8e03cb88f250bfaab17cf7f18526053b4 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 18 Sep 2023 20:35:23 +0200 Subject: [PATCH] added tolerance --- client/eventsSDL/InputSourceMouse.cpp | 2 +- client/eventsSDL/InputSourceTouch.cpp | 5 ++- client/gui/EventDispatcher.cpp | 52 +++++++++++++++++---------- client/gui/EventDispatcher.h | 3 +- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/client/eventsSDL/InputSourceMouse.cpp b/client/eventsSDL/InputSourceMouse.cpp index ec971c645..dc9d8227f 100644 --- a/client/eventsSDL/InputSourceMouse.cpp +++ b/client/eventsSDL/InputSourceMouse.cpp @@ -48,7 +48,7 @@ void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & b { case SDL_BUTTON_LEFT: if(button.clicks > 1) - GH.events().dispatchMouseDoubleClick(position); + GH.events().dispatchMouseDoubleClick(position, 0); else GH.events().dispatchMouseLeftButtonPressed(position, 0); break; diff --git a/client/eventsSDL/InputSourceTouch.cpp b/client/eventsSDL/InputSourceTouch.cpp index fdf794ab1..ef80833f0 100644 --- a/client/eventsSDL/InputSourceTouch.cpp +++ b/client/eventsSDL/InputSourceTouch.cpp @@ -182,7 +182,10 @@ void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger) { GH.input().setCursorPosition(convertTouchToMouse(tfinger)); if(tfinger.timestamp - lastLeftClickTimeTicks < params.doubleTouchTimeMilliseconds && (convertTouchToMouse(tfinger) - lastLeftClickPosition).length() < params.doubleTouchToleranceDistance) - GH.events().dispatchMouseDoubleClick(convertTouchToMouse(tfinger)); + { + GH.events().dispatchMouseDoubleClick(convertTouchToMouse(tfinger), params.touchToleranceDistance); + GH.events().dispatchMouseLeftButtonReleased(convertTouchToMouse(tfinger), params.touchToleranceDistance); + } else { GH.events().dispatchMouseLeftButtonPressed(convertTouchToMouse(tfinger), params.touchToleranceDistance); diff --git a/client/gui/EventDispatcher.cpp b/client/gui/EventDispatcher.cpp index 36e5822f2..3dc576f5e 100644 --- a/client/gui/EventDispatcher.cpp +++ b/client/gui/EventDispatcher.cpp @@ -116,25 +116,9 @@ void EventDispatcher::dispatchShortcutReleased(const std::vector & sh } } -void EventDispatcher::dispatchMouseDoubleClick(const Point & position) +void EventDispatcher::dispatchMouseDoubleClick(const Point & position, int tolerance) { - bool doubleClicked = false; - auto hlp = doubleClickInterested; - - for(auto & i : hlp) - { - if(!vstd::contains(doubleClickInterested, i)) - continue; - - if(i->receiveEvent(position, AEventsReceiver::DOUBLECLICK)) - { - i->clickDouble(position); - doubleClicked = true; - } - } - - if(!doubleClicked) - handleLeftButtonClick(position, 0, true); + handleDoubleButtonClick(position, tolerance); } void EventDispatcher::dispatchMouseLeftButtonPressed(const Point & position, int tolerance) @@ -246,6 +230,38 @@ void EventDispatcher::handleLeftButtonClick(const Point & position, int toleranc } } +void EventDispatcher::handleDoubleButtonClick(const Point & position, int tolerance) +{ + // WARNING: this approach is NOT SAFE + // 1) We allow (un)registering elements when list itself is being processed/iterated + // 2) To avoid iterator invalidation we create a copy of this list for processing + // HOWEVER it is completely possible (as in, actually happen, no just theory) to: + // 1) element gets unregistered and deleted from lclickable + // 2) element is completely deleted, as in - destructor called, memory freed + // 3) new element is created *with exactly same address(!) + // 4) new element is registered and code will incorrectly assume that this element is still registered + // POSSIBLE SOLUTION: make EventReceivers inherit from create_shared_from this and store weak_ptr's in lists + + AEventsReceiver * nearestElement = findElementInToleranceRange(doubleClickInterested, position, AEventsReceiver::DOUBLECLICK, tolerance); + bool doubleClicked = false; + auto hlp = doubleClickInterested; + + for(auto & i : hlp) + { + if(!vstd::contains(doubleClickInterested, i)) + continue; + + if(i->receiveEvent(position, AEventsReceiver::DOUBLECLICK) || i == nearestElement) + { + i->clickDouble(position); + doubleClicked = true; + } + } + + if(!doubleClicked) + handleLeftButtonClick(position, tolerance, true); +} + void EventDispatcher::dispatchMouseScrolled(const Point & distance, const Point & position) { EventReceiversList hlp = wheelInterested; diff --git a/client/gui/EventDispatcher.h b/client/gui/EventDispatcher.h index dee3d77cd..0ab25ed5c 100644 --- a/client/gui/EventDispatcher.h +++ b/client/gui/EventDispatcher.h @@ -36,6 +36,7 @@ class EventDispatcher EventReceiversList panningInterested; void handleLeftButtonClick(const Point & position, int tolerance, bool isPressed); + void handleDoubleButtonClick(const Point & position, int tolerance); AEventsReceiver * findElementInToleranceRange(const EventReceiversList & list, const Point & position, int eventToTest, int tolerance); template @@ -59,7 +60,7 @@ public: void dispatchMouseLeftButtonPressed(const Point & position, int tolerance); void dispatchMouseLeftButtonReleased(const Point & position, int tolerance); void dispatchMouseScrolled(const Point & distance, const Point & position); - void dispatchMouseDoubleClick(const Point & position); + void dispatchMouseDoubleClick(const Point & position, int tolerance); void dispatchMouseMoved(const Point & distance, const Point & position); void dispatchMouseDragged(const Point & currentPosition, const Point & lastUpdateDistance);