blob: 9dd13fbd86695d99569df32db5b0b543352b94f5 [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ui/a11y/lib/gesture_manager/gesture_handler_v2.h"
#include <lib/syslog/cpp/macros.h>
#include "src/ui/a11y/lib/gesture_manager/recognizers_v2/any_recognizer.h"
#include "src/ui/a11y/lib/gesture_manager/recognizers_v2/directional_swipe_recognizers.h"
#include "src/ui/a11y/lib/gesture_manager/recognizers_v2/m_finger_n_tap_drag_recognizer.h"
#include "src/ui/a11y/lib/gesture_manager/recognizers_v2/m_finger_n_tap_recognizer.h"
#include "src/ui/a11y/lib/gesture_manager/recognizers_v2/one_finger_drag_recognizer.h"
#include "src/ui/a11y/lib/gesture_manager/recognizers_v2/one_finger_n_tap_recognizer.h"
#include "src/ui/a11y/lib/gesture_manager/recognizers_v2/two_finger_drag_recognizer.h"
namespace a11y {
namespace {
using a11y::recognizers_v2 ::AnyRecognizer;
using a11y::recognizers_v2 ::DownSwipeGestureRecognizer;
using a11y::recognizers_v2 ::LeftSwipeGestureRecognizer;
using a11y::recognizers_v2 ::MFingerNTapDragRecognizer;
using a11y::recognizers_v2 ::MFingerNTapRecognizer;
using a11y::recognizers_v2 ::OneFingerDragRecognizer;
using a11y::recognizers_v2 ::RightSwipeGestureRecognizer;
using a11y::recognizers_v2 ::TwoFingerDragRecognizer;
using a11y::recognizers_v2 ::UpSwipeGestureRecognizer;
// This recognizer is stateless and trivial, so it makes sense as static.
AnyRecognizer consume_all;
} // namespace
GestureHandlerV2::GestureHandlerV2(AddRecognizerToArenaCallback add_recognizer_callback)
: add_recognizer_callback_(std::move(add_recognizer_callback)) {}
void GestureHandlerV2::OnGesture(const GestureType gesture_type, const GestureEvent gesture_event,
a11y::gesture_util_v2::GestureContext gesture_context) {
auto it = gesture_handlers_.find(gesture_type);
if (it == gesture_handlers_.end()) {
FX_LOGS(INFO) << "GestureHandlerV2::OnGesture: No action found for GestureType:"
<< gesture_type;
return;
}
switch (gesture_event) {
case GestureEvent::kRecognize:
FX_DCHECK(it->second.on_recognize);
it->second.on_recognize(gesture_context);
break;
case GestureEvent::kUpdate:
FX_DCHECK(it->second.on_update);
it->second.on_update(gesture_context);
break;
case GestureEvent::kComplete:
FX_DCHECK(it->second.on_complete);
it->second.on_complete(gesture_context);
break;
default:
break;
}
}
bool GestureHandlerV2::BindMFingerNTapAction(uint32_t num_fingers, uint32_t num_taps,
OnGestureCallback on_recognize) {
GestureType gesture_type = kUnknown;
// This computation is just to make the switch statement cleaner.
// Since m and n are always <= 3, we can uniquely identify the type of an
// m-finger-n-tap with the integer (10m + n). E.g. a 3-finger-double-tap would
// be type 32.
auto gesture_type_id = 10 * num_fingers + num_taps;
switch (gesture_type_id) {
case 11:
gesture_type = kOneFingerSingleTap;
break;
case 12:
gesture_type = kOneFingerDoubleTap;
break;
case 13:
gesture_type = kOneFingerTripleTap;
break;
case 21:
gesture_type = kTwoFingerSingleTap;
break;
case 32:
gesture_type = kThreeFingerDoubleTap;
break;
default:
break;
}
if (gesture_type == kUnknown) {
return false;
}
if (gesture_recognizers_.find(gesture_type) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for GestureType: " << gesture_type;
return false;
}
gesture_handlers_[gesture_type].on_recognize = std::move(on_recognize);
gesture_recognizers_[gesture_type] = std::make_unique<MFingerNTapRecognizer>(
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kRecognize, context);
},
num_fingers, num_taps);
add_recognizer_callback_(gesture_recognizers_[gesture_type].get());
return true;
}
bool GestureHandlerV2::BindOneFingerSingleTapAction(OnGestureCallback callback) {
return BindOneFingerNTapAction(std::move(callback), 1);
}
bool GestureHandlerV2::BindOneFingerDoubleTapAction(OnGestureCallback callback) {
return BindOneFingerNTapAction(std::move(callback), 2);
}
bool GestureHandlerV2::BindOneFingerNTapAction(OnGestureCallback callback, int number_of_taps) {
GestureType gesture_type = kUnknown;
switch (number_of_taps) {
case 1:
gesture_type = kOneFingerSingleTap;
break;
case 2:
gesture_type = kOneFingerDoubleTap;
break;
default:
return false;
}
if (gesture_recognizers_.find(gesture_type) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for GestureType: " << gesture_type;
return false;
}
gesture_handlers_[gesture_type].on_complete = std::move(callback);
gesture_recognizers_[gesture_type] = std::make_unique<recognizers_v2::OneFingerNTapRecognizer>(
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kComplete, context);
},
number_of_taps);
add_recognizer_callback_(gesture_recognizers_[gesture_type].get());
return true;
}
bool GestureHandlerV2::BindOneFingerDragAction(OnGestureCallback on_recognize,
OnGestureCallback on_update,
OnGestureCallback on_complete) {
if (gesture_recognizers_.find(kOneFingerDrag) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for one finger drag.";
return false;
}
gesture_handlers_[kOneFingerDrag] = {std::move(on_recognize), std::move(on_update),
std::move(on_complete)};
gesture_recognizers_[kOneFingerDrag] = std::make_unique<OneFingerDragRecognizer>(
[this](a11y::gesture_util_v2::GestureContext context) {
OnGesture(kOneFingerDrag, GestureEvent::kRecognize, context);
}, /* on recognize */
[this](a11y::gesture_util_v2::GestureContext context) {
OnGesture(kOneFingerDrag, GestureEvent::kUpdate, context);
}, /* on update */
[this](a11y::gesture_util_v2::GestureContext context) {
OnGesture(kOneFingerDrag, GestureEvent::kComplete, context);
} /* on complete */);
add_recognizer_callback_(gesture_recognizers_[kOneFingerDrag].get());
return true;
}
bool GestureHandlerV2::BindTwoFingerDragAction(OnGestureCallback on_recognize,
OnGestureCallback on_update,
OnGestureCallback on_complete) {
if (gesture_recognizers_.find(kTwoFingerDrag) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for two finger drag.";
return false;
}
gesture_handlers_[kTwoFingerDrag] = {std::move(on_recognize), std::move(on_update),
std::move(on_complete)};
gesture_recognizers_[kTwoFingerDrag] = std::make_unique<TwoFingerDragRecognizer>(
[this](a11y::gesture_util_v2::GestureContext context) {
OnGesture(kTwoFingerDrag, GestureEvent::kRecognize, context);
}, /* drag start callback */
[this](a11y::gesture_util_v2::GestureContext context) {
OnGesture(kTwoFingerDrag, GestureEvent::kUpdate, context);
}, /* drag update callback */
[this](a11y::gesture_util_v2::GestureContext context) {
OnGesture(kTwoFingerDrag, GestureEvent::kComplete, context);
} /* drag completion callback */);
add_recognizer_callback_(gesture_recognizers_[kTwoFingerDrag].get());
return true;
}
bool GestureHandlerV2::BindSwipeAction(OnGestureCallback callback, GestureType gesture_type) {
switch (gesture_type) {
case kOneFingerUpSwipe:
case kThreeFingerUpSwipe:
return BindUpSwipeAction(std::move(callback), gesture_type);
case kOneFingerDownSwipe:
case kThreeFingerDownSwipe:
return BindDownSwipeAction(std::move(callback), gesture_type);
case kOneFingerLeftSwipe:
case kThreeFingerLeftSwipe:
return BindLeftSwipeAction(std::move(callback), gesture_type);
break;
case kOneFingerRightSwipe:
case kThreeFingerRightSwipe:
return BindRightSwipeAction(std::move(callback), gesture_type);
break;
default:
break;
}
return false;
}
bool GestureHandlerV2::BindUpSwipeAction(OnGestureCallback callback, GestureType gesture_type) {
uint32_t number_of_fingers;
switch (gesture_type) {
case kOneFingerUpSwipe:
number_of_fingers = 1;
break;
case kThreeFingerUpSwipe:
number_of_fingers = 3;
break;
default:
return false;
}
if (gesture_recognizers_.find(gesture_type) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for Up Swipe gesture with " << number_of_fingers
<< " finger.";
return false;
}
gesture_handlers_[gesture_type].on_complete = std::move(callback);
gesture_recognizers_[gesture_type] = std::make_unique<UpSwipeGestureRecognizer>(
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kComplete, context);
},
number_of_fingers);
add_recognizer_callback_(gesture_recognizers_[gesture_type].get());
return true;
}
bool GestureHandlerV2::BindDownSwipeAction(OnGestureCallback callback, GestureType gesture_type) {
uint32_t number_of_fingers;
switch (gesture_type) {
case kOneFingerDownSwipe:
number_of_fingers = 1;
break;
case kThreeFingerDownSwipe:
number_of_fingers = 3;
break;
default:
return false;
}
if (gesture_recognizers_.find(gesture_type) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for Down Swipe gesture with " << number_of_fingers
<< " finger.";
return false;
}
gesture_handlers_[gesture_type].on_complete = std::move(callback);
gesture_recognizers_[gesture_type] = std::make_unique<DownSwipeGestureRecognizer>(
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kComplete, context);
},
number_of_fingers);
add_recognizer_callback_(gesture_recognizers_[gesture_type].get());
return true;
}
bool GestureHandlerV2::BindLeftSwipeAction(OnGestureCallback callback, GestureType gesture_type) {
uint32_t number_of_fingers;
switch (gesture_type) {
case kOneFingerLeftSwipe:
number_of_fingers = 1;
break;
case kThreeFingerLeftSwipe:
number_of_fingers = 3;
break;
default:
return false;
}
if (gesture_recognizers_.find(gesture_type) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for Left Swipe gesture with " << number_of_fingers
<< " finger.";
return false;
}
gesture_handlers_[gesture_type].on_complete = std::move(callback);
gesture_recognizers_[gesture_type] = std::make_unique<LeftSwipeGestureRecognizer>(
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kComplete, context);
},
number_of_fingers);
add_recognizer_callback_(gesture_recognizers_[gesture_type].get());
return true;
}
bool GestureHandlerV2::BindRightSwipeAction(OnGestureCallback callback, GestureType gesture_type) {
uint32_t number_of_fingers;
switch (gesture_type) {
case kOneFingerRightSwipe:
number_of_fingers = 1;
break;
case kThreeFingerRightSwipe:
number_of_fingers = 3;
break;
default:
return false;
}
if (gesture_recognizers_.find(gesture_type) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for Right Swipe gesture with " << number_of_fingers
<< " finger.";
return false;
}
gesture_handlers_[gesture_type].on_complete = std::move(callback);
gesture_recognizers_[gesture_type] = std::make_unique<RightSwipeGestureRecognizer>(
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kComplete, context);
},
number_of_fingers);
add_recognizer_callback_(gesture_recognizers_[gesture_type].get());
return true;
}
bool GestureHandlerV2::BindTwoFingerSingleTapAction(OnGestureCallback callback) {
if (gesture_recognizers_.find(kTwoFingerSingleTap) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for GestureType: " << kTwoFingerSingleTap;
return false;
}
gesture_handlers_[kTwoFingerSingleTap].on_complete = std::move(callback);
gesture_recognizers_[kTwoFingerSingleTap] = std::make_unique<MFingerNTapRecognizer>(
[this](a11y::gesture_util_v2::GestureContext context) {
OnGesture(kTwoFingerSingleTap, GestureEvent::kComplete, context);
},
2, // number of fingers
1 /* number of taps */);
add_recognizer_callback_(gesture_recognizers_[kTwoFingerSingleTap].get());
return true;
}
bool GestureHandlerV2::BindMFingerNTapDragAction(OnGestureCallback on_recognize,
OnGestureCallback on_update,
OnGestureCallback on_complete,
uint32_t num_fingers, uint32_t num_taps) {
GestureType gesture_type = kUnknown;
// This computation is just to make the switch statement cleaner.
// Since m and n are always <= 3, we can uniquely identify the type of an
// m-finger-n-tap with the integer (10m + n). E.g. a 3-finger-double-tap would
// be type 32.
const int32_t gesture_type_id = 10 * num_fingers + num_taps;
switch (gesture_type_id) {
case 12:
gesture_type = kOneFingerDoubleTapDrag;
break;
case 13:
gesture_type = kOneFingerTripleTapDrag;
break;
case 32:
gesture_type = kThreeFingerDoubleTapDrag;
break;
default:
break;
}
if (gesture_type == kUnknown) {
return false;
}
if (gesture_recognizers_.find(gesture_type) != gesture_recognizers_.end()) {
FX_LOGS(INFO) << "Action already exists for GestureType: " << gesture_type;
return false;
}
gesture_handlers_[gesture_type].on_recognize = std::move(on_recognize);
gesture_handlers_[gesture_type].on_update = std::move(on_update);
gesture_handlers_[gesture_type].on_complete = std::move(on_complete);
gesture_recognizers_[gesture_type] = std::make_unique<MFingerNTapDragRecognizer>(
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kRecognize, context);
}, /* on recognize */
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kUpdate, context);
}, /* on update */
[this, gesture_type](a11y::gesture_util_v2::GestureContext context) {
OnGesture(gesture_type, GestureEvent::kComplete, context);
}, /* on complete */
num_fingers, num_taps);
add_recognizer_callback_(gesture_recognizers_[gesture_type].get());
return true;
}
void GestureHandlerV2::ConsumeAll() { add_recognizer_callback_(&consume_all); }
void GestureHandlerV2::Clear() {
gesture_handlers_.clear();
gesture_recognizers_.clear();
}
} // namespace a11y