new framework

Signed-off-by: wangzezhen <wangzezhen@huawei.com>
Change-Id: I25253be71a5b63dfc64c4201c2e5bddcd4d1e35e
This commit is contained in:
wangzezhen 2022-09-21 19:20:59 +08:00
parent e48b6ccef3
commit 5510cc38da
58 changed files with 5707 additions and 132 deletions

View File

@ -20,6 +20,17 @@
#include "frameworks/bridge/declarative_frontend/jsview/js_interactable_view.h"
#include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
#include "frameworks/core/components/gesture_listener/gesture_component.h"
#include "frameworks/core/components_ng/gestures/recognizers/exclusive_recognizer.h"
#include "frameworks/core/components_ng/gestures/gesture_group.h"
#include "frameworks/core/components_ng/gestures/long_press_gesture.h"
#include "frameworks/core/components_ng/gestures/pan_gesture.h"
#include "frameworks/core/components_ng/gestures/recognizers/parallel_recognizer.h"
#include "frameworks/core/components_ng/gestures/pinch_gesture.h"
#include "frameworks/core/components_ng/gestures/rotation_gesture.h"
#include "frameworks/core/components_ng/gestures/swipe_gesture.h"
#include "frameworks/core/components_ng/gestures/tap_gesture.h"
#include "frameworks/core/gestures/exclusive_recognizer.h"
#include "frameworks/core/gestures/gesture_group.h"
#include "frameworks/core/gestures/long_press_gesture.h"
@ -61,6 +72,13 @@ constexpr char ROTATION_ANGLE[] = "angle";
void JSGesture::Create(const JSCallbackInfo& info)
{
LOGD("JS gesture create");
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
}
GesturePriority priority = GesturePriority::Low;
if (info.Length() > 0 && info[0]->IsNumber()) {
int32_t priorityNum = info[0]->ToNumber<int32_t>();
@ -69,14 +87,6 @@ void JSGesture::Create(const JSCallbackInfo& info)
priority = static_cast<GesturePriority>(priorityNum);
}
}
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
}
gestureProcessor->SetPriority(priority);
GestureMask gestureMask = GestureMask::Normal;
@ -97,17 +107,14 @@ void JSGesture::Finish()
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
NG::ViewStackProcessor::GetInstance()->ResetGestureProcessor();
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
};
auto gesture = gestureProcessor->FinishGesture();
if (!gesture) {
LOGE("gesture is not exist when component finish");
return;
}
gesture->SetGestureMask(gestureProcessor->GetGestureMask());
gesture->SetPriority(gestureProcessor->GetPriority());
if (Container::IsCurrentUseNewPipeline()) {
auto gesture = gestureProcessor->FinishGestureNG();
if (!gesture) {
LOGE("gesture is not exist when component finish");
return;
}
gesture->SetGestureMask(gestureProcessor->GetGestureMask());
gesture->SetPriority(gestureProcessor->GetPriority());
auto gestureEventHub = NG::ViewStackProcessor::GetInstance()->GetMainFrameNodeGestureEventHub();
if (gestureEventHub) {
gestureEventHub->AddGesture(gesture);
@ -115,6 +122,14 @@ void JSGesture::Finish()
return;
}
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
auto gesture = gestureProcessor->FinishGesture();
if (!gesture) {
LOGE("gesture is not exist when component finish");
return;
}
gesture->SetGestureMask(gestureProcessor->GetGestureMask());
gesture->SetPriority(gestureProcessor->GetPriority());
auto boxComponent = ViewStackProcessor::GetInstance()->GetBoxComponent();
boxComponent->AddGesture(gestureProcessor->GetPriority(), gesture);
}
@ -125,14 +140,16 @@ void JSGesture::Pop()
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
gestureProcessor->PopGestureNG();
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
gestureProcessor->PopGesture();
};
gestureProcessor->PopGesture();
}
void JSTapGesture::Create(const JSCallbackInfo& args)
{
LOGD("JSTapGesture Create");
int32_t countNum = DEFAULT_TAP_COUNT;
int32_t fingersNum = DEFAULT_TAP_FINGER;
if (args.Length() > 0 && args[0]->IsObject()) {
@ -144,7 +161,6 @@ void JSTapGesture::Create(const JSCallbackInfo& args)
int32_t countNumber = count->ToNumber<int32_t>();
countNum = countNumber <= DEFAULT_TAP_COUNT ? DEFAULT_TAP_COUNT : countNumber;
}
if (fingers->IsNumber()) {
int32_t fingersNumber = fingers->ToNumber<int32_t>();
fingersNum = fingersNumber <= DEFAULT_TAP_FINGER ? DEFAULT_TAP_FINGER : fingersNumber;
@ -155,17 +171,18 @@ void JSTapGesture::Create(const JSCallbackInfo& args)
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
auto gesture = AceType::MakeRefPtr<NG::TapGesture>(countNum, fingersNum);
gestureProcessor->PushGestureNG(gesture);
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
auto gesture = AceType::MakeRefPtr<TapGesture>(countNum, fingersNum);
gestureProcessor->PushGesture(gesture);
}
auto gesture = AceType::MakeRefPtr<OHOS::Ace::TapGesture>(countNum, fingersNum);
gestureProcessor->PushGesture(gesture);
}
void JSLongPressGesture::Create(const JSCallbackInfo& args)
{
LOGD("JSLongPressGesture Create");
int32_t fingersNum = DEFAULT_LONG_PRESS_FINGER;
bool repeatResult = false;
int32_t durationNum = DEFAULT_LONG_PRESS_DURATION;
@ -179,11 +196,9 @@ void JSLongPressGesture::Create(const JSCallbackInfo& args)
int32_t fingersNumber = fingers->ToNumber<int32_t>();
fingersNum = fingersNumber <= DEFAULT_LONG_PRESS_FINGER ? DEFAULT_LONG_PRESS_FINGER : fingersNumber;
}
if (repeat->IsBoolean()) {
repeatResult = repeat->ToBoolean();
}
if (duration->IsNumber()) {
int32_t durationNumber = duration->ToNumber<int32_t>();
durationNum = durationNumber <= 0 ? DEFAULT_LONG_PRESS_DURATION : durationNumber;
@ -193,38 +208,53 @@ void JSLongPressGesture::Create(const JSCallbackInfo& args)
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
auto gesture = AceType::MakeRefPtr<NG::LongPressGesture>(fingersNum, repeatResult, durationNum);
gestureProcessor->PushGestureNG(gesture);
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
auto gesture = AceType::MakeRefPtr<LongPressGesture>(fingersNum, repeatResult, durationNum);
gestureProcessor->PushGesture(gesture);
}
auto gesture = AceType::MakeRefPtr<OHOS::Ace::LongPressGesture>(fingersNum, repeatResult, durationNum);
gestureProcessor->PushGesture(gesture);
}
void JSPanGesture::Create(const JSCallbackInfo& args)
{
LOGD("JSPanGesture Create");
int32_t fingersNum = DEFAULT_PAN_FINGER;
double distanceNum = DEFAULT_PAN_DISTANCE;
PanDirection panDirection;
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
if (args.Length() <= 0 || !args[0]->IsObject()) {
auto gesture = AceType::MakeRefPtr<NG::PanGesture>(fingersNum, panDirection, distanceNum);
gestureProcessor->PushGestureNG(gesture);
return;
}
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
}
if (args.Length() <= 0 || !args[0]->IsObject()) {
auto gesture = AceType::MakeRefPtr<OHOS::Ace::PanGesture>(fingersNum, panDirection, distanceNum);
gestureProcessor->PushGesture(gesture);
return;
if (args.Length() <= 0 || !args[0]->IsObject()) {
auto gesture = AceType::MakeRefPtr<PanGesture>(fingersNum, panDirection, distanceNum);
gestureProcessor->PushGesture(gesture);
return;
}
}
JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
JSPanGestureOption* panGestureOption = obj->Unwrap<JSPanGestureOption>();
if (panGestureOption != nullptr) {
auto gesture = AceType::MakeRefPtr<OHOS::Ace::PanGesture>(panGestureOption->GetPanGestureOption());
gestureProcessor->PushGesture(gesture);
return;
if (Container::IsCurrentUseNewPipeline()) {
if (panGestureOption != nullptr) {
auto gesture = AceType::MakeRefPtr<NG::PanGesture>(panGestureOption->GetPanGestureOption());
gestureProcessor->PushGestureNG(gesture);
return;
}
} else {
if (panGestureOption != nullptr) {
auto gesture = AceType::MakeRefPtr<PanGesture>(panGestureOption->GetPanGestureOption());
gestureProcessor->PushGesture(gesture);
return;
}
}
JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
@ -235,12 +265,10 @@ void JSPanGesture::Create(const JSCallbackInfo& args)
int32_t fingersNumber = fingers->ToNumber<int32_t>();
fingersNum = fingersNumber <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingersNumber;
}
if (distance->IsNumber()) {
double distanceNumber = distance->ToNumber<double>();
distanceNum = LessNotEqual(distanceNumber, 0.0) ? DEFAULT_PAN_DISTANCE : distanceNumber;
}
if (directionNum->IsNumber()) {
uint32_t directNum = directionNum->ToNumber<uint32_t>();
if (directNum >= static_cast<uint32_t>(PanDirection::NONE) &&
@ -248,29 +276,40 @@ void JSPanGesture::Create(const JSCallbackInfo& args)
panDirection.type = directNum;
}
}
auto gesture = AceType::MakeRefPtr<OHOS::Ace::PanGesture>(fingersNum, panDirection, distanceNum);
gestureProcessor->PushGesture(gesture);
if (Container::IsCurrentUseNewPipeline()) {
auto gesture = AceType::MakeRefPtr<NG::PanGesture>(fingersNum, panDirection, distanceNum);
gestureProcessor->PushGestureNG(gesture);
} else {
auto gesture = AceType::MakeRefPtr<PanGesture>(fingersNum, panDirection, distanceNum);
gestureProcessor->PushGesture(gesture);
}
}
void JSSwipeGesture::Create(const JSCallbackInfo& args)
{
LOGD("JSSwipeGesture Create");
int32_t fingersNum = DEFAULT_SLIDE_FINGER;
double speedNum = DEFAULT_SLIDE_SPEED;
SwipeDirection slideDirection;
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
if (args.Length() <= 0 || !args[0]->IsObject()) {
auto gesture = AceType::MakeRefPtr<NG::SwipeGesture>(fingersNum, slideDirection, speedNum);
gestureProcessor->PushGestureNG(gesture);
return;
}
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
if (args.Length() <= 0 || !args[0]->IsObject()) {
auto gesture = AceType::MakeRefPtr<SwipeGesture>(fingersNum, slideDirection, speedNum);
gestureProcessor->PushGesture(gesture);
return;
}
};
if (args.Length() <= 0 || !args[0]->IsObject()) {
auto gesture = AceType::MakeRefPtr<SwipeGesture>(fingersNum, slideDirection, speedNum);
gestureProcessor->PushGesture(gesture);
return;
}
JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
JSRef<JSVal> speed = obj->GetProperty(GESTURE_SPEED);
JSRef<JSVal> directionNum = obj->GetProperty(SWIPE_DIRECTION);
@ -279,12 +318,10 @@ void JSSwipeGesture::Create(const JSCallbackInfo& args)
int32_t fingersNumber = fingers->ToNumber<int32_t>();
fingersNum = fingersNumber <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingersNumber;
}
if (speed->IsNumber()) {
double speedNumber = speed->ToNumber<double>();
speedNum = LessNotEqual(speedNumber, 0.0) ? DEFAULT_SLIDE_SPEED : speedNumber;
}
if (directionNum->IsNumber()) {
uint32_t directNum = directionNum->ToNumber<uint32_t>();
if (directNum >= static_cast<uint32_t>(SwipeDirection::NONE) &&
@ -292,14 +329,19 @@ void JSSwipeGesture::Create(const JSCallbackInfo& args)
slideDirection.type = directNum;
}
}
auto gesture = AceType::MakeRefPtr<SwipeGesture>(fingersNum, slideDirection, speedNum);
gestureProcessor->PushGesture(gesture);
if (Container::IsCurrentUseNewPipeline()) {
auto gesture = AceType::MakeRefPtr<NG::SwipeGesture>(fingersNum, slideDirection, speedNum);
gestureProcessor->PushGestureNG(gesture);
} else {
auto gesture = AceType::MakeRefPtr<SwipeGesture>(fingersNum, slideDirection, speedNum);
gestureProcessor->PushGesture(gesture);
}
}
void JSPinchGesture::Create(const JSCallbackInfo& args)
{
LOGD("JSPinchGesture Create");
int32_t fingersNum = DEFAULT_PINCH_FINGER;
double distanceNum = DEFAULT_PINCH_DISTANCE;
if (args.Length() > 0 && args[0]->IsObject()) {
@ -320,17 +362,18 @@ void JSPinchGesture::Create(const JSCallbackInfo& args)
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
auto gesture = AceType::MakeRefPtr<NG::PinchGesture>(fingersNum, distanceNum);
gestureProcessor->PushGestureNG(gesture);
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
auto gesture = AceType::MakeRefPtr<PinchGesture>(fingersNum, distanceNum);
gestureProcessor->PushGesture(gesture);
};
auto gesture = AceType::MakeRefPtr<OHOS::Ace::PinchGesture>(fingersNum, distanceNum);
gestureProcessor->PushGesture(gesture);
}
void JSRotationGesture::Create(const JSCallbackInfo& args)
{
LOGD("JSRotationGesture Create");
double angleNum = DEFAULT_ROTATION_ANGLE;
int32_t fingersNum = DEFAULT_ROTATION_FINGER;
if (args.Length() > 0 && args[0]->IsObject()) {
@ -342,7 +385,6 @@ void JSRotationGesture::Create(const JSCallbackInfo& args)
int32_t fingersNumber = fingers->ToNumber<int32_t>();
fingersNum = fingersNumber <= DEFAULT_ROTATION_FINGER ? DEFAULT_ROTATION_FINGER : fingersNumber;
}
if (angle->IsNumber()) {
double angleNumber = angle->ToNumber<double>();
angleNum = LessNotEqual(angleNumber, 0.0) ? DEFAULT_ROTATION_ANGLE : angleNumber;
@ -352,17 +394,18 @@ void JSRotationGesture::Create(const JSCallbackInfo& args)
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
auto gesture = AceType::MakeRefPtr<NG::RotationGesture>(fingersNum, angleNum);
gestureProcessor->PushGestureNG(gesture);
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
auto gesture = AceType::MakeRefPtr<RotationGesture>(fingersNum, angleNum);
gestureProcessor->PushGesture(gesture);
};
auto gesture = AceType::MakeRefPtr<OHOS::Ace::RotationGesture>(fingersNum, angleNum);
gestureProcessor->PushGesture(gesture);
}
void JSGestureGroup::Create(const JSCallbackInfo& args)
{
int32_t gestureMode = 0;
if (args.Length() > 0 && args[0]->IsNumber()) {
gestureMode = args[0]->ToNumber<int32_t>();
}
@ -371,11 +414,14 @@ void JSGestureGroup::Create(const JSCallbackInfo& args)
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
auto gesture = AceType::MakeRefPtr<NG::GestureGroup>(static_cast<GestureMode>(gestureMode));
gestureProcessor->PushGestureNG(gesture);
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
auto gesture = AceType::MakeRefPtr<GestureGroup>(static_cast<GestureMode>(gestureMode));
gestureProcessor->PushGesture(gesture);
};
auto gesture = AceType::MakeRefPtr<OHOS::Ace::GestureGroup>(static_cast<GestureMode>(gestureMode));
gestureProcessor->PushGesture(gesture);
}
void JSGesture::JsHandlerOnGestureEvent(JSGestureEvent action, const JSCallbackInfo& args)
@ -388,27 +434,65 @@ void JSGesture::JsHandlerOnGestureEvent(JSGestureEvent action, const JSCallbackI
RefPtr<GestureProcessor> gestureProcessor;
if (Container::IsCurrentUseNewPipeline()) {
gestureProcessor = NG::ViewStackProcessor::GetInstance()->GetOrCreateGestureProcessor();
} else {
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
};
auto gesture = gestureProcessor->TopGestureNG();
if (!gesture) {
LOGE("top gesture is illegal");
return;
}
RefPtr<JsGestureFunction> handlerFunc = AceType::MakeRefPtr<JsGestureFunction>(JSRef<JSFunc>::Cast(args[0]));
if (action == JSGestureEvent::CANCEL) {
auto onActionCancelFunc = [execCtx = args.GetExecutionContext(), func = std::move(handlerFunc)]() {
JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
auto info = GestureEvent();
ACE_SCORING_EVENT("Gesture.onCancel");
func->Execute(info);
};
gesture->SetOnActionCancelId(onActionCancelFunc);
return;
}
auto onActionFunc = [execCtx = args.GetExecutionContext(), func = std::move(handlerFunc)](
GestureEvent& info) {
JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
ACE_SCORING_EVENT("Gesture.onActionCancel");
func->Execute(info);
};
switch (action) {
case JSGestureEvent::ACTION:
gesture->SetOnActionId(onActionFunc);
break;
case JSGestureEvent::START:
gesture->SetOnActionStartId(onActionFunc);
break;
case JSGestureEvent::UPDATE:
gesture->SetOnActionUpdateId(onActionFunc);
break;
case JSGestureEvent::END:
gesture->SetOnActionEndId(onActionFunc);
break;
default:
LOGW("Unknown gesture action %{public}d", action);
break;
}
return;
}
gestureProcessor = ViewStackProcessor::GetInstance()->GetGestureComponent();
auto gesture = gestureProcessor->TopGesture();
if (!gesture) {
LOGE("top gesture is illegal");
return;
}
RefPtr<JsGestureFunction> handlerFunc = AceType::MakeRefPtr<JsGestureFunction>(JSRef<JSFunc>::Cast(args[0]));
RefPtr<V2::InspectorFunctionImpl> impl;
if (!Container::IsCurrentUseNewPipeline()) {
auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
if (!inspector) {
LOGE("fail to get inspector for on handle event");
return;
}
impl = inspector->GetInspectorFunctionImpl();
auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
if (!inspector) {
LOGE("fail to get inspector for on handle event");
return;
}
impl = inspector->GetInspectorFunctionImpl();
if (action == JSGestureEvent::CANCEL) {
auto onActionCancelFunc = [execCtx = args.GetExecutionContext(), func = std::move(handlerFunc), impl]() {
@ -534,12 +618,10 @@ void JSPanGestureOption::Constructor(const JSCallbackInfo& args)
int32_t fingersNumber = fingers->ToNumber<int32_t>();
fingersNum = fingersNumber <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingersNumber;
}
if (distance->IsNumber()) {
double distanceNumber = distance->ToNumber<double>();
distanceNum = LessNotEqual(distanceNumber, 0.0) ? DEFAULT_PAN_DISTANCE : distanceNumber;
}
if (directionNum->IsNumber()) {
uint32_t directNum = directionNum->ToNumber<uint32_t>();
if (directNum >= static_cast<uint32_t>(PanDirection::NONE) &&

View File

@ -19,6 +19,7 @@
#include "frameworks/bridge/declarative_frontend/jsview/js_pan_handler.h"
#include "frameworks/bridge/declarative_frontend/jsview/js_touch_handler.h"
#include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h"
#include "frameworks/core/components_ng/gestures/tap_gesture.h"
#include "frameworks/core/gestures/tap_gesture.h"
#include "frameworks/core/pipeline/base/component.h"

View File

@ -345,6 +345,7 @@ template("ace_core_source_set") {
deps += [
"$ace_root/frameworks/core/components_ng/base:ace_core_components_base_ng_$platform",
"$ace_root/frameworks/core/components_ng/event:ace_core_components_event_ng_$platform",
"$ace_root/frameworks/core/components_ng/gestures:ace_core_components_gestures_ng_$platform",
"$ace_root/frameworks/core/components_ng/image_provider:ace_core_components_image_provider_ng_$platform",
"$ace_root/frameworks/core/components_ng/layout:ace_core_components_layout_ng_$platform",
"$ace_root/frameworks/core/components_ng/manager:ace_core_components_manager_ng_$platform",
@ -641,6 +642,7 @@ template("ace_core_ng_source_set") {
deps += [
"$ace_root/frameworks/core/components_ng/base:ace_core_components_base_ng_$platform",
"$ace_root/frameworks/core/components_ng/event:ace_core_components_event_ng_$platform",
"$ace_root/frameworks/core/components_ng/gestures:ace_core_components_gestures_ng_$platform",
"$ace_root/frameworks/core/components_ng/image_provider:ace_core_components_image_provider_ng_$platform",
"$ace_root/frameworks/core/components_ng/layout:ace_core_components_layout_ng_$platform",
"$ace_root/frameworks/core/components_ng/manager:ace_core_components_manager_ng_$platform",

View File

@ -17,6 +17,7 @@
#include "base/geometry/ng/point_t.h"
#include "base/log/ace_trace.h"
#include "base/memory/ace_type.h"
#include "base/utils/utils.h"
#include "core/components_ng/base/frame_node.h"
#include "core/event/key_event.h"
@ -68,7 +69,7 @@ void EventManager::TouchTest(const TouchEvent& touchPoint, const RefPtr<NG::Fram
return;
}
// first clean.
referee_->CleanGestureScope(touchPoint.id);
refereeNG_->CleanGestureScope(touchPoint.id);
// collect
TouchTestResult hitTestResult;
const NG::PointF point { touchPoint.x, touchPoint.y };
@ -220,6 +221,7 @@ bool EventManager::DispatchTouchEvent(const TouchEvent& point)
if (point.type == TouchType::UP || point.type == TouchType::CANCEL) {
referee_->CleanGestureScope(point.id);
refereeNG_->CleanGestureScope(point.id);
touchTestResults_.erase(point.id);
}
@ -539,6 +541,7 @@ EventManager::EventManager()
{
LOGI("EventManger Constructor.");
referee_ = AceType::MakeRefPtr<GestureReferee>();
refereeNG_ = AceType::MakeRefPtr<NG::GestureReferee>();
}
} // namespace OHOS::Ace

View File

@ -20,6 +20,7 @@
#include "base/memory/ace_type.h"
#include "base/memory/referenced.h"
#include "core/components_ng/gestures/gesture_referee.h"
#include "core/event/axis_event.h"
#include "core/event/key_event.h"
#include "core/event/mouse_event.h"
@ -129,6 +130,11 @@ public:
return referee_;
}
RefPtr<NG::GestureReferee> GetGestureRefereeNG()
{
return refereeNG_;
}
private:
std::unordered_map<size_t, TouchTestResult> touchTestResults_;
std::unordered_map<size_t, MouseTestResult> mouseTestResults_;
@ -146,6 +152,7 @@ private:
int32_t instanceId_ = 0;
bool inSelectedRect_ = false;
RefPtr<GestureReferee> referee_;
RefPtr<NG::GestureReferee> refereeNG_;
};
} // namespace OHOS::Ace

View File

@ -538,7 +538,7 @@ HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& pare
const TouchRestrict& touchRestrict, TouchTestResult& result)
{
const auto& rect = geometryNode_->GetFrame().GetRect();
LOGI("TouchTest: type is %{public}s, the region is %{public}s", GetTag().c_str(), rect.ToString().c_str());
LOGD("TouchTest: type is %{public}s, the region is %{public}s", GetTag().c_str(), rect.ToString().c_str());
if (!rect.IsInRegion(parentLocalPoint)) {
return HitTestResult::OUT_OF_REGION;
@ -577,6 +577,11 @@ HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& pare
}
}
result.splice(result.end(), std::move(newComingTargets));
auto gestureHub = eventHub_->GetGestureEventHub();
if (gestureHub) {
gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result);
}
if (preventBubbling) {
return HitTestResult::STOP_BUBBLING;
}

View File

@ -18,7 +18,7 @@
#include "base/utils/utils.h"
#include "core/components_ng/base/frame_node.h"
#include "core/components_ng/event/gesture_event_hub.h"
#include "core/gestures/click_recognizer.h"
#include "core/components_ng/gestures/recognizers/click_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
@ -38,7 +38,7 @@ void ClickEventActuator::OnCollectTouchTarget(const OffsetF& coordinateOffset, c
auto frameNode = gestureHub->GetFrameNode();
CHECK_NULL_VOID(frameNode);
auto clickRecognizer = MakeRefPtr<ClickRecognizer>(frameNode->GetContext());
auto clickRecognizer = MakeRefPtr<ClickRecognizer>();
auto callback = [weak = WeakClaim(this)](GestureEvent& info) {
auto actuator = weak.Upgrade();
CHECK_NULL_VOID(actuator);

View File

@ -22,7 +22,6 @@
#include "core/components_ng/base/geometry_node.h"
#include "core/components_ng/event/gesture_event_hub.h"
#include "core/event/ace_event_handler.h"
#include "core/gestures/click_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
#include "core/pipeline_ng/ui_task_scheduler.h"

View File

@ -18,12 +18,12 @@
#include "core/components_ng/base/geometry_node.h"
#include "core/event/key_event.h"
#include "core/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class FrameNode;
class FocusHub;
class ClickInfo;
class EventHub;
using TabIndexNodeList = std::list<std::pair<int32_t, WeakPtr<FocusHub>>>;

View File

@ -15,10 +15,11 @@
#include "core/components_ng/event/gesture_event_hub.h"
#include "base/memory/ace_type.h"
#include "core/components_ng/base/frame_node.h"
#include "core/components_ng/event/event_hub.h"
#include "core/gestures/exclusive_recognizer.h"
#include "core/gestures/parallel_recognizer.h"
#include "core/components_ng/gestures/recognizers/exclusive_recognizer.h"
#include "core/components_ng/gestures/recognizers/parallel_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
@ -34,28 +35,7 @@ RefPtr<FrameNode> GestureEventHub::GetFrameNode() const
bool GestureEventHub::ProcessTouchTestHit(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict,
TouchTestResult& innerTargets, TouchTestResult& finalResult)
{
auto eventHub = eventHub_.Upgrade();
auto getEventTargetImpl = eventHub ? eventHub->CreateGetEventTargetImpl() : nullptr;
if (scrollableActuator_) {
// TODO: need to change scrollable to be gesture recognizer to make gesture referee works.
scrollableActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, innerTargets);
}
if (touchEventActuator_) {
touchEventActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, innerTargets);
}
if (clickEventActuator_) {
clickEventActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, innerTargets);
}
if (panEventActuator_) {
panEventActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, innerTargets);
}
std::list<RefPtr<GestureRecognizer>> innerRecognizers;
for (auto const& eventTarget : innerTargets) {
auto recognizer = AceType::DynamicCast<GestureRecognizer>(eventTarget);
if (recognizer) {
@ -64,9 +44,24 @@ bool GestureEventHub::ProcessTouchTestHit(const OffsetF& coordinateOffset, const
finalResult.push_back(eventTarget);
}
}
ProcessTouchTestHierarchy(coordinateOffset, touchRestrict, innerRecognizers, finalResult);
auto eventHub = eventHub_.Upgrade();
auto getEventTargetImpl = eventHub ? eventHub->CreateGetEventTargetImpl() : nullptr;
if (scrollableActuator_) {
// TODO: need to change scrollable to be gesture recognizer to make gesture referee works.
scrollableActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, finalResult);
}
if (touchEventActuator_) {
touchEventActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, finalResult);
}
if (clickEventActuator_) {
clickEventActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, finalResult);
}
if (panEventActuator_) {
panEventActuator_->OnCollectTouchTarget(coordinateOffset, touchRestrict, getEventTargetImpl, finalResult);
}
return false;
}
@ -89,8 +84,11 @@ void GestureEventHub::ProcessTouchTestHierarchy(const OffsetF& coordinateOffset,
if (innerRecognizers.size() == 1) {
current = *innerRecognizers.begin();
} else if (innerRecognizers.size() > 1) {
current = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(innerRecognizers));
current->SetCoordinateOffset(offset);
if (!innerExclusiveRecognizer_) {
innerExclusiveRecognizer_ = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(innerRecognizers));
innerExclusiveRecognizer_->SetCoordinateOffset(offset);
}
current = innerExclusiveRecognizer_;
}
if (recreateGesture_) {
@ -118,8 +116,11 @@ void GestureEventHub::ProcessTouchTestHierarchy(const OffsetF& coordinateOffset,
}
if (recognizers.size() > 1) {
current = AceType::MakeRefPtr<ParallelRecognizer>(std::move(recognizers));
current->SetCoordinateOffset(offset);
if (!externalParallelRecognizer_ || recreateGesture_) {
externalParallelRecognizer_ = AceType::MakeRefPtr<ParallelRecognizer>(std::move(recognizers));
externalParallelRecognizer_->SetCoordinateOffset(offset);
}
current = externalParallelRecognizer_;
} else if (recognizers.size() == 1) {
current = *recognizers.begin();
}
@ -133,8 +134,11 @@ void GestureEventHub::ProcessTouchTestHierarchy(const OffsetF& coordinateOffset,
}
if (recognizers.size() > 1) {
current = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(recognizers));
current->SetCoordinateOffset(offset);
if (!externalExclusiveRecognizer_ || recreateGesture_) {
externalExclusiveRecognizer_ = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(recognizers));
externalExclusiveRecognizer_->SetCoordinateOffset(offset);
}
current = externalExclusiveRecognizer_;
} else if (recognizers.size() == 1) {
current = *recognizers.begin();
}
@ -154,7 +158,7 @@ void GestureEventHub::UpdateGestureHierarchy()
auto iter = gestures_.begin();
auto recognizerIter = gestureHierarchy_.begin();
for (; iter != gestures_.end(); iter++, recognizerIter++) {
auto newRecognizer = (*iter)->CreateRecognizer(host->GetContext());
auto newRecognizer = (*iter)->CreateRecognizer();
success = success && (*recognizerIter)->ReconcileFrom(newRecognizer);
if (!success) {
break;
@ -172,7 +176,7 @@ void GestureEventHub::UpdateGestureHierarchy()
if (!gesture) {
continue;
}
auto recognizer = gesture->CreateRecognizer(host->GetContext());
auto recognizer = gesture->CreateRecognizer();
if (!recognizer) {
continue;
}
@ -185,4 +189,37 @@ void GestureEventHub::UpdateGestureHierarchy()
gestures_.clear();
}
void GestureEventHub::CombineIntoExclusiveRecognizer(const PointF& globalPoint, const PointF& localPoint,
TouchTestResult& result)
{
TouchTestResult finalResult;
std::list<RefPtr<GestureRecognizer>> recognizers;
const auto coordinateOffset = globalPoint - localPoint;
auto offset = Offset(coordinateOffset.GetX(), coordinateOffset.GetY());
for (auto const& eventTarget : result) {
auto recognizer = AceType::DynamicCast<GestureRecognizer>(eventTarget);
if (recognizer) {
recognizers.push_back(std::move(recognizer));
} else {
finalResult.push_back(eventTarget);
}
}
RefPtr<GestureRecognizer> current;
if (recognizers.size() == 1) {
current = *recognizers.begin();
} else if (recognizers.size() > 1) {
if (!nodeExclusiveRecognizer_) {
nodeExclusiveRecognizer_ = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(recognizers));
nodeExclusiveRecognizer_->SetCoordinateOffset(offset);
}
current = nodeExclusiveRecognizer_;
}
if (current) {
finalResult.emplace_back(std::move(current));
}
result.swap(finalResult);
}
} // namespace OHOS::Ace::NG

View File

@ -18,12 +18,15 @@
#include <list>
#include "base/geometry/ng/point_t.h"
#include "base/memory/referenced.h"
#include "core/components/common/layout/constants.h"
#include "core/components_ng/event/click_event.h"
#include "core/components_ng/event/pan_event.h"
#include "core/components_ng/event/scrollable_event.h"
#include "core/components_ng/event/touch_event.h"
#include "core/components_ng/gestures/recognizers/exclusive_recognizer.h"
#include "core/components_ng/gestures/recognizers/parallel_recognizer.h"
namespace OHOS::Ace::NG {
@ -70,7 +73,7 @@ public:
explicit GestureEventHub(const WeakPtr<EventHub>& eventHub);
~GestureEventHub() override = default;
void AddGesture(const RefPtr<Gesture>& gesture)
void AddGesture(const RefPtr<NG::Gesture>& gesture)
{
if (!recreateGesture_) {
gestures_.clear();
@ -188,6 +191,9 @@ public:
hitTestMode_ = hitTestMode;
}
void CombineIntoExclusiveRecognizer(const PointF& globalPoint, const PointF& localPoint,
TouchTestResult& result);
private:
void ProcessTouchTestHierarchy(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict,
std::list<RefPtr<GestureRecognizer>>& innerRecognizers, TouchTestResult& finalResult);
@ -199,9 +205,13 @@ private:
RefPtr<TouchEventActuator> touchEventActuator_;
RefPtr<ClickEventActuator> clickEventActuator_;
RefPtr<PanEventActuator> panEventActuator_;
RefPtr<ExclusiveRecognizer> innerExclusiveRecognizer_;
RefPtr<ExclusiveRecognizer> externalExclusiveRecognizer_;
RefPtr<ExclusiveRecognizer> nodeExclusiveRecognizer_;
RefPtr<ParallelRecognizer> externalParallelRecognizer_;
// Set by use gesture, priorityGesture and parallelGesture attribute function.
std::list<RefPtr<Gesture>> gestures_;
std::list<RefPtr<NG::Gesture>> gestures_;
std::list<RefPtr<GestureRecognizer>> gestureHierarchy_;
HitTestMode hitTestMode_ = HitTestMode::DEFAULT;
bool recreateGesture_ = true;

View File

@ -18,6 +18,7 @@
#include "base/utils/utils.h"
#include "core/components_ng/base/frame_node.h"
#include "core/components_ng/event/gesture_event_hub.h"
#include "core/components_ng/gestures/recognizers/pan_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
@ -38,7 +39,7 @@ PanEventActuator::PanEventActuator(const WeakPtr<GestureEventHub>& gestureEventH
CHECK_NULL_VOID(gestureHub);
auto frameNode = gestureHub->GetFrameNode();
CHECK_NULL_VOID(frameNode);
panRecognizer_ = MakeRefPtr<PanRecognizer>(frameNode->GetContext(), fingers_, direction_, distance_);
panRecognizer_ = MakeRefPtr<PanRecognizer>(fingers_, direction_, distance_);
}
void PanEventActuator::OnCollectTouchTarget(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict,

View File

@ -21,12 +21,12 @@
#include "base/memory/referenced.h"
#include "core/components_ng/event/gesture_event_actuator.h"
#include "core/gestures/gesture_info.h"
#include "core/gestures/pan_recognizer.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class GestureEventHub;
class PanRecognizer;
class PanEvent : public Referenced {
public:

View File

@ -0,0 +1,42 @@
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import(
"//foundation/arkui/ace_engine/frameworks/core/components_ng/components.gni")
build_component_ng("gestures_ng") {
sources = [
# gestures
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/gesture_group.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/gesture_referee.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/long_press_gesture.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/pan_gesture.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/pinch_gesture.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/rotation_gesture.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/swipe_gesture.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/tap_gesture.cpp",
# recognizers
"recognizers/click_recognizer.cpp",
"recognizers/exclusive_recognizer.cpp",
"recognizers/gesture_recognizer.cpp",
"recognizers/long_press_recognizer.cpp",
"recognizers/multi_fingers_recognizer.cpp",
"recognizers/pan_recognizer.cpp",
"recognizers/parallel_recognizer.cpp",
"recognizers/pinch_recognizer.cpp",
"recognizers/rotation_recognizer.cpp",
"recognizers/sequenced_recognizer.cpp",
"recognizers/swipe_recognizer.cpp",
]
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/gesture_group.h"
#include "core/components_ng/gestures/recognizers/exclusive_recognizer.h"
#include "core/components_ng/gestures/recognizers/parallel_recognizer.h"
#include "core/components_ng/gestures/recognizers/sequenced_recognizer.h"
namespace OHOS::Ace::NG {
RefPtr<GestureRecognizer> GestureGroup::CreateRecognizer()
{
LOGD("create gesture group, sub size %{public}zu, mode %{public}d", gestures_.size(), mode_);
std::vector<RefPtr<GestureRecognizer>> recognizers;
for (auto& subGesture : gestures_) {
auto recognizer = subGesture->CreateRecognizer();
if (recognizer) {
recognizers.emplace_back(recognizer);
}
}
RefPtr<GestureRecognizer> groupRecognizer;
switch (mode_) {
case GestureMode::Sequence:
groupRecognizer = AceType::MakeRefPtr<SequencedRecognizer>(recognizers);
if (onActionCancelId_) {
groupRecognizer->SetOnActionCancel(*onActionCancelId_);
}
break;
case GestureMode::Parallel:
groupRecognizer = AceType::MakeRefPtr<ParallelRecognizer>(recognizers);
break;
case GestureMode::Exclusive:
groupRecognizer = AceType::MakeRefPtr<ExclusiveRecognizer>(recognizers);
break;
default:
LOGE("unknown gesture mode %{public}d when create gesture group recognizer", mode_);
return nullptr;
}
groupRecognizer->SetPriority(priority_);
groupRecognizer->SetPriorityMask(gestureMask_);
return groupRecognizer;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_GROUP_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_GROUP_H
#include <functional>
#include <string>
#include <vector>
#include "base/geometry/offset.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class ACE_EXPORT GestureGroup : public Gesture {
DECLARE_ACE_TYPE(GestureGroup, Gesture);
public:
GestureGroup(GestureMode mode, const std::vector<RefPtr<Gesture>>& gestures) : mode_(mode), gestures_(gestures) {}
explicit GestureGroup(GestureMode mode) : mode_(mode) {}
~GestureGroup() override = default;
void AddGesture(RefPtr<Gesture> gesture)
{
gestures_.emplace_back(gesture);
}
protected:
RefPtr<GestureRecognizer> CreateRecognizer() override;
private:
GestureMode mode_;
std::vector<RefPtr<Gesture>> gestures_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_GROUP_H

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_INFO_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_INFO_H
#include <functional>
#include <list>
#include <string>
#include <unordered_map>
#include <vector>
#include "base/geometry/offset.h"
#include "base/geometry/point.h"
#include "base/image/pixel_map.h"
#include "base/memory/ace_type.h"
#include "base/utils/event_callback.h"
#include "base/utils/macros.h"
#include "base/utils/type_definition.h"
#include "core/event/ace_events.h"
#include "core/gestures/gesture_info.h"
#include "core/gestures/velocity.h"
#include "core/gestures/velocity_tracker.h"
namespace OHOS::Ace::NG {
class GestureRecognizer;
class ACE_EXPORT Gesture : public virtual AceType {
DECLARE_ACE_TYPE(Gesture, AceType);
public:
Gesture() = default;
explicit Gesture(int32_t fingers) : fingers_(fingers) {}
~Gesture() override = default;
void SetOnActionId(const GestureEventFunc& onActionId)
{
onActionId_ = std::make_unique<GestureEventFunc>(onActionId);
}
void SetOnActionStartId(const GestureEventFunc& onActionStartId)
{
onActionStartId_ = std::make_unique<GestureEventFunc>(onActionStartId);
}
void SetOnActionUpdateId(const GestureEventFunc& onActionUpdateId)
{
onActionUpdateId_ = std::make_unique<GestureEventFunc>(onActionUpdateId);
}
void SetOnActionEndId(const GestureEventFunc& onActionEndId)
{
onActionEndId_ = std::make_unique<GestureEventFunc>(onActionEndId);
}
void SetOnActionCancelId(const GestureEventNoParameter& onActionCancelId)
{
onActionCancelId_ = std::make_unique<GestureEventNoParameter>(onActionCancelId);
}
void SetPriority(GesturePriority priority)
{
priority_ = priority;
}
void SetGestureMask(GestureMask gestureMask)
{
gestureMask_ = gestureMask;
}
GesturePriority GetPriority() const
{
return priority_;
}
GestureMask GetGestureMask() const
{
return gestureMask_;
}
virtual RefPtr<GestureRecognizer> CreateRecognizer() = 0;
protected:
int32_t fingers_ = 1;
GesturePriority priority_ = GesturePriority::Low;
GestureMask gestureMask_ = GestureMask::Normal;
std::unique_ptr<GestureEventFunc> onActionId_;
std::unique_ptr<GestureEventFunc> onActionStartId_;
std::unique_ptr<GestureEventFunc> onActionUpdateId_;
std::unique_ptr<GestureEventFunc> onActionEndId_;
std::unique_ptr<GestureEventNoParameter> onActionCancelId_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_INFO_H

View File

@ -0,0 +1,422 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/gesture_referee.h"
#include "core/components_ng/gestures/recognizers/gesture_recognizer.h"
namespace OHOS::Ace::NG {
void GestureScope::AddMember(const RefPtr<GestureRecognizer>& recognizer)
{
if (!recognizer) {
LOGE("gesture recognizer is null, AddMember failed.");
return;
}
if (Existed(recognizer)) {
LOGE("gesture recognizer has already been added.");
return;
}
recognizer->SetRefereeState(RefereeState::DETECTING);
switch (recognizer->GetPriority()) {
case GesturePriority::Parallel:
parallelRecognizers_.emplace_back(recognizer);
break;
case GesturePriority::High:
highRecognizers_.emplace_back(recognizer);
break;
case GesturePriority::Low:
lowRecognizers_.emplace_back(recognizer);
break;
default:
LOGW("Add unknown type member %{public}d to referee", recognizer->GetPriority());
break;
}
}
void GestureScope::DelMember(const RefPtr<GestureRecognizer>& recognizer)
{
if (!recognizer) {
LOGI("gesture recognizer is null, DelMember finish.");
return;
}
if (!Existed(recognizer)) {
LOGI("gesture recognizer is not existed when deleted.");
return;
}
LOGD("gesture referee ready to delete member of %{public}s", AceType::TypeName(recognizer));
RefereeState prevState = recognizer->GetRefereeState();
recognizer->SetRefereeState(RefereeState::DETECTING);
if (recognizer->GetPriority() == GesturePriority::Parallel) {
parallelRecognizers_.remove(recognizer);
return;
}
RemoveAndUnBlockGesture(prevState == RefereeState::PENDING, recognizer);
}
void GestureScope::HandleGestureDisposal(const RefPtr<GestureRecognizer>& recognizer, const GestureDisposal disposal)
{
if (!Existed(recognizer)) {
LOGE("can not find the recognizer");
return;
}
GesturePriority priority = recognizer->GetPriority();
if (priority == GesturePriority::Parallel) {
HandleParallelDisposal(recognizer, disposal);
return;
}
switch (disposal) {
case GestureDisposal::ACCEPT:
HandleAcceptDisposal(recognizer);
break;
case GestureDisposal::PENDING:
HandlePendingDisposal(recognizer);
break;
case GestureDisposal::REJECT:
HandleRejectDisposal(recognizer);
break;
default:
LOGW("handle known gesture disposal %{public}d", disposal);
break;
}
}
void GestureScope::HandleParallelDisposal(const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
{
if (disposal == GestureDisposal::REJECT) {
parallelRecognizers_.remove(recognizer);
recognizer->SetRefereeState(RefereeState::FAIL);
recognizer->OnRejected(touchId_);
} else if (disposal == GestureDisposal::ACCEPT) {
parallelRecognizers_.remove(recognizer);
recognizer->SetRefereeState(RefereeState::SUCCEED);
recognizer->OnAccepted(touchId_);
}
}
void GestureScope::HandleAcceptDisposal(const RefPtr<GestureRecognizer>& recognizer)
{
if (CheckNeedBlocked(recognizer)) {
LOGI("gesture referee ready to notify block for %{public}s", AceType::TypeName(recognizer));
recognizer->SetRefereeState(RefereeState::BLOCKED);
return;
}
LOGI("gesture referee accept %{public}s of id %{public}zu", AceType::TypeName(recognizer), touchId_);
AcceptGesture(recognizer);
}
void GestureScope::HandlePendingDisposal(const RefPtr<GestureRecognizer>& recognizer)
{
if (CheckNeedBlocked(recognizer)) {
LOGI("gesture referee ready to notify block for %{public}s", AceType::TypeName(recognizer));
recognizer->SetRefereeState(RefereeState::BLOCKED);
return;
}
LOGI("gesture referee ready to notify pending for %{public}s", AceType::TypeName(recognizer));
recognizer->SetRefereeState(RefereeState::PENDING);
recognizer->OnPending(touchId_);
}
void GestureScope::HandleRejectDisposal(const RefPtr<GestureRecognizer>& recognizer)
{
LOGI("gesture referee ready to notify reject for %{public}s", AceType::TypeName(recognizer));
RefereeState prevState = recognizer->GetRefereeState();
recognizer->SetRefereeState(RefereeState::FAIL);
recognizer->OnRejected(touchId_);
RemoveAndUnBlockGesture(prevState == RefereeState::PENDING, recognizer);
}
void GestureScope::RemoveAndUnBlockGesture(bool isPrevPending, const WeakPtr<GestureRecognizer>& weakRecognizer)
{
auto recognizer = weakRecognizer.Upgrade();
if (!recognizer) {
return;
}
if (recognizer->GetPriority() == GesturePriority::High) {
highRecognizers_.remove(recognizer);
if (highRecognizers_.empty()) {
UnBlockGesture(lowRecognizers_);
return;
}
if (isPrevPending) {
UnBlockGesture(highRecognizers_);
}
} else {
lowRecognizers_.remove(recognizer);
if (isPrevPending) {
UnBlockGesture(lowRecognizers_);
}
}
}
bool GestureScope::Existed(const RefPtr<GestureRecognizer>& recognizer)
{
if (!recognizer) {
LOGE("recognizer is null, AddGestureRecognizer failed.");
return false;
}
std::list<WeakPtr<GestureRecognizer>> members = GetMembersByRecognizer(recognizer);
if (members.empty()) {
return false;
}
auto result = std::find(members.cbegin(), members.cend(), recognizer);
return result != members.cend();
}
const std::list<WeakPtr<GestureRecognizer>>& GestureScope::GetMembersByRecognizer(
const RefPtr<GestureRecognizer>& recognizer)
{
switch (recognizer->GetPriority()) {
case GesturePriority::Low:
return lowRecognizers_;
case GesturePriority::High:
return highRecognizers_;
case GesturePriority::Parallel:
return parallelRecognizers_;
default:
return lowRecognizers_;
}
}
bool GestureScope::CheckNeedBlocked(const RefPtr<GestureRecognizer>& recognizer)
{
if (recognizer->GetPriority() == GesturePriority::Low && !highRecognizers_.empty()) {
LOGD("self is low priority, high recognizers are not processed");
return true;
}
std::list<WeakPtr<GestureRecognizer>> members = GetMembersByRecognizer(recognizer);
for (const auto& member : members) {
if (member == recognizer) {
return false;
}
if (member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING) {
return true;
}
}
return false;
}
void GestureScope::AcceptGesture(const RefPtr<GestureRecognizer>& recognizer)
{
if (recognizer->GetPriority() == GesturePriority::Low) {
for (const auto& rejectedItem : lowRecognizers_) {
if (rejectedItem == recognizer) {
continue;
}
auto strongItem = rejectedItem.Upgrade();
if (strongItem) {
strongItem->OnRejected(touchId_);
strongItem->SetRefereeState(RefereeState::FAIL);
}
}
} else {
for (const auto& rejectedItem : highRecognizers_) {
if (rejectedItem == recognizer) {
continue;
}
auto strongItem = rejectedItem.Upgrade();
if (strongItem) {
strongItem->OnRejected(touchId_);
strongItem->SetRefereeState(RefereeState::FAIL);
}
}
for (const auto& rejectedItem : lowRecognizers_) {
if (rejectedItem == recognizer) {
continue;
}
auto strongItem = rejectedItem.Upgrade();
if (strongItem) {
strongItem->OnRejected(touchId_);
strongItem->SetRefereeState(RefereeState::FAIL);
}
}
}
recognizer->SetRefereeState(RefereeState::SUCCEED);
recognizer->OnAccepted(touchId_);
if (recognizer->GetPriority() == GesturePriority::Low) {
lowRecognizers_.clear();
} else {
highRecognizers_.clear();
lowRecognizers_.clear();
}
}
void GestureScope::UnBlockGesture(std::list<WeakPtr<GestureRecognizer>>& members)
{
auto weakBlockedMember =
std::find_if(std::begin(members), std::end(members), [](const WeakPtr<GestureRecognizer>& member) {
return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::BLOCKED;
});
if (weakBlockedMember == members.end()) {
LOGD("no blocked gesture in recognizers");
return;
}
auto blockedMember = (*weakBlockedMember).Upgrade();
if (!blockedMember) {
LOGW("BlockedMember not exists.");
return;
}
if ((blockedMember)->GetDetectState() == DetectState::DETECTED) {
LOGD("unblock and accept this gesture");
AcceptGesture(blockedMember);
return;
}
LOGD("set the gesture %{public}s to be pending", AceType::TypeName((*blockedMember)));
(blockedMember)->SetRefereeState(RefereeState::PENDING);
(blockedMember)->OnPending(touchId_);
}
void GestureScope::ForceClose()
{
LOGD("force close gesture scope of id %{public}zu", touchId_);
for (const auto& weakRejectedItem : lowRecognizers_) {
auto rejectedItem = weakRejectedItem.Upgrade();
if (rejectedItem) {
rejectedItem->OnRejected(touchId_);
}
}
lowRecognizers_.clear();
for (const auto& weakRejectedItem : highRecognizers_) {
auto rejectedItem = weakRejectedItem.Upgrade();
if (rejectedItem) {
rejectedItem->OnRejected(touchId_);
}
}
highRecognizers_.clear();
for (const auto& weakRejectedItem : parallelRecognizers_) {
auto rejectedItem = weakRejectedItem.Upgrade();
if (rejectedItem) {
rejectedItem->OnRejected(touchId_);
}
}
parallelRecognizers_.clear();
}
bool GestureScope::IsPending() const
{
auto pendingMember = std::find_if(
std::begin(lowRecognizers_), std::end(lowRecognizers_), [](const WeakPtr<GestureRecognizer>& member) {
return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING;
});
if (pendingMember != lowRecognizers_.end()) {
return true;
}
pendingMember = std::find_if(
std::begin(highRecognizers_), std::end(highRecognizers_), [](const WeakPtr<GestureRecognizer>& member) {
return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING;
});
if (pendingMember != highRecognizers_.end()) {
return true;
}
pendingMember = std::find_if(
std::begin(parallelRecognizers_), std::end(parallelRecognizers_), [](const WeakPtr<GestureRecognizer>& member) {
return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING;
});
return pendingMember != parallelRecognizers_.end();
}
void GestureReferee::AddGestureRecognizer(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
if (!recognizer) {
LOGE("recognizer is null, AddGestureRecognizer failed.");
return;
}
LOGD("add gesture recognizer %{public}s into scope %{public}zu,", AceType::TypeName(recognizer), touchId);
const auto iter = gestureScopes_.find(touchId);
if (iter != gestureScopes_.end()) {
iter->second.AddMember(recognizer);
} else {
GestureScope gestureScope(touchId);
gestureScope.AddMember(recognizer);
gestureScopes_.try_emplace(touchId, std::move(gestureScope));
}
}
void GestureReferee::DelGestureRecognizer(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
if (!recognizer) {
LOGE("recognizer is null, DelGestureRecognizer failed.");
return;
}
LOGD("delete gesture recognizer %{public}s from scope %{public}zu ", AceType::TypeName(recognizer), touchId);
const auto iter = gestureScopes_.find(touchId);
if (iter == gestureScopes_.end()) {
return;
}
iter->second.DelMember(recognizer);
}
void GestureReferee::CleanGestureScope(size_t touchId)
{
const auto iter = gestureScopes_.find(touchId);
if (iter != gestureScopes_.end()) {
if (iter->second.IsPending()) {
LOGE("gesture scope of touch id %{public}zu is pending, do not clean this.", touchId);
return;
}
if (!iter->second.IsEmpty()) {
iter->second.ForceClose();
}
gestureScopes_.erase(iter);
}
}
void GestureReferee::Adjudicate(size_t touchId, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
{
if (!recognizer) {
LOGE("recognizer is null, Adjudicate failed.");
return;
}
const auto iter = gestureScopes_.find(touchId);
if (iter != gestureScopes_.end()) {
iter->second.HandleGestureDisposal(recognizer, disposal);
if (iter->second.IsEmpty()) {
LOGD("clean the gesture referee of %{public}zu", touchId);
gestureScopes_.erase(iter);
}
} else {
LOGE("fail to find the gesture scope for %{public}zu session id", touchId);
}
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_REFEREE_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_REFEREE_H
#include <list>
#include <unordered_map>
#include "base/memory/ace_type.h"
#include "base/utils/singleton.h"
namespace OHOS::Ace::NG {
class GestureRecognizer;
enum class GestureDisposal {
ACCEPT = 0,
REJECT,
PENDING,
};
class GestureScope {
public:
explicit GestureScope(size_t touchId) : touchId_(touchId) {}
~GestureScope() = default;
void AddMember(const RefPtr<GestureRecognizer>& recognizer);
void DelMember(const RefPtr<GestureRecognizer>& recognizer);
void ForceClose();
void HandleGestureDisposal(const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal);
bool IsEmpty() const
{
return highRecognizers_.empty() && lowRecognizers_.empty() && parallelRecognizers_.empty();
}
bool IsPending() const;
private:
bool Existed(const RefPtr<GestureRecognizer>& recognizer);
const std::list<WeakPtr<GestureRecognizer>>& GetMembersByRecognizer(const RefPtr<GestureRecognizer>& recognizer);
bool CheckNeedBlocked(const RefPtr<GestureRecognizer>& recognizer);
void AcceptGesture(const RefPtr<GestureRecognizer>& recognizer);
void UnBlockGesture(std::list<WeakPtr<GestureRecognizer>>& members);
void HandleParallelDisposal(const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal);
void HandleAcceptDisposal(const RefPtr<GestureRecognizer>& recognizer);
void HandlePendingDisposal(const RefPtr<GestureRecognizer>& recognizer);
void HandleRejectDisposal(const RefPtr<GestureRecognizer>& recognizer);
void RemoveAndUnBlockGesture(bool isPrevPending, const WeakPtr<GestureRecognizer>& recognizer);
size_t touchId_ = 0;
std::list<WeakPtr<GestureRecognizer>> highRecognizers_;
std::list<WeakPtr<GestureRecognizer>> lowRecognizers_;
std::list<WeakPtr<GestureRecognizer>> parallelRecognizers_;
};
class GestureReferee : public virtual AceType {
DECLARE_ACE_TYPE(GestureRefereeNG, AceType);
public:
GestureReferee() = default;
~GestureReferee() = default;
// Each gesture recognizer should add itself to the gesture scope at the beginning of the gesture sequence
// (touch down event) for gesture adjudicating.
void AddGestureRecognizer(size_t touchId, const RefPtr<GestureRecognizer>& recognizer);
// In multi finger recognizers, touch up one finger does not result to the whole gesture failed. Recognizer should
// remove the recognizer out of the referee.
void DelGestureRecognizer(size_t touchId, const RefPtr<GestureRecognizer>& recognizer);
// Try to clean gesture scope when receive cancel event.
void CleanGestureScope(size_t touchId);
// Called by the gesture recognizer when the gesture recognizer has completed the recognition of the gesture (accept
// or reject)
void Adjudicate(size_t touchId, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal);
private:
// Stores gesture recognizer collection according to Id.
std::unordered_map<size_t, GestureScope> gestureScopes_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_GESTURE_REFEREE_H

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/long_press_gesture.h"
#include "core/components_ng/gestures/recognizers/long_press_recognizer.h"
namespace OHOS::Ace::NG {
RefPtr<GestureRecognizer> LongPressGesture::CreateRecognizer()
{
LOGD("create long press gesture, fingers %{public}d, duration %{public}d, isRepeat %{public}d", fingers_, duration_,
repeat_);
auto longPressRecognizer = AceType::MakeRefPtr<LongPressRecognizer>(
duration_, fingers_, repeat_, isForDrag_, isDisableMouseLeft_);
longPressRecognizer->SetPriority(priority_);
longPressRecognizer->SetPriorityMask(gestureMask_);
if (onActionId_) {
longPressRecognizer->SetOnAction(*onActionId_);
}
if (onActionEndId_) {
longPressRecognizer->SetOnActionEnd(*onActionEndId_);
}
if (onActionCancelId_) {
longPressRecognizer->SetOnActionCancel(*onActionCancelId_);
}
return longPressRecognizer;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_LONG_PRESS_GESTURE_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_LONG_PRESS_GESTURE_H
#include <functional>
#include <string>
#include <vector>
#include "base/geometry/offset.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class ACE_EXPORT LongPressGesture : public Gesture {
DECLARE_ACE_TYPE(LongPressGesture, Gesture);
public:
LongPressGesture(
int32_t fingers, bool repeat, int32_t duration, bool isForDrag = false, bool isDisableMouseLeft = false)
: Gesture(fingers), repeat_(repeat), duration_(duration), isForDrag_(isForDrag),
isDisableMouseLeft_(isDisableMouseLeft)
{}
~LongPressGesture() override = default;
protected:
RefPtr<GestureRecognizer> CreateRecognizer() override;
private:
bool repeat_ = false;
int32_t duration_ = 500;
bool isForDrag_ = false;
bool isDisableMouseLeft_ = false;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_LONG_PRESS_GESTURE_H

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/pan_gesture.h"
#include "base/geometry/dimension.h"
#include "core/components_ng/gestures/recognizers/pan_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
RefPtr<GestureRecognizer> PanGesture::CreateRecognizer()
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(context, nullptr);
double distance = context->NormalizeToPx(Dimension(distance_, DimensionUnit::VP));
RefPtr<PanRecognizer> panRecognizer;
if (panGestureOption_) {
LOGD("AceType::MakeRefPtr<OHOS::Ace::PanRecognizer>(panGestureOption_)");
panRecognizer = AceType::MakeRefPtr<PanRecognizer>(panGestureOption_);
} else {
LOGD("AceType::MakeRefPtr<OHOS::Ace::PanRecognizer>(fingers_, direction_, distance)");
panRecognizer = AceType::MakeRefPtr<PanRecognizer>(fingers_, direction_, distance);
}
if (onActionStartId_) {
panRecognizer->SetOnActionStart(*onActionStartId_);
}
if (onActionUpdateId_) {
panRecognizer->SetOnActionUpdate(*onActionUpdateId_);
}
if (onActionEndId_) {
panRecognizer->SetOnActionEnd(*onActionEndId_);
}
if (onActionCancelId_) {
panRecognizer->SetOnActionCancel(*onActionCancelId_);
}
panRecognizer->SetPriority(priority_);
panRecognizer->SetPriorityMask(gestureMask_);
return panRecognizer;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_PAN_GESTURE_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_PAN_GESTURE_H
#include <functional>
#include <string>
#include <vector>
#include "base/geometry/offset.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class ACE_EXPORT PanGesture : public Gesture {
DECLARE_ACE_TYPE(PanGesture, Gesture);
public:
PanGesture(int32_t fingers, const PanDirection& direction, double distance)
{
fingers_ = fingers;
direction_ = direction;
distance_ = distance;
};
explicit PanGesture(RefPtr<PanGestureOption> panGestureOption)
{
panGestureOption_ = panGestureOption;
};
~PanGesture() override = default;
protected:
RefPtr<GestureRecognizer> CreateRecognizer() override;
private:
PanDirection direction_;
double distance_ = 0.0;
RefPtr<PanGestureOption> panGestureOption_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_PAN_GESTURE_H

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/pinch_gesture.h"
#include "base/geometry/dimension.h"
#include "base/utils/utils.h"
#include "core/components_ng/base/ui_node.h"
#include "core/components_ng/gestures/recognizers/pinch_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
RefPtr<GestureRecognizer> PinchGesture::CreateRecognizer()
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(context, nullptr);
double distance = context->NormalizeToPx(Dimension(distance_, DimensionUnit::VP));
auto pinchRecognizer = AceType::MakeRefPtr<PinchRecognizer>(fingers_, distance);
if (onActionStartId_) {
pinchRecognizer->SetOnActionStart(*onActionStartId_);
}
if (onActionUpdateId_) {
pinchRecognizer->SetOnActionUpdate(*onActionUpdateId_);
}
if (onActionEndId_) {
pinchRecognizer->SetOnActionEnd(*onActionEndId_);
}
if (onActionCancelId_) {
pinchRecognizer->SetOnActionCancel(*onActionCancelId_);
}
pinchRecognizer->SetPriority(priority_);
pinchRecognizer->SetPriorityMask(gestureMask_);
return pinchRecognizer;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_PINCH_GESTURE_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_PINCH_GESTURE_H
#include <functional>
#include <string>
#include <vector>
#include "base/geometry/offset.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class ACE_EXPORT PinchGesture : public Gesture {
DECLARE_ACE_TYPE(PinchGesture, Gesture);
public:
PinchGesture(int32_t fingers, double distance) : Gesture(fingers), distance_(distance) {}
~PinchGesture() override = default;
protected:
RefPtr<GestureRecognizer> CreateRecognizer() override;
private:
double distance_ = 0.0;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_PINCH_GESTURE_H

View File

@ -0,0 +1,328 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/click_recognizer.h"
#include "base/geometry/offset.h"
#include "base/log/log.h"
#include "base/ressched/ressched_report.h"
#include "base/utils/utils.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
namespace {
int32_t MULTI_FINGER_TIMEOUT = 300;
constexpr int32_t MULTI_FINGER_TIMEOUT_TOUCH = 300;
constexpr int32_t MULTI_FINGER_TIMEOUT_MOUSE = 300;
int32_t MULTI_TAP_TIMEOUT = 300;
constexpr int32_t MULTI_TAP_TIMEOUT_TOUCH = 300;
constexpr int32_t MULTI_TAP_TIMEOUT_MOUSE = 500;
int32_t MULTI_TAP_SLOP = 100;
constexpr int32_t MULTI_TAP_SLOP_TOUCH = 100;
constexpr int32_t MULTI_TAP_SLOP_MOUSE = 15;
#ifndef WEARABLE_PRODUCT
double MAX_THRESHOLD = 20.0;
constexpr double MAX_THRESHOLD_TOUCH = 20.0;
#else
constexpr double MAX_THRESHOLD = 12.0;
constexpr double MAX_THRESHOLD_TOUCH = 12.0;
#endif
constexpr int32_t MAX_THRESHOLD_MOUSE = 15;
constexpr int32_t MAX_TAP_FINGERS = 10;
} // namespace
void ClickRecognizer::InitGlobalValue(SourceType sourceType)
{
switch (sourceType) {
case SourceType::TOUCH:
MULTI_FINGER_TIMEOUT = MULTI_FINGER_TIMEOUT_TOUCH;
MULTI_TAP_TIMEOUT = MULTI_TAP_TIMEOUT_TOUCH;
MULTI_TAP_SLOP = MULTI_TAP_SLOP_TOUCH;
MAX_THRESHOLD = MAX_THRESHOLD_TOUCH;
break;
case SourceType::MOUSE:
case SourceType::TOUCH_PAD:
MULTI_FINGER_TIMEOUT = MULTI_FINGER_TIMEOUT_MOUSE;
MULTI_TAP_TIMEOUT = MULTI_TAP_TIMEOUT_MOUSE;
MULTI_TAP_SLOP = MULTI_TAP_SLOP_MOUSE;
MAX_THRESHOLD = MAX_THRESHOLD_MOUSE;
break;
default:
LOGI("Unrecognized input source type: %{public}d", sourceType);
}
}
void ClickRecognizer::OnAccepted()
{
LOGI("Click gesture has been accepted!");
ResSchedReport::GetInstance().ResSchedDataReport("click");
if (onClick_) {
TouchEvent touchPoint = {};
if (!touchPoints_.empty()) {
touchPoint = touchPoints_.begin()->second;
}
ClickInfo info(touchPoint.id);
info.SetTimeStamp(touchPoint.time);
info.SetGlobalLocation(touchPoint.GetOffset()).SetLocalLocation(touchPoint.GetOffset() - coordinateOffset_);
info.SetSourceDevice(deviceType_);
info.SetDeviceId(deviceId_);
onClick_(info);
}
if (remoteMessage_) {
TouchEvent touchPoint = {};
if (!touchPoints_.empty()) {
touchPoint = touchPoints_.begin()->second;
}
ClickInfo info(touchPoint.id);
info.SetTimeStamp(touchPoint.time);
info.SetGlobalLocation(touchPoint.GetOffset()).SetLocalLocation(touchPoint.GetOffset() - coordinateOffset_);
remoteMessage_(info);
}
SetFingerList(touchPoints_, coordinateOffset_, fingerList_);
SendCallbackMsg(onAction_);
Reset();
}
void ClickRecognizer::OnRejected()
{
LOGD("click gesture has been rejected!");
Reset();
}
void ClickRecognizer::HandleTouchDownEvent(const TouchEvent& event)
{
InitGlobalValue(event.sourceType);
LOGD("click recognizer receives touch down event, begin to detect click event");
if (fingers_ > MAX_TAP_FINGERS) {
return;
}
// If number of fingers which put on the screen more than fingers_,
// the gesture will be rejected when one of them touch up.
if (pointsCount_ == fingers_) {
pointsCount_++;
LOGE("number of fingers put on the screen more than %{public}d, current fingers is %{public}d",
fingers_, pointsCount_);
return;
}
if (state_ == DetectState::READY) {
if (tappedCount_ > 0 && pointsCount_ == 0) {
tapDeadlineTimer_.Cancel();
}
AddToReferee(event.id, AceType::Claim(this));
touchPoints_[event.id] = event;
pointsCount_++;
if (fingers_ > 1 && pointsCount_ == 1) {
// waiting for multi-finger press
DeadlineTimer(fingerDeadlineTimer_, MULTI_FINGER_TIMEOUT);
}
} else {
LOGE("the state of click recognizer is not ready to receive touch down event, "
"state is %{public}d, id is %{public}d",
state_, event.id);
}
if (pointsCount_ == fingers_) {
// Turn off the multi-finger press deadline timer
fingerDeadlineTimer_.Cancel();
state_ = DetectState::DETECTING;
equalsToFingers_ = true;
if (ExceedSlop()) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
}
}
void ClickRecognizer::HandleTouchUpEvent(const TouchEvent& event)
{
InitGlobalValue(event.sourceType);
LOGD("click recognizer receives touch up event");
if (pointsCount_ > fingers_) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
if (state_ == DetectState::READY) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (state_ == DetectState::DETECTED) {
return;
}
touchPoints_[event.id] = event;
pointsCount_--;
// Check whether multi-finger taps are completed in count_ times
if (pointsCount_ == 0 && equalsToFingers_) {
// Turn off the multi-finger lift deadline timer
fingerDeadlineTimer_.Cancel();
focusPoint_ = ComputeFocusPoint();
tappedCount_++;
if (tappedCount_ == count_) {
LOGI("this gesture is click, try to accept it");
time_ = event.time;
state_ = DetectState::DETECTED;
if (useCatchMode_) {
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
} else {
OnAccepted();
}
return;
}
equalsToFingers_ = false;
state_ = DetectState::READY;
// waiting for multi-finger lift
DeadlineTimer(tapDeadlineTimer_, MULTI_TAP_TIMEOUT);
}
Adjudicate(AceType::Claim(this), GestureDisposal::PENDING);
if (pointsCount_ < fingers_ && equalsToFingers_) {
DeadlineTimer(fingerDeadlineTimer_, MULTI_FINGER_TIMEOUT);
}
}
void ClickRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
{
InitGlobalValue(event.sourceType);
LOGD("click recognizer receives touch move event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
Offset offset = event.GetOffset() - touchPoints_[event.id].GetOffset();
if (offset.GetDistance() > MAX_THRESHOLD) {
LOGD("this gesture is not click, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
}
void ClickRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
{
InitGlobalValue(event.sourceType);
LOGD("click recognizer receives touch cancel event");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
void ClickRecognizer::HandleOverdueDeadline()
{
if (pointsCount_ < fingers_ || tappedCount_ < count_) {
LOGD("the state is not detecting for accept multi-finger tap gesture");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
}
void ClickRecognizer::DeadlineTimer(CancelableCallback<void()>& deadlineTimer, int32_t time)
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto&& callback = [weakPtr = AceType::WeakClaim(this)]() {
auto refPtr = weakPtr.Upgrade();
if (refPtr) {
refPtr->HandleOverdueDeadline();
} else {
LOGE("fail to handle overdue deadline due to context is nullptr");
}
};
deadlineTimer.Reset(callback);
auto taskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
taskExecutor.PostDelayedTask(deadlineTimer, time);
}
void ClickRecognizer::Reset()
{
touchPoints_.clear();
fingerList_.clear();
pointsCount_ = 0;
equalsToFingers_ = false;
tappedCount_ = 0;
state_ = DetectState::READY;
}
Offset ClickRecognizer::ComputeFocusPoint()
{
Offset sumOfPoints;
for (auto& element : touchPoints_) {
sumOfPoints = sumOfPoints + element.second.GetOffset();
}
Offset focusPoint = sumOfPoints / touchPoints_.size();
return focusPoint;
}
bool ClickRecognizer::ExceedSlop()
{
if (tappedCount_ > 0 && tappedCount_ < count_) {
Offset currentFocusPoint = ComputeFocusPoint();
Offset slop = currentFocusPoint - focusPoint_;
if (GreatOrEqual(slop.GetDistance(), MULTI_TAP_SLOP)) {
return true;
}
}
return false;
}
void ClickRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& onAction)
{
if (onAction && *onAction) {
GestureEvent info;
info.SetTimeStamp(time_);
info.SetFingerList(fingerList_);
TouchEvent touchPoint = {};
if (!touchPoints_.empty()) {
touchPoint = touchPoints_.begin()->second;
}
info.SetGlobalLocation(touchPoint.GetOffset()).SetLocalLocation(touchPoint.GetOffset() - coordinateOffset_);
info.SetSourceDevice(deviceType_);
info.SetDeviceId(deviceId_);
(*onAction)(info);
}
}
bool ClickRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<ClickRecognizer> curr = AceType::DynamicCast<ClickRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (curr->count_ != count_ || curr->fingers_ != fingers_ || curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
onAction_ = std::move(curr->onAction_);
return true;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_CLICK_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_CLICK_RECOGNIZER_H
#include <functional>
#include "base/thread/cancelable_callback.h"
#include "core/components_ng/gestures/gesture_info.h"
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
#include "core/focus/focus_node.h"
namespace OHOS::Ace::NG {
class ClickRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(ClickRecognizer, MultiFingersRecognizer);
public:
ClickRecognizer() = default;
ClickRecognizer(int32_t fingers, int32_t count) : count_(count)
{
fingers_ = fingers;
}
~ClickRecognizer() override = default;
void OnAccepted() override;
void OnRejected() override;
void SetOnClick(const ClickCallback& onClick)
{
onClick_ = onClick;
}
void SetRemoteMessage(const ClickCallback& remoteMessage)
{
remoteMessage_ = remoteMessage;
}
void SetUseCatchMode(bool useCatchMode)
{
useCatchMode_ = useCatchMode;
}
private:
void HandleTouchDownEvent(const TouchEvent& event) override;
void HandleTouchUpEvent(const TouchEvent& event) override;
void HandleTouchMoveEvent(const TouchEvent& event) override;
void HandleTouchCancelEvent(const TouchEvent& event) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
void HandleOverdueDeadline();
void DeadlineTimer(CancelableCallback<void()>& deadlineTimer, int32_t time);
Offset ComputeFocusPoint();
void Reset();
void SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback);
bool ExceedSlop();
void InitGlobalValue(SourceType deviceId);
int32_t count_ = 1;
// number of fingers which put on the screen
int32_t pointsCount_ = 0;
int32_t tappedCount_ = 0;
// Check whether the pointsCount_ has reached the configured value
bool equalsToFingers_ = false;
// the time when gesture recognition is successful
TimeStamp time_;
Offset focusPoint_;
ClickCallback onClick_;
ClickCallback remoteMessage_;
bool useCatchMode_ = true;
CancelableCallback<void()> fingerDeadlineTimer_;
CancelableCallback<void()> tapDeadlineTimer_;
std::map<int32_t, TouchEvent> touchPoints_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_CLICK_RECOGNIZER_H

View File

@ -0,0 +1,268 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/exclusive_recognizer.h"
#include <vector>
#include "base/geometry/offset.h"
#include "base/log/log.h"
#include "base/memory/ace_type.h"
#include "core/components_ng/gestures/gesture_referee.h"
#include "core/components_ng/gestures/recognizers/click_recognizer.h"
namespace OHOS::Ace::NG {
void ExclusiveRecognizer::OnAccepted(size_t touchId)
{
LOGD("the exclusive gesture recognizer has been accepted, touch id %{public}zu", touchId);
if (refereePointers_.find(touchId) == refereePointers_.end()) {
return;
}
refereePointers_.erase(touchId);
if (!activeRecognizer_) {
return;
}
activeRecognizer_->SetCoordinateOffset(coordinateOffset_);
activeRecognizer_->OnAccepted(touchId);
activeRecognizer_->SetRefereeState(RefereeState::SUCCEED);
for (auto& recognizer : recognizers_) {
if (recognizer != activeRecognizer_) {
LOGD("the sub gesture %{public}s is rejected because one is accepted", AceType::TypeName(recognizer));
recognizer->OnRejected(touchId);
recognizer->SetRefereeState(RefereeState::FAIL);
}
}
if (AceType::InstanceOf<ClickRecognizer>(activeRecognizer_)) {
Reset();
}
}
void ExclusiveRecognizer::OnRejected(size_t touchId)
{
if (refereePointers_.find(touchId) == refereePointers_.end()) {
return;
}
refereePointers_.erase(touchId);
LOGD("the exclusive gesture recognizer has been rejected! the touch id is %{public}zu", touchId);
for (auto& recognizer : recognizers_) {
if (recognizer->GetRefereeState() == RefereeState::FAIL) {
continue;
}
recognizer->OnRejected(touchId);
if (recognizer->GetDetectState() == DetectState::READY) {
recognizer->SetRefereeState(RefereeState::FAIL);
}
}
}
void ExclusiveRecognizer::OnPending(size_t touchId)
{
if (refereePointers_.find(touchId) == refereePointers_.end()) {
return;
}
LOGD("the exclusive gesture recognizer is pending! the touch id is %{public}zu", touchId);
for (auto& recognizer : recognizers_) {
if (recognizer->GetRefereeState() == RefereeState::PENDING) {
recognizer->OnPending(touchId);
}
}
}
bool ExclusiveRecognizer::HandleEvent(const TouchEvent& point)
{
switch (point.type) {
case TouchType::MOVE:
case TouchType::DOWN:
case TouchType::UP:
case TouchType::CANCEL:
if (activeRecognizer_) {
activeRecognizer_->HandleEvent(point);
} else {
for (auto& recognizer : recognizers_) {
recognizer->HandleEvent(point);
}
}
break;
default:
LOGW("exclusive recognizer received unknown touch type");
break;
}
if (activeRecognizer_ && activeRecognizer_->GetDetectState() != DetectState::DETECTED) {
LOGD("sub detected gesture has finished, change the exclusive recognizer to be ready");
Reset();
}
return true;
}
void ExclusiveRecognizer::OnFlushTouchEventsBegin()
{
for (auto& recognizer : recognizers_) {
recognizer->OnFlushTouchEventsBegin();
}
}
void ExclusiveRecognizer::OnFlushTouchEventsEnd()
{
for (auto& recognizer : recognizers_) {
recognizer->OnFlushTouchEventsEnd();
}
}
void ExclusiveRecognizer::BatchAdjudicate(
const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
{
// any sub recognizer accept itself will drive to detected state
if (state_ == DetectState::DETECTED) {
LOGD("exclusive gesture recognizer is in detected state, do not process disposal");
return;
}
if (disposal == GestureDisposal::ACCEPT) {
AcceptSubGesture(recognizer);
return;
}
if (disposal == GestureDisposal::PENDING) {
if (CheckNeedBlocked(recognizer)) {
recognizer->SetRefereeState(RefereeState::BLOCKED);
} else {
recognizer->SetRefereeState(RefereeState::PENDING);
MultiFingersRecognizer::Adjudicate(AceType::Claim(this), GestureDisposal::PENDING);
}
return;
}
// process reject disposal
LOGD("sub gesture recognizer %{public}s ask for reject", AceType::TypeName(recognizer));
RefereeState prevState = recognizer->GetRefereeState();
for (auto touchId : touchIds) {
recognizer->OnRejected(touchId);
}
recognizer->SetRefereeState(RefereeState::FAIL);
if (prevState == RefereeState::PENDING) {
for (auto& tmpRecognizer : recognizers_) {
if (tmpRecognizer->GetRefereeState() == RefereeState::BLOCKED &&
tmpRecognizer->GetDetectState() == DetectState::DETECTED) {
activeRecognizer_ = tmpRecognizer;
state_ = DetectState::DETECTED;
MultiFingersRecognizer::Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
break;
}
}
}
if (CheckAllFailed()) {
LOGD("all gesture recognizers are rejected, adjudicate reject");
MultiFingersRecognizer::Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
Reset();
}
}
void ExclusiveRecognizer::AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
recognizer->SetRefereeState(RefereeState::DETECTING);
if (state_ == DetectState::READY) {
state_ = DetectState::DETECTING;
}
if (state_ == DetectState::DETECTING) {
MultiFingersRecognizer::AddToReferee(touchId, AceType::Claim(this));
}
}
bool ExclusiveRecognizer::CheckNeedBlocked(const RefPtr<GestureRecognizer>& recognizer)
{
auto pendingMember = std::find_if(
std::begin(recognizers_), std::end(recognizers_), [recognizer](const RefPtr<GestureRecognizer>& member) {
return (member != recognizer) && (member->GetRefereeState() == RefereeState::PENDING);
});
if (pendingMember != recognizers_.end()) {
LOGD("exclusive gesture recognizer detected pending gesture in members");
return true;
}
return false;
}
void ExclusiveRecognizer::AcceptSubGesture(const RefPtr<GestureRecognizer>& recognizer)
{
LOGD("sub gesture recognizer %{public}s ask for accept", AceType::TypeName(recognizer));
if (CheckNeedBlocked(recognizer)) {
recognizer->SetRefereeState(RefereeState::BLOCKED);
return;
}
activeRecognizer_ = recognizer;
state_ = DetectState::DETECTED;
MultiFingersRecognizer::Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
}
bool ExclusiveRecognizer::CheckAllFailed()
{
auto notFailMember = std::find_if(std::begin(recognizers_), std::end(recognizers_),
[](const RefPtr<GestureRecognizer>& member) { return member->GetRefereeState() != RefereeState::FAIL; });
return notFailMember == recognizers_.end();
}
void ExclusiveRecognizer::Reset()
{
state_ = DetectState::READY;
activeRecognizer_ = nullptr;
for (auto& recognizer : recognizers_) {
recognizer->SetRefereeState(RefereeState::DETECTING);
}
}
bool ExclusiveRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<ExclusiveRecognizer> curr = AceType::DynamicCast<ExclusiveRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (recognizers_.size() != curr->recognizers_.size() || curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
auto currIter = curr->recognizers_.begin();
for (auto iter = recognizers_.begin(); iter != recognizers_.end(); iter++, currIter++) {
if (!(*iter)->ReconcileFrom(*currIter)) {
Reset();
return false;
}
}
return true;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_EXCLUSIVE_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_EXCLUSIVE_RECOGNIZER_H
#include <functional>
#include <set>
#include "core/components_ng/gestures/gesture_info.h"
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
namespace OHOS::Ace::NG {
// ExclusiveRecognizer identifies gesture exclusive.
class ACE_EXPORT ExclusiveRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(ExclusiveRecognizer, MultiFingersRecognizer);
public:
explicit ExclusiveRecognizer(const std::vector<RefPtr<GestureRecognizer>>& recognizers)
{
for (auto& recognizer : recognizers) {
recognizer->SetGestureGroup(AceType::WeakClaim(this));
recognizers_.emplace_back(recognizer);
}
}
explicit ExclusiveRecognizer(std::list<RefPtr<GestureRecognizer>>&& recognizers)
{
recognizers_.swap(recognizers);
for (auto& recognizer : recognizers_) {
recognizer->SetGestureGroup(AceType::WeakClaim(this));
}
}
~ExclusiveRecognizer() override = default;
void OnAccepted(size_t touchId) override;
void OnRejected(size_t touchId) override;
void OnPending(size_t touchId) override;
bool HandleEvent(const TouchEvent& point) override;
void OnFlushTouchEventsBegin() override;
void OnFlushTouchEventsEnd() override;
private:
void HandleTouchDownEvent(const TouchEvent& event) override {};
void HandleTouchUpEvent(const TouchEvent& event) override {};
void HandleTouchMoveEvent(const TouchEvent& event) override {};
void HandleTouchCancelEvent(const TouchEvent& event) override {};
void BatchAdjudicate(const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer,
GestureDisposal disposal) override;
void AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
bool CheckNeedBlocked(const RefPtr<GestureRecognizer>& recognizer);
void AcceptSubGesture(const RefPtr<GestureRecognizer>& recognizer);
bool CheckAllFailed();
void Reset();
std::list<RefPtr<GestureRecognizer>> recognizers_;
RefPtr<GestureRecognizer> activeRecognizer_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_EXCLUSIVE_RECOGNIZER_H

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/gesture_recognizer.h"
#include "base/log/log.h"
#include "core/common/container.h"
#include "core/event/axis_event.h"
namespace OHOS::Ace::NG {
namespace {
RefPtr<GestureReferee> GetCurrentGestureReferee()
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(context, nullptr);
auto eventManager = context->GetEventManager();
if (!eventManager) {
return nullptr;
}
return eventManager->GetGestureRefereeNG();
}
}
bool GestureRecognizer::HandleEvent(const TouchEvent& point)
{
switch (point.type) {
case TouchType::MOVE:
HandleTouchMoveEvent(point);
break;
case TouchType::DOWN:
deviceId_ = point.deviceId;
deviceType_ = point.sourceType;
HandleTouchDownEvent(point);
break;
case TouchType::UP:
HandleTouchUpEvent(point);
break;
case TouchType::CANCEL:
HandleTouchCancelEvent(point);
break;
default:
LOGW("unknown touch type");
break;
}
return true;
}
bool GestureRecognizer::HandleEvent(const AxisEvent& event)
{
switch (event.action) {
case AxisAction::BEGIN:
deviceId_ = event.deviceId;
deviceType_ = event.sourceType;
HandleTouchDownEvent(event);
case AxisAction::UPDATE:
HandleTouchMoveEvent(event);
break;
case AxisAction::END:
HandleTouchUpEvent(event);
break;
default:
HandleTouchCancelEvent(event);
LOGW("unknown touch type");
break;
}
return true;
}
void GestureRecognizer::AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
auto gestureGroup = gestureGroup_.Upgrade();
if (gestureGroup) {
gestureGroup->AddToReferee(touchId, recognizer);
return;
}
auto referee = GetCurrentGestureReferee();
if (referee) {
referee->AddGestureRecognizer(touchId, recognizer);
}
}
void GestureRecognizer::DelFromReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
auto gestureGroup = gestureGroup_.Upgrade();
if (gestureGroup) {
gestureGroup->DelFromReferee(touchId, recognizer);
return;
}
auto referee = GetCurrentGestureReferee();
if (referee) {
referee->DelGestureRecognizer(touchId, recognizer);
}
}
void GestureRecognizer::BatchAdjudicate(
const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
{
auto gestureGroup = gestureGroup_.Upgrade();
if (gestureGroup) {
gestureGroup->BatchAdjudicate(touchIds, recognizer, disposal);
return;
}
std::set<size_t> copyIds = touchIds;
auto referee = GetCurrentGestureReferee();
if (!referee) {
LOGW("No GestureReferee in GestureRecoginer.");
return;
}
for (auto pointerId : copyIds) {
LOGD("Adjudicate gesture recognizer, touch id %{public}zu, disposal %{public}d", pointerId, disposal);
referee->Adjudicate(pointerId, recognizer, disposal);
}
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,185 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_GESTURE_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_GESTURE_RECOGNIZER_H
#include <map>
#include <memory>
#include <set>
#include "core/components_ng/gestures/gesture_info.h"
#include "core/components_ng/gestures/gesture_referee.h"
#include "core/event/axis_event.h"
#include "core/event/touch_event.h"
namespace OHOS::Ace::NG {
enum class DetectState { READY, DETECTING, DETECTED };
enum class RefereeState { DETECTING, PENDING, BLOCKED, SUCCEED, FAIL };
class ACE_EXPORT GestureRecognizer : public TouchEventTarget {
DECLARE_ACE_TYPE(GestureRecognizer, TouchEventTarget)
public:
// Called when request of handling gesture sequence is accepted by gesture referee.
virtual void OnAccepted(size_t touchId) = 0;
// Called when request of handling gesture sequence is rejected by gesture referee.
virtual void OnRejected(size_t touchId) = 0;
// Called when request of handling gesture sequence is rejected by gesture referee.
virtual void OnPending(size_t touchId) {}
// Reconiciles the state from the given recognizer into this. The
// implementation must check that the given recognizer type matches the
// current one. The return value should be false if the reconciliation fails
// and true if it succeeds
virtual bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
return true;
}
bool DispatchEvent(const TouchEvent& point) override
{
return true;
}
bool HandleEvent(const TouchEvent& point) override;
bool HandleEvent(const AxisEvent& event) override;
GesturePriority GetPriority() const
{
return priority_;
}
void SetPriority(GesturePriority priority)
{
priority_ = priority;
}
GestureMask GetPriorityMask() const
{
return priorityMask_;
}
void SetPriorityMask(GestureMask priorityMask)
{
priorityMask_ = priorityMask;
}
RefereeState GetRefereeState() const
{
return refereeState_;
}
void SetRefereeState(RefereeState refereeState)
{
refereeState_ = refereeState;
}
DetectState GetDetectState() const
{
return state_;
}
void SetGestureGroup(const WeakPtr<GestureRecognizer>& gestureGroup)
{
gestureGroup_ = gestureGroup;
}
void SetOnAction(const GestureEventFunc& onAction)
{
onAction_ = std::make_unique<GestureEventFunc>(onAction);
}
void SetOnActionStart(const GestureEventFunc& onActionStart)
{
onActionStart_ = std::make_unique<GestureEventFunc>(onActionStart);
}
void SetOnActionUpdate(const GestureEventFunc& onActionUpdate)
{
onActionUpdate_ = std::make_unique<GestureEventFunc>(onActionUpdate);
}
void SetOnActionEnd(const GestureEventFunc& onActionEnd)
{
onActionEnd_ = std::make_unique<GestureEventFunc>(onActionEnd);
}
void SetOnActionCancel(const GestureEventNoParameter& onActionCancel)
{
onActionCancel_ = std::make_unique<GestureEventNoParameter>(onActionCancel);
}
inline void SendCancelMsg()
{
if (onActionCancel_ && *onActionCancel_) {
(*onActionCancel_)();
}
}
void SetIsExternalGesture(bool isExternalGesture)
{
isExternalGesture_ = isExternalGesture;
}
bool GetIsExternalGesture() const
{
return isExternalGesture_;
}
protected:
virtual void HandleTouchDownEvent(const TouchEvent& event) = 0;
virtual void HandleTouchUpEvent(const TouchEvent& event) = 0;
virtual void HandleTouchMoveEvent(const TouchEvent& event) = 0;
virtual void HandleTouchCancelEvent(const TouchEvent& event) = 0;
virtual void HandleTouchDownEvent(const AxisEvent& event) {}
virtual void HandleTouchUpEvent(const AxisEvent& event) {}
virtual void HandleTouchMoveEvent(const AxisEvent& event) {}
virtual void HandleTouchCancelEvent(const AxisEvent& event) {}
virtual void AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer);
virtual void DelFromReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer);
virtual void BatchAdjudicate(
const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal);
DetectState state_ { DetectState::READY };
RefereeState refereeState_ { RefereeState::DETECTING };
GesturePriority priority_ = GesturePriority::Low;
GestureMask priorityMask_ = GestureMask::Normal;
int32_t fingers_ = 1;
std::list<FingerInfo> fingerList_;
bool isExternalGesture_ = false;
std::unique_ptr<GestureEventFunc> onAction_;
std::unique_ptr<GestureEventFunc> onActionStart_;
std::unique_ptr<GestureEventFunc> onActionUpdate_;
std::unique_ptr<GestureEventFunc> onActionEnd_;
std::unique_ptr<GestureEventNoParameter> onActionCancel_;
int64_t deviceId_ = 0;
SourceType deviceType_ = SourceType::NONE;
private:
WeakPtr<GestureRecognizer> gestureGroup_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_GESTURE_RECOGNIZER_H

View File

@ -0,0 +1,288 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/long_press_recognizer.h"
#include "base/utils/utils.h"
#include "core/components_ng/gestures/gesture_referee.h"
#include "core/event/ace_events.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
namespace {
constexpr double MAX_THRESHOLD = 15.0;
constexpr int32_t MAX_FINGERS = 10;
} // namespace
void LongPressRecognizer::OnAccepted()
{
LOGI("long press gesture has been accepted!");
if (onLongPress_ && !touchMap_.empty()) {
TouchEvent trackPoint = touchMap_.begin()->second;
LongPressInfo info(trackPoint.id);
info.SetTimeStamp(time_);
info.SetScreenLocation(trackPoint.GetScreenOffset());
info.SetGlobalLocation(trackPoint.GetOffset()).SetLocalLocation(trackPoint.GetOffset() - coordinateOffset_);
info.SetTarget(GetEventTarget().value_or(EventTarget()));
onLongPress_(info);
}
SetFingerList(touchMap_, coordinateOffset_, fingerList_);
SendCallbackMsg(onActionUpdate_, false);
SendCallbackMsg(onAction_, false);
if (repeat_) {
StartRepeatTimer();
}
if (pendingEnd_) {
SendCallbackMsg(onActionEnd_, false);
Reset();
} else if (pendingCancel_) {
SendCancelMsg();
Reset();
}
}
void LongPressRecognizer::OnRejected()
{
LOGI("long press gesture has been rejected!");
Reset();
}
void LongPressRecognizer::HandleTouchDownEvent(const TouchEvent& event)
{
if (isDisableMouseLeft_ && event.sourceType == SourceType::MOUSE) {
LOGI("mouse left button is disabled for long press recognizer.");
return;
}
if (fingers_ > MAX_FINGERS) {
return;
}
LOGD("long press recognizer receives touch down event, begin to detect long press event");
int32_t curDuration = duration_;
if (isForDrag_ && event.sourceType == SourceType::MOUSE) {
curDuration = 0;
}
if ((touchRestrict_.forbiddenType & TouchRestrict::LONG_PRESS) == TouchRestrict::LONG_PRESS) {
LOGI("the long press is forbidden");
return;
}
globalPoint_ = Point(event.x, event.y);
if (state_ == DetectState::READY) {
touchMap_[event.id] = event;
pointsCount_++;
AddToReferee(event.id, AceType::Claim(this));
if (pointsCount_ == fingers_) {
state_ = DetectState::DETECTING;
if (useCatchMode_) {
DeadlineTimer(curDuration, false);
} else {
DeadlineTimer(curDuration, true);
}
}
} else {
LOGW("the state is not ready for detecting long press gesture, state id %{public}d, id is %{public}d",
state_, event.id);
}
}
void LongPressRecognizer::HandleTouchUpEvent(const TouchEvent& event)
{
LOGD("long press recognizer receives touch up event");
auto it = touchMap_.find(event.id);
if (it == touchMap_.end()) {
return;
}
if (state_ != DetectState::DETECTED) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (refereeState_ == RefereeState::SUCCEED) {
SendCallbackMsg(onActionUpdate_, false);
SendCallbackMsg(onActionEnd_, false);
Reset();
} else {
pendingEnd_ = true;
}
}
void LongPressRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
{
LOGD("long press recognizer receives touch move event");
auto it = touchMap_.find(event.id);
if (it == touchMap_.end()) {
return;
}
Offset offset = event.GetOffset() - touchMap_[event.id].GetOffset();
if (offset.GetDistance() > MAX_THRESHOLD) {
if (state_ == DetectState::DETECTED && refereeState_ == RefereeState::SUCCEED) {
SendCallbackMsg(onActionEnd_, false);
Reset();
return;
}
LOGD("this gesture is not long press, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
time_ = event.time;
}
void LongPressRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
{
LOGD("long press recognizer receives touch cancel event");
if (state_ == DetectState::READY || state_ == DetectState::DETECTING) {
LOGD("cancel long press gesture detect, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
SendCancelMsg();
return;
}
if (refereeState_ == RefereeState::SUCCEED) {
SendCancelMsg();
Reset();
} else {
pendingCancel_ = true;
}
}
void LongPressRecognizer::HandleOverdueDeadline()
{
if (state_ == DetectState::DETECTING) {
LOGI("this gesture is long press, try to accept it");
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
SendCallbackMsg(onActionUpdate_, false);
} else {
LOGW("the state is not detecting for accept long press gesture");
}
}
void LongPressRecognizer::DeadlineTimer(int32_t time, bool isAccept)
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto&& callback = [weakPtr = AceType::WeakClaim(this), isAccept]() {
auto refPtr = weakPtr.Upgrade();
if (refPtr) {
if (!isAccept) {
refPtr->HandleOverdueDeadline();
} else {
refPtr->OnAccepted();
}
} else {
LOGI("fail to handle overdue deadline due to context is nullptr");
}
};
deadlineTimer_.Reset(callback);
auto taskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
taskExecutor.PostDelayedTask(deadlineTimer_, time);
}
void LongPressRecognizer::DoRepeat()
{
SendCallbackMsg(onAction_, true);
StartRepeatTimer();
}
void LongPressRecognizer::StartRepeatTimer()
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto&& callback = [weakPtr = AceType::WeakClaim(this)]() {
auto refPtr = weakPtr.Upgrade();
if (refPtr) {
refPtr->DoRepeat();
} else {
LOGW("fail to handle overdue deadline due to context is nullptr");
}
};
timer_.Reset(callback);
auto taskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
taskExecutor.PostDelayedTask(timer_, duration_);
}
double LongPressRecognizer::ConvertPxToVp(double offset) const
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(context, offset);
double vpOffset = context->ConvertPxToVp(Dimension(offset, DimensionUnit::PX));
return vpOffset;
}
void LongPressRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback, bool isRepeat)
{
if (callback && *callback) {
GestureEvent info;
info.SetTimeStamp(time_);
info.SetRepeat(isRepeat);
info.SetFingerList(fingerList_);
TouchEvent trackPoint = {};
if (!touchMap_.empty()) {
trackPoint = touchMap_.begin()->second;
}
info.SetSourceDevice(deviceType_);
info.SetDeviceId(deviceId_);
info.SetGlobalPoint(globalPoint_);
info.SetScreenLocation(trackPoint.GetScreenOffset());
info.SetGlobalLocation(trackPoint.GetOffset()).SetLocalLocation(trackPoint.GetOffset() - coordinateOffset_);
info.SetTarget(GetEventTarget().value_or(EventTarget()));
(*callback)(info);
}
}
void LongPressRecognizer::Reset()
{
touchMap_.clear();
fingerList_.clear();
pointsCount_ = 0;
timer_.Cancel();
deadlineTimer_.Cancel();
state_ = DetectState::READY;
pendingEnd_ = false;
pendingCancel_ = false;
}
bool LongPressRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<LongPressRecognizer> curr = AceType::DynamicCast<LongPressRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (curr->duration_ != duration_ || curr->fingers_ != fingers_ || curr->repeat_ != repeat_ ||
curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
onAction_ = std::move(curr->onAction_);
onActionEnd_ = std::move(curr->onActionEnd_);
onActionCancel_ = std::move(curr->onActionCancel_);
return true;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_LONG_PRESS_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_LONG_PRESS_RECOGNIZER_H
#include "base/thread/cancelable_callback.h"
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
namespace OHOS::Ace::NG {
class LongPressInfo : public BaseEventInfo, public TouchLocationInfo {
DECLARE_RELATIONSHIP_OF_CLASSES(LongPressInfo, BaseEventInfo, TouchLocationInfo);
public:
explicit LongPressInfo(int32_t fingerId) : BaseEventInfo("onLongPress"), TouchLocationInfo(fingerId) {}
~LongPressInfo() override = default;
};
using OnLongPress = std::function<void(const LongPressInfo&)>;
using LongPressCallback = std::function<void(const GestureEvent&)>;
using LongPressNoParamCallback = std::function<void()>;
class LongPressRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(LongPressRecognizer, MultiFingersRecognizer);
public:
explicit LongPressRecognizer() {}
LongPressRecognizer(int32_t duration, int32_t fingers, bool repeat,
bool isForDrag = false, bool isDisableMouseLeft = false)
: duration_(duration), repeat_(repeat), isForDrag_(isForDrag),
isDisableMouseLeft_(isDisableMouseLeft)
{
fingers_ = fingers;
}
~LongPressRecognizer() override = default;
void OnAccepted() override;
void OnRejected() override;
void SetOnLongPress(const OnLongPress& onLongPress)
{
onLongPress_ = onLongPress;
}
void SetUseCatchMode(bool useCatchMode)
{
useCatchMode_ = useCatchMode;
}
private:
void HandleTouchDownEvent(const TouchEvent& event) override;
void HandleTouchUpEvent(const TouchEvent& event) override;
void HandleTouchMoveEvent(const TouchEvent& event) override;
void HandleTouchCancelEvent(const TouchEvent& event) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
void HandleOverdueDeadline();
void DeadlineTimer(int32_t time, bool isAccept);
void DoRepeat();
void StartRepeatTimer();
void SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback, bool isRepeat);
void Reset();
double ConvertPxToVp(double offset) const;
OnLongPress onLongPress_;
CancelableCallback<void()> deadlineTimer_;
CancelableCallback<void()> timer_;
int32_t duration_ = 500;
int32_t fingers_ = 1;
bool repeat_ = false;
std::map<int32_t, TouchEvent> touchMap_;
int32_t pointsCount_ = 0;
TimeStamp time_;
bool pendingEnd_ = false;
bool pendingCancel_ = false;
bool useCatchMode_ = true;
bool isForDrag_ = false;
bool isDisableMouseLeft_ = false;
Point globalPoint_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_LONG_PRESS_RECOGNIZER_H

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
#include "base/memory/ace_type.h"
namespace OHOS::Ace::NG {
void MultiFingersRecognizer::OnAccepted(size_t touchId)
{
if (!IsInReferee(touchId)) {
return;
}
acceptedCount_++;
if (refereePointers_.size() == acceptedCount_) {
OnAccepted();
refereePointers_.clear();
acceptedCount_ = 0;
}
}
void MultiFingersRecognizer::OnRejected(size_t touchId)
{
if (!IsInReferee(touchId)) {
return;
}
OnRejected();
refereePointers_.clear();
acceptedCount_ = 0;
}
void MultiFingersRecognizer::Adjudicate(const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
{
if (refereePointers_.empty()) {
return;
}
std::set<size_t> copyIds = refereePointers_;
GestureRecognizer::BatchAdjudicate(copyIds, recognizer, disposal);
}
void MultiFingersRecognizer::AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
auto result = refereePointers_.emplace(touchId);
if (result.second) {
GestureRecognizer::AddToReferee(touchId, recognizer);
}
}
void MultiFingersRecognizer::DelFromReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
refereePointers_.erase(touchId);
GestureRecognizer::DelFromReferee(touchId, recognizer);
}
bool MultiFingersRecognizer::IsInReferee(size_t touchId)
{
return refereePointers_.find(touchId) != refereePointers_.end();
}
void MultiFingersRecognizer::SetFingerList(const std::map<int32_t, TouchEvent> touchPoints,
const Offset& coordinateOffset, std::list<FingerInfo>& fingerList)
{
for (auto& point : touchPoints) {
Offset localLocation = point.second.GetOffset() - coordinateOffset;
FingerInfo fingerInfo = {point.first, point.second.GetOffset(), localLocation};
fingerList.emplace_back(fingerInfo);
}
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_MULTI_FINGERS_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_MULTI_FINGERS_RECOGNIZER_H
#include <functional>
#include <map>
#include "core/components_ng/gestures/recognizers/gesture_recognizer.h"
namespace OHOS::Ace::NG {
// ClickRecognizer identifies only single click events.
// For long press and double click, see: LongPressRecognizer and DoubleClickRecognizer.
class MultiFingersRecognizer : public GestureRecognizer {
DECLARE_ACE_TYPE(MultiFingersRecognizer, GestureRecognizer);
public:
MultiFingersRecognizer() = default;
~MultiFingersRecognizer() override = default;
void OnAccepted(size_t touchId) override;
void OnRejected(size_t touchId) override;
void AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer) override;
void DelFromReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer) override;
bool IsInReferee(size_t touchId);
void Adjudicate(const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal);
virtual void OnAccepted() {}
virtual void OnRejected() {}
void SetRefereePointer(size_t touchId)
{
refereePointers_.emplace(touchId);
}
std::set<size_t> refereePointers_;
void SetFingerList(const std::map<int32_t, TouchEvent> touchPoints, const Offset& coordinateOffset,
std::list<FingerInfo>& fingerList);
private:
size_t acceptedCount_ = 0;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_MULTI_FINGERS_RECOGNIZER_H

View File

@ -0,0 +1,442 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/pan_recognizer.h"
#include "base/geometry/offset.h"
#include "base/log/log.h"
#include "core/components_ng/gestures/gesture_referee.h"
#include "core/event/axis_event.h"
namespace OHOS::Ace::NG {
namespace {
constexpr int32_t MAX_PAN_FINGERS = 10;
constexpr double DISTANCE_PER_MOUSE_DEGREE = DP_PER_LINE_DESKTOP * LINE_NUMBER_DESKTOP / MOUSE_WHEEL_DEGREES;
constexpr int32_t AXIS_PAN_FINGERS = 1;
} // namespace
void PanRecognizer::OnAccepted()
{
SendCallbackMsg(onActionStart_);
SendCallbackMsg(onActionUpdate_);
if (pendingEnd_) {
LOGD("pan gesture recognizer has pending end event when waiting to be accepted");
SendCallbackMsg(onActionEnd_);
Reset();
} else if (pendingCancel_) {
SendCancelMsg();
Reset();
}
}
void PanRecognizer::OnRejected()
{
LOGD("pan gesture has been rejected!");
Reset();
}
void PanRecognizer::HandleTouchDownEvent(const TouchEvent& event)
{
LOGD("pan recognizer receives touch down event, begin to detect pan event");
fingers_ = newFingers_;
distance_ = newDistance_;
direction_ = newDirection_;
if (fingers_ > MAX_PAN_FINGERS) {
return;
}
if (direction_.type == PanDirection::NONE) {
return;
}
deviceId_ = event.deviceId;
deviceType_ = event.sourceType;
touchPoints_[event.id] = event;
if (state_ == DetectState::READY) {
AddToReferee(event.id, AceType::Claim(this));
if (static_cast<int32_t>(refereePointers_.size()) == fingers_) {
velocityTracker_.Reset();
velocityTracker_.UpdateTouchPoint(event);
state_ = DetectState::DETECTING;
}
}
}
void PanRecognizer::HandleTouchDownEvent(const AxisEvent& event)
{
LOGD("pan recognizer receives axis start event, begin to detect pan event");
if (fingers_ != AXIS_PAN_FINGERS) {
return;
}
if (direction_.type == PanDirection::NONE) {
return;
}
deviceId_ = event.deviceId;
deviceType_ = event.sourceType;
lastAxisEvent_ = event;
if (state_ == DetectState::READY) {
state_ = DetectState::DETECTING;
}
}
void PanRecognizer::HandleTouchUpEvent(const TouchEvent& event)
{
LOGD("pan recognizer receives touch up event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
globalPoint_ = Point(event.x, event.y);
touchPoints_.erase(itr);
velocityTracker_.UpdateTouchPoint(event, true);
if (state_ == DetectState::READY) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (state_ == DetectState::DETECTING) {
size_t inRefereeNum = refereePointers_.size();
bool inReferee = IsInReferee(static_cast<size_t>(event.id));
if (inReferee) {
inRefereeNum--;
}
if (static_cast<int32_t>(touchPoints_.size()) < fingers_ || inRefereeNum < 1) {
LOGD("this gesture is not pan, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (inReferee) {
DelFromReferee(event.id, AceType::Claim(this));
}
return;
}
if (static_cast<int32_t>(touchPoints_.size()) < fingers_) {
if (refereeState_ == RefereeState::SUCCEED) {
SendCallbackMsg(onActionEnd_);
Reset();
} else {
pendingEnd_ = true;
}
}
}
void PanRecognizer::HandleTouchUpEvent(const AxisEvent& event)
{
LOGD("pan recognizer receives axis end event");
if (fingers_ != AXIS_PAN_FINGERS) {
return;
}
globalPoint_ = Point(event.x, event.y);
if (state_ != DetectState::DETECTED) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
state_ = DetectState::READY;
return;
}
SendCallbackMsg(onActionEnd_, false);
Reset();
}
void PanRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
{
LOGD("pan recognizer receives touch move event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
globalPoint_ = Point(event.x, event.y);
if (state_ == DetectState::READY) {
touchPoints_[event.id] = event;
return;
}
delta_ = (event.GetOffset() - touchPoints_[event.id].GetOffset()) / touchPoints_.size();
mainDelta_ = GetMainAxisDelta();
velocityTracker_.UpdateTouchPoint(event);
averageDistance_ += delta_;
touchPoints_[event.id] = event;
time_ = event.time;
if (state_ == DetectState::DETECTING) {
auto result = IsPanGestureAccept();
if (result == GestureAcceptResult::ACCEPT) {
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
} else if (result == GestureAcceptResult::REJECT) {
LOGW("pan recognizer reject");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
} else if (state_ == DetectState::DETECTED && refereeState_ == RefereeState::SUCCEED) {
if ((direction_.type & PanDirection::VERTICAL) == 0) {
averageDistance_.SetY(0.0);
} else if ((direction_.type & PanDirection::HORIZONTAL) == 0) {
averageDistance_.SetX(0.0);
}
LOGD("pan recognizer detected successful");
if (isFlushTouchEventsEnd_) {
SendCallbackMsg(onActionUpdate_);
}
}
}
void PanRecognizer::OnFlushTouchEventsBegin()
{
isFlushTouchEventsEnd_ = false;
}
void PanRecognizer::OnFlushTouchEventsEnd()
{
isFlushTouchEventsEnd_ = true;
}
void PanRecognizer::HandleTouchMoveEvent(const AxisEvent& event)
{
LOGD("pan recognizer receives axis update event");
if (fingers_ != AXIS_PAN_FINGERS) {
return;
}
globalPoint_ = Point(event.x, event.y);
if (state_ == DetectState::READY) {
lastAxisEvent_ = event;
return;
}
if ((direction_.type & PanDirection::HORIZONTAL) == 0) {
// PanRecognizer Direction: Vertical
delta_ = Offset(-event.horizontalAxis * DISTANCE_PER_MOUSE_DEGREE,
-event.verticalAxis * DISTANCE_PER_MOUSE_DEGREE);
} else if ((direction_.type & PanDirection::VERTICAL) == 0) {
// PanRecognizer Direction: Horizontal
if (NearZero(event.horizontalAxis)) {
delta_ = Offset(-event.verticalAxis * DISTANCE_PER_MOUSE_DEGREE, 0);
} else {
delta_ = Offset(-event.horizontalAxis * DISTANCE_PER_MOUSE_DEGREE,
-event.verticalAxis * DISTANCE_PER_MOUSE_DEGREE);
}
}
mainDelta_ = GetMainAxisDelta();
averageDistance_ += delta_;
lastAxisEvent_ = event;
time_ = event.time;
if (state_ == DetectState::DETECTING) {
auto result = IsPanGestureAccept();
if (result == GestureAcceptResult::ACCEPT) {
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
} else if (result == GestureAcceptResult::REJECT) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
}
if (state_ == DetectState::DETECTED) {
if ((direction_.type & PanDirection::VERTICAL) == 0) {
averageDistance_.SetY(0.0);
} else if ((direction_.type & PanDirection::HORIZONTAL) == 0) {
averageDistance_.SetX(0.0);
}
SendCallbackMsg(onActionUpdate_, false);
}
}
void PanRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
{
LOGD("pan recognizer receives touch cancel event");
if (state_ == DetectState::READY || state_ == DetectState::DETECTING) {
LOGD("cancel pan gesture detect, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (refereeState_ == RefereeState::SUCCEED) {
SendCancelMsg();
Reset();
} else {
pendingCancel_ = true;
}
}
void PanRecognizer::HandleTouchCancelEvent(const AxisEvent& event)
{
if (fingers_ != AXIS_PAN_FINGERS) {
return;
}
return HandleTouchCancelEvent(TouchEvent {});
}
PanRecognizer::GestureAcceptResult PanRecognizer::IsPanGestureAccept() const
{
if ((direction_.type & PanDirection::ALL) == PanDirection::ALL) {
double offset = averageDistance_.GetDistance();
if (fabs(offset) < distance_) {
return GestureAcceptResult::DETECTING;
}
return GestureAcceptResult::ACCEPT;
}
if (fabs(averageDistance_.GetX()) > fabs(averageDistance_.GetY())) {
if ((direction_.type & PanDirection::HORIZONTAL) != 0) {
double offset = averageDistance_.GetX();
if (fabs(offset) < distance_) {
return GestureAcceptResult::DETECTING;
}
if ((direction_.type & PanDirection::LEFT) == 0 && offset < 0) {
return GestureAcceptResult::REJECT;
}
if ((direction_.type & PanDirection::RIGHT) == 0 && offset > 0) {
return GestureAcceptResult::REJECT;
}
return GestureAcceptResult::ACCEPT;
}
return GestureAcceptResult::DETECTING;
} else {
if ((direction_.type & PanDirection::VERTICAL) != 0) {
double offset = averageDistance_.GetY();
if (fabs(offset) < distance_) {
return GestureAcceptResult::DETECTING;
}
if ((direction_.type & PanDirection::UP) == 0 && offset < 0) {
return GestureAcceptResult::REJECT;
}
if ((direction_.type & PanDirection::DOWN) == 0 && offset > 0) {
return GestureAcceptResult::REJECT;
}
return GestureAcceptResult::ACCEPT;
}
return GestureAcceptResult::DETECTING;
}
}
void PanRecognizer::Reset()
{
touchPoints_.clear();
averageDistance_.Reset();
state_ = DetectState::READY;
pendingEnd_ = false;
pendingCancel_ = false;
}
void PanRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback, bool isTouchEvent)
{
if (callback && *callback) {
GestureEvent info;
info.SetTimeStamp(time_);
info.SetOffsetX(averageDistance_.GetX());
info.SetOffsetY(averageDistance_.GetY());
TouchEvent touchPoint = {};
if (!touchPoints_.empty()) {
touchPoint = touchPoints_.begin()->second;
}
info.SetGlobalPoint(globalPoint_).SetLocalLocation(touchPoint.GetOffset() - coordinateOffset_);
info.SetDeviceId(deviceId_);
info.SetSourceDevice(deviceType_);
info.SetDelta(delta_);
info.SetMainDelta(mainDelta_);
if (isTouchEvent) {
info.SetVelocity(velocityTracker_.GetVelocity());
info.SetMainVelocity(velocityTracker_.GetMainAxisVelocity());
} else {
info.SetVelocity(Velocity());
info.SetMainVelocity(0.0);
}
info.SetTarget(GetEventTarget().value_or(EventTarget()));
(*callback)(info);
}
}
bool PanRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<PanRecognizer> curr = AceType::DynamicCast<PanRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (curr->fingers_ != fingers_ || curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
direction_.type = curr->direction_.type;
newDirection_.type = curr->newDirection_.type;
distance_ = curr->distance_;
newDistance_ = curr->newDistance_;
onActionStart_ = std::move(curr->onActionStart_);
onActionUpdate_ = std::move(curr->onActionUpdate_);
onActionEnd_ = std::move(curr->onActionEnd_);
onActionCancel_ = std::move(curr->onActionCancel_);
return true;
}
void PanRecognizer::ChangeFingers(int32_t fingers)
{
if (fingers_ != fingers) {
newFingers_ = fingers;
}
}
void PanRecognizer::ChangeDirection(const PanDirection& direction)
{
if (direction_.type != direction.type) {
direction_.type = direction.type;
newDirection_.type = direction.type;
}
}
void PanRecognizer::ChangeDistance(double distance)
{
if (distance_ != distance) {
if (state_ == DetectState::READY || state_ == DetectState::DETECTING) {
distance_ = distance;
}
newDistance_ = distance;
}
}
double PanRecognizer::GetMainAxisDelta()
{
switch (direction_.type) {
case PanDirection::ALL:
return delta_.GetDistance();
case PanDirection::HORIZONTAL:
return delta_.GetX();
case PanDirection::VERTICAL:
return delta_.GetY();
default:
return 0.0;
}
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PAN_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PAN_RECOGNIZER_H
#include <cmath>
#include <functional>
#include <map>
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
class PanRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(PanRecognizer, MultiFingersRecognizer);
public:
PanRecognizer(int32_t fingers, const PanDirection& direction, double distance)
: direction_(direction), distance_(distance)
{
fingers_ = fingers;
newFingers_ = fingers_;
newDistance_ = distance_;
newDirection_ = direction_;
if ((direction_.type & PanDirection::VERTICAL) == 0) {
velocityTracker_ = VelocityTracker(Axis::HORIZONTAL);
} else if ((direction_.type & PanDirection::HORIZONTAL) == 0) {
velocityTracker_ = VelocityTracker(Axis::VERTICAL);
}
}
PanRecognizer(RefPtr<PanGestureOption> panGestureOption) : panGestureOption_(panGestureOption)
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
uint32_t directNum = panGestureOption->GetDirection().type;
double distanceNumber = panGestureOption->GetDistance();
int32_t fingersNumber = panGestureOption->GetFingers();
double distance = LessNotEqual(distanceNumber, 0.0) ? DEFAULT_PAN_DISTANCE : distanceNumber;
distance_ = context->NormalizeToPx(Dimension(distance, DimensionUnit::VP));
fingers_ = fingersNumber <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingersNumber;
if (directNum >= PanDirection::NONE && directNum <= PanDirection::ALL) {
direction_.type = directNum;
}
newFingers_ = fingers_;
newDistance_ = distance_;
newDirection_ = direction_;
PanFingersFuncType changeFingers = [weak = AceType::WeakClaim(this)](int32_t fingers) {
auto panRecognizer = weak.Upgrade();
if (!panRecognizer) {
return;
}
panRecognizer->ChangeFingers(fingers);
};
onChangeFingers_ = OnPanFingersFunc(changeFingers);
panGestureOption_->SetOnPanFingersId(onChangeFingers_);
PanDirectionFuncType changeDirection = [weak = AceType::WeakClaim(this)](const PanDirection& direction) {
auto panRecognizer = weak.Upgrade();
if (!panRecognizer) {
return;
}
panRecognizer->ChangeDirection(direction);
};
onChangeDirection_ = OnPanDirectionFunc(changeDirection);
panGestureOption_->SetOnPanDirectionId(onChangeDirection_);
PanDistanceFuncType changeDistance = [weak = AceType::WeakClaim(this)](double distance) {
auto panRecognizer = weak.Upgrade();
if (!panRecognizer) {
return;
}
panRecognizer->ChangeDistance(distance);
};
onChangeDistance_ = OnPanDistanceFunc(changeDistance);
panGestureOption_->SetOnPanDistanceId(onChangeDistance_);
}
~PanRecognizer() override
{
if (panGestureOption_ == nullptr) {
return;
}
panGestureOption_->GetOnPanFingersIds().erase(onChangeFingers_.GetId());
panGestureOption_->GetOnPanDirectionIds().erase(onChangeDirection_.GetId());
panGestureOption_->GetOnPanDistanceIds().erase(onChangeDistance_.GetId());
}
void OnAccepted() override;
void OnRejected() override;
void OnFlushTouchEventsBegin() override;
void OnFlushTouchEventsEnd() override;
private:
enum class GestureAcceptResult {
ACCEPT,
REJECT,
DETECTING,
};
void HandleTouchDownEvent(const TouchEvent& event) override;
void HandleTouchUpEvent(const TouchEvent& event) override;
void HandleTouchMoveEvent(const TouchEvent& event) override;
void HandleTouchCancelEvent(const TouchEvent& event) override;
void HandleTouchDownEvent(const AxisEvent& event) override;
void HandleTouchUpEvent(const AxisEvent& event) override;
void HandleTouchMoveEvent(const AxisEvent& event) override;
void HandleTouchCancelEvent(const AxisEvent& event) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
GestureAcceptResult IsPanGestureAccept() const;
void Reset();
void SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback, bool isTouchEvent = true);
void ChangeFingers(int32_t fingers);
void ChangeDirection(const PanDirection& direction);
void ChangeDistance(double distance);
double GetMainAxisDelta();
const TouchRestrict& GetTouchRestrict() const
{
return touchRestrict_;
}
PanDirection direction_;
double distance_ = 0.0;
std::map<int32_t, TouchEvent> touchPoints_;
AxisEvent lastAxisEvent_;
Offset averageDistance_;
Offset delta_;
double mainDelta_ = 0.0;
VelocityTracker velocityTracker_;
TimeStamp time_;
bool pendingEnd_ = false;
bool pendingCancel_ = false;
Point globalPoint_;
RefPtr<PanGestureOption> panGestureOption_;
OnPanFingersFunc onChangeFingers_;
OnPanDirectionFunc onChangeDirection_;
OnPanDistanceFunc onChangeDistance_;
int32_t newFingers_ = 1;
double newDistance_ = 0.0;
PanDirection newDirection_;
bool isFlushTouchEventsEnd_ = false;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PAN_RECOGNIZER_H

View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/parallel_recognizer.h"
#include <vector>
#include "base/geometry/offset.h"
#include "base/log/log.h"
#include "core/components_ng/gestures/gesture_referee.h"
namespace OHOS::Ace::NG {
void ParallelRecognizer::OnAccepted(size_t touchId)
{
if (refereePointers_.find(touchId) == refereePointers_.end()) {
return;
}
refereePointers_.erase(touchId);
LOGD("the parallel gesture recognizer has been accepted, touch id %{public}zu", touchId);
for (auto& recognizer : recognizers_) {
if (recognizer->GetDetectState() == DetectState::DETECTED) {
recognizer->SetCoordinateOffset(coordinateOffset_);
recognizer->OnAccepted(touchId);
recognizer->SetRefereeState(RefereeState::SUCCEED);
}
}
}
void ParallelRecognizer::OnRejected(size_t touchId)
{
if (refereePointers_.find(touchId) == refereePointers_.end()) {
return;
}
refereePointers_.erase(touchId);
LOGD("the parallel gesture recognizer has been rejected! the touch id is %{public}zu", touchId);
for (auto& recognizer : recognizers_) {
recognizer->OnRejected(touchId);
if (recognizer->GetDetectState() == DetectState::READY) {
recognizer->SetRefereeState(RefereeState::FAIL);
}
}
}
void ParallelRecognizer::OnPending(size_t touchId)
{
if (refereePointers_.find(touchId) == refereePointers_.end()) {
return;
}
LOGD("the parallel gesture recognizer is pending! the touch id is %{public}zu", touchId);
for (auto& recognizer : recognizers_) {
if (recognizer->GetRefereeState() == RefereeState::PENDING) {
recognizer->OnPending(touchId);
}
}
}
bool ParallelRecognizer::HandleEvent(const TouchEvent& point)
{
if (point.type == TouchType::UNKNOWN) {
LOGW("unknown touch type");
return true;
}
if (point.type == TouchType::DOWN) {
bool allRecognizeEnd = true;
for (auto& recognizer : recognizers_) {
if (!IsRecognizeEnd(recognizer)) {
allRecognizeEnd = false;
break;
}
}
if (allRecognizeEnd) {
LOGD("all sub gestures recognize finish, change the parallel state to be ready");
Reset();
}
}
for (auto& recognizer : recognizers_) {
if (recognizer->GetRefereeState() != RefereeState::FAIL) {
recognizer->HandleEvent(point);
}
}
return true;
}
void ParallelRecognizer::OnFlushTouchEventsBegin()
{
for (auto& recognizer : recognizers_) {
recognizer->OnFlushTouchEventsBegin();
}
}
void ParallelRecognizer::OnFlushTouchEventsEnd()
{
for (auto& recognizer : recognizers_) {
recognizer->OnFlushTouchEventsEnd();
}
}
bool ParallelRecognizer::IsRecognizeEnd(const RefPtr<GestureRecognizer>& recognizer)
{
DetectState currState = recognizer->GetDetectState();
RefereeState refereeState = recognizer->GetRefereeState();
return (refereeState == RefereeState::SUCCEED && currState != DetectState::DETECTED) ||
(refereeState == RefereeState::FAIL);
}
void ParallelRecognizer::BatchAdjudicate(
const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
{
if (disposal == GestureDisposal::ACCEPT) {
if (state_ == DetectState::DETECTING) {
LOGD("the sub gesture recognizer %{public}s ask for accept", AceType::TypeName(recognizer));
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
} else if (refereeState_ == RefereeState::SUCCEED) {
LOGD("the sub gesture recognizer %{public}s is accepted because referee succeed",
AceType::TypeName(recognizer));
for (auto touchId : touchIds) {
recognizer->OnAccepted(touchId);
}
recognizer->SetRefereeState(RefereeState::SUCCEED);
}
} else if (disposal == GestureDisposal::REJECT) {
for (auto touchId : touchIds) {
recognizer->OnRejected(touchId);
}
recognizer->SetRefereeState(RefereeState::FAIL);
LOGD("the sub gesture recognizer %{public}s ask for reject", AceType::TypeName(recognizer));
bool needReject = true;
for (auto& tmpRecognizer : recognizers_) {
if (tmpRecognizer->GetRefereeState() != RefereeState::FAIL) {
needReject = false;
break;
}
}
if (needReject) {
LOGD("all gesture recognizers are rejected, adjudicate reject");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
} else {
if (state_ == DetectState::DETECTING) {
recognizer->SetRefereeState(RefereeState::PENDING);
Adjudicate(AceType::Claim(this), GestureDisposal::PENDING);
}
}
}
void ParallelRecognizer::AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
recognizer->SetRefereeState(RefereeState::DETECTING);
if (state_ == DetectState::READY) {
state_ = DetectState::DETECTING;
}
if (state_ == DetectState::DETECTING) {
MultiFingersRecognizer::AddToReferee(touchId, AceType::Claim(this));
}
}
void ParallelRecognizer::Reset()
{
state_ = DetectState::READY;
for (auto& recognizer : recognizers_) {
recognizer->SetRefereeState(RefereeState::DETECTING);
}
}
bool ParallelRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<ParallelRecognizer> curr = AceType::DynamicCast<ParallelRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (recognizers_.size() != curr->recognizers_.size() || curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
auto currIter = curr->recognizers_.begin();
for (auto iter = recognizers_.begin(); iter != recognizers_.end(); iter++, currIter++) {
if (!(*iter)->ReconcileFrom(*currIter)) {
Reset();
return false;
}
}
return true;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PARALLEL_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PARALLEL_RECOGNIZER_H
#include <functional>
#include "core/components_ng/gestures/gesture_info.h"
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
namespace OHOS::Ace::NG {
// ParallelRecognizer identifies events in parallel recognizers.
// For long press and double click, see: LongPressRecognizer and DoubleClickRecognizer.
class ACE_EXPORT ParallelRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(ParallelRecognizer, MultiFingersRecognizer);
public:
explicit ParallelRecognizer(const std::vector<RefPtr<GestureRecognizer>>& recognizers)
{
for (const auto& recognizer : recognizers) {
recognizer->SetGestureGroup(AceType::WeakClaim(this));
recognizers_.emplace_back(recognizer);
}
}
explicit ParallelRecognizer(std::list<RefPtr<GestureRecognizer>>&& recognizers)
{
recognizers_ = std::move(recognizers);
for (const auto& recognizer : recognizers_) {
recognizer->SetGestureGroup(AceType::WeakClaim(this));
}
}
~ParallelRecognizer() override = default;
void OnAccepted(size_t touchId) override;
void OnRejected(size_t touchId) override;
void OnPending(size_t touchId) override;
bool HandleEvent(const TouchEvent& point) override;
void OnFlushTouchEventsBegin() override;
void OnFlushTouchEventsEnd() override;
private:
void HandleTouchDownEvent(const TouchEvent& event) override {};
void HandleTouchUpEvent(const TouchEvent& event) override {};
void HandleTouchMoveEvent(const TouchEvent& event) override {};
void HandleTouchCancelEvent(const TouchEvent& event) override {};
void BatchAdjudicate(const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer,
GestureDisposal disposal) override;
void AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
void Reset();
void DelFromReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer) override {}
bool IsRecognizeEnd(const RefPtr<GestureRecognizer>& recognizer);
std::list<RefPtr<GestureRecognizer>> recognizers_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PARALLEL_RECOGNIZER_H

View File

@ -0,0 +1,295 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/pinch_recognizer.h"
#include "base/geometry/offset.h"
#include "base/log/log.h"
#include "base/ressched/ressched_report.h"
#include "core/components_ng/gestures/gesture_referee.h"
namespace OHOS::Ace::NG {
namespace {
constexpr int32_t MAX_PINCH_FINGERS = 5;
constexpr int32_t AXIS_PINCH_FINGERS = 2;
} // namespace
void PinchRecognizer::OnAccepted()
{
ResSchedReport::GetInstance().ResSchedDataReport("click");
SendCallbackMsg(onActionStart_);
if (pendingEnd_) {
SendCallbackMsg(onActionEnd_);
Reset();
} else if (pendingCancel_) {
SendCancelMsg();
Reset();
}
}
void PinchRecognizer::OnRejected()
{
LOGD("pinch gesture has been rejected!");
Reset();
}
void PinchRecognizer::HandleTouchDownEvent(const TouchEvent& event)
{
LOGD("pinch recognizer receives touch down event, begin to detect pinch event");
if (fingers_ > MAX_PINCH_FINGERS) {
return;
}
if (state_ == DetectState::READY) {
AddToReferee(event.id, AceType::Claim(this));
touchPoints_[event.id] = event;
if (static_cast<int32_t>(touchPoints_.size()) == fingers_) {
initialDev_ = ComputeAverageDeviation();
pinchCenter_ = ComputePinchCenter();
state_ = DetectState::DETECTING;
}
}
}
void PinchRecognizer::HandleTouchDownEvent(const AxisEvent& event)
{
LOGD("pinch recognizer receives touch down event, begin to detect pinch event");
if (fingers_ != AXIS_PINCH_FINGERS) {
return;
}
if (state_ == DetectState::READY) {
pinchCenter_ = Offset(event.x, event.y);
state_ = DetectState::DETECTING;
}
}
void PinchRecognizer::HandleTouchUpEvent(const TouchEvent& event)
{
LOGD("pinch recognizer receives touch up event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
touchPoints_.erase(itr);
if (state_ != DetectState::DETECTED) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (refereeState_ == RefereeState::SUCCEED) {
SendCallbackMsg(onActionEnd_);
Reset();
} else {
pendingEnd_ = true;
}
}
void PinchRecognizer::HandleTouchUpEvent(const AxisEvent& event)
{
LOGD("pinch recognizer receives touch up event");
if (fingers_ != AXIS_PINCH_FINGERS) {
return;
}
if (state_ != DetectState::DETECTED) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
SendCallbackMsg(onActionEnd_);
Reset();
}
void PinchRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
{
LOGD("pinch recognizer receives touch move event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
if (state_ == DetectState::READY) {
touchPoints_[event.id] = event;
return;
}
touchPoints_[event.id] = event;
currentDev_ = ComputeAverageDeviation();
time_ = event.time;
if (state_ == DetectState::DETECTING) {
if (GreatOrEqual(fabs(currentDev_ - initialDev_), distance_)) {
scale_ = currentDev_ / initialDev_;
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
}
} else if (state_ == DetectState::DETECTED && refereeState_ == RefereeState::SUCCEED) {
scale_ = currentDev_ / initialDev_;
if (isFlushTouchEventsEnd_) {
SendCallbackMsg(onActionUpdate_);
}
}
}
void PinchRecognizer::OnFlushTouchEventsBegin()
{
isFlushTouchEventsEnd_ = false;
}
void PinchRecognizer::OnFlushTouchEventsEnd()
{
isFlushTouchEventsEnd_ = true;
}
void PinchRecognizer::HandleTouchMoveEvent(const AxisEvent& event)
{
LOGD("pinch recognizer receives touch move event");
if (fingers_ != AXIS_PINCH_FINGERS) {
return;
}
if (state_ == DetectState::READY) {
return;
}
time_ = event.time;
if (state_ == DetectState::DETECTING) {
scale_ = event.pinchAxisScale;
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
}
if (state_ == DetectState::DETECTED) {
scale_ = event.pinchAxisScale;
SendCallbackMsg(onActionUpdate_);
}
}
void PinchRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
{
LOGD("pinch recognizer receives touch cancel event");
if (state_ == DetectState::READY || state_ == DetectState::DETECTING) {
LOGD("cancel pinch gesture detect, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (refereeState_ == RefereeState::SUCCEED) {
SendCancelMsg();
Reset();
} else {
pendingCancel_ = true;
}
}
void PinchRecognizer::HandleTouchCancelEvent(const AxisEvent& event)
{
SendCancelMsg();
Reset();
}
double PinchRecognizer::ComputeAverageDeviation()
{
// compute the coordinate of focal point
double sumOfX = 0.0;
double sumOfY = 0.0;
for (auto& element : touchPoints_) {
sumOfX = sumOfX + element.second.x;
sumOfY = sumOfY + element.second.y;
}
double focalX = sumOfX / touchPoints_.size();
double focalY = sumOfY / touchPoints_.size();
// compute average deviation
double devX = 0.0;
double devY = 0.0;
for (auto& element : touchPoints_) {
devX = devX + fabs(element.second.x - focalX);
devY = devY + fabs(element.second.y - focalY);
}
double aveDevX = devX / touchPoints_.size();
double aveDevY = devY / touchPoints_.size();
// compute zoom distance
double zoomDistance = sqrt(pow(aveDevX, 2) + pow(aveDevY, 2));
return zoomDistance;
}
Offset PinchRecognizer::ComputePinchCenter()
{
double sumOfX = 0.0;
double sumOfY = 0.0;
for (auto& element : touchPoints_) {
sumOfX = sumOfX + element.second.x;
sumOfY = sumOfY + element.second.y;
}
double focalX = sumOfX / touchPoints_.size();
double focalY = sumOfY / touchPoints_.size();
Offset pinchCenter = Offset(focalX, focalY);
return pinchCenter;
}
void PinchRecognizer::Reset()
{
touchPoints_.clear();
state_ = DetectState::READY;
pendingEnd_ = false;
pendingCancel_ = false;
}
void PinchRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback)
{
if (callback && *callback) {
GestureEvent info;
info.SetTimeStamp(time_);
info.SetScale(scale_);
info.SetPinchCenter(pinchCenter_);
info.SetDeviceId(deviceId_);
info.SetSourceDevice(deviceType_);
info.SetTarget(GetEventTarget().value_or(EventTarget()));
(*callback)(info);
}
}
bool PinchRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<PinchRecognizer> curr = AceType::DynamicCast<PinchRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (curr->fingers_ != fingers_ || curr->distance_ != distance_ || curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
onActionStart_ = std::move(curr->onActionStart_);
onActionUpdate_ = std::move(curr->onActionUpdate_);
onActionEnd_ = std::move(curr->onActionEnd_);
onActionCancel_ = std::move(curr->onActionCancel_);
return true;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PINCH_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PINCH_RECOGNIZER_H
#include <cmath>
#include <functional>
#include <map>
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
namespace OHOS::Ace::NG {
class PinchRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(PinchRecognizer, MultiFingersRecognizer);
public:
PinchRecognizer(int32_t fingers, double distance) : distance_(distance)
{
fingers_ = fingers;
}
~PinchRecognizer() override = default;
void OnAccepted() override;
void OnRejected() override;
private:
void HandleTouchDownEvent(const TouchEvent& event) override;
void HandleTouchUpEvent(const TouchEvent& event) override;
void HandleTouchMoveEvent(const TouchEvent& event) override;
void HandleTouchCancelEvent(const TouchEvent& event) override;
void HandleTouchDownEvent(const AxisEvent& event) override;
void HandleTouchUpEvent(const AxisEvent& event) override;
void HandleTouchMoveEvent(const AxisEvent& event) override;
void HandleTouchCancelEvent(const AxisEvent& event) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
double ComputeAverageDeviation();
void Reset();
void SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback);
Offset ComputePinchCenter();
void OnFlushTouchEventsBegin() override;
void OnFlushTouchEventsEnd() override;
double distance_ = 0.0;
double initialDev_ = 0.0;
double currentDev_ = 0.0;
double scale_ = 1.0;
Offset pinchCenter_;
TimeStamp time_;
std::map<int32_t, TouchEvent> touchPoints_;
bool pendingEnd_ = false;
bool pendingCancel_ = false;
bool isFlushTouchEventsEnd_ = false;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_PINCH_RECOGNIZER_H

View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/rotation_recognizer.h"
#include "base/geometry/offset.h"
#include "base/log/log.h"
#include "core/components_ng/gestures/gesture_referee.h"
namespace OHOS::Ace::NG {
namespace {
constexpr int32_t MAX_ROTATION_FINGERS = 5;
} // namespace
void RotationRecognizer::OnAccepted()
{
SendCallbackMsg(onActionStart_);
if (pendingEnd_) {
SendCallbackMsg(onActionEnd_);
Reset();
} else if (pendingCancel_) {
SendCancelMsg();
Reset();
}
}
void RotationRecognizer::OnRejected()
{
LOGD("rotation gesture has been rejected!");
Reset();
}
void RotationRecognizer::HandleTouchDownEvent(const TouchEvent& event)
{
LOGD("rotation recognizer receives touch down event, begin to detect rotation event");
if (fingers_ > MAX_ROTATION_FINGERS) {
return;
}
if (state_ == DetectState::READY) {
AddToReferee(event.id, AceType::Claim(this));
touchPoints_[event.id] = event;
if (static_cast<int32_t>(touchPoints_.size()) == fingers_) {
initialAngle_ = ComputeAngle();
state_ = DetectState::DETECTING;
}
}
}
void RotationRecognizer::HandleTouchUpEvent(const TouchEvent& event)
{
LOGD("rotation recognizer receives touch up event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
touchPoints_.erase(itr);
if (state_ != DetectState::DETECTED) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
GestureEvent info;
info.SetTimeStamp(time_);
info.SetAngle(resultAngle_);
if (refereeState_ == RefereeState::SUCCEED) {
SendCallbackMsg(onActionEnd_);
Reset();
} else {
pendingEnd_ = true;
}
}
void RotationRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
{
LOGD("rotation recognizer receives touch move event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
if (state_ == DetectState::READY) {
touchPoints_[event.id] = event;
return;
}
touchPoints_[event.id] = event;
currentAngle_ = ComputeAngle();
time_ = event.time;
if (state_ == DetectState::DETECTING) {
double diffAngle = fabs((currentAngle_ - initialAngle_));
if (GreatOrEqual(diffAngle, angle_)) {
resultAngle_ = ChangeValueRange(currentAngle_ - initialAngle_);
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
}
} else if (state_ == DetectState::DETECTED && refereeState_ == RefereeState::SUCCEED) {
resultAngle_ = ChangeValueRange(currentAngle_ - initialAngle_);
SendCallbackMsg(onActionUpdate_);
}
}
void RotationRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
{
LOGD("rotation recognizer receives touch cancel event");
if (state_ == DetectState::READY || state_ == DetectState::DETECTING) {
LOGD("cancel rotation gesture detect, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (refereeState_ == RefereeState::SUCCEED) {
SendCancelMsg();
Reset();
} else {
pendingCancel_ = true;
}
}
double RotationRecognizer::ComputeAngle()
{
double fx = touchPoints_[0].x;
double fy = touchPoints_[0].y;
double sx = touchPoints_[1].x;
double sy = touchPoints_[1].y;
double angle = atan2(fy - sy, fx - sx) * 180.0 / M_PI;
return angle;
}
// Map the value range to -180 to 180
double RotationRecognizer::ChangeValueRange(double value)
{
double result = 0.0;
if (LessOrEqual(value, -180.0)) {
result = value + 360.0;
} else if (GreatNotEqual(value, 180.0)) {
result = value - 360.0;
} else {
result = value;
}
return result;
}
void RotationRecognizer::Reset()
{
touchPoints_.clear();
state_ = DetectState::READY;
pendingEnd_ = false;
pendingCancel_ = false;
}
void RotationRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback)
{
if (callback && *callback) {
GestureEvent info;
info.SetTimeStamp(time_);
info.SetAngle(resultAngle_);
info.SetDeviceId(deviceId_);
info.SetSourceDevice(deviceType_);
info.SetTarget(GetEventTarget().value_or(EventTarget()));
(*callback)(info);
}
}
bool RotationRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<RotationRecognizer> curr = AceType::DynamicCast<RotationRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (curr->fingers_ != fingers_ || !NearEqual(curr->angle_, angle_) || curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
onActionStart_ = std::move(curr->onActionStart_);
onActionUpdate_ = std::move(curr->onActionUpdate_);
onActionEnd_ = std::move(curr->onActionEnd_);
onActionCancel_ = std::move(curr->onActionCancel_);
return true;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_ROTATION_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_ROTATION_RECOGNIZER_H
#include <cmath>
#include <functional>
#include <map>
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
namespace OHOS::Ace::NG {
class RotationRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(RotationRecognizer, MultiFingersRecognizer);
public:
RotationRecognizer(int32_t fingers, double angle) : angle_(angle)
{
fingers_ = fingers;
}
~RotationRecognizer() override = default;
void OnAccepted() override;
void OnRejected() override;
private:
void HandleTouchDownEvent(const TouchEvent& event) override;
void HandleTouchUpEvent(const TouchEvent& event) override;
void HandleTouchMoveEvent(const TouchEvent& event) override;
void HandleTouchCancelEvent(const TouchEvent& event) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
double ComputeAngle();
void Reset();
void SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback);
static double ChangeValueRange(double value);
double angle_ = 0.0;
double initialAngle_ = 0.0;
double currentAngle_ = 0.0;
double resultAngle_ = 0.0;
TimeStamp time_;
std::map<int32_t, TouchEvent> touchPoints_;
bool pendingEnd_ = false;
bool pendingCancel_ = false;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_ROTATION_RECOGNIZER_H

View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/sequenced_recognizer.h"
#include <vector>
#include "base/thread/task_executor.h"
#include "base/utils/utils.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
namespace {
constexpr int32_t SEQUENCE_GESTURE_TIMEOUT = 300;
}
void SequencedRecognizer::OnAccepted()
{
LOGD("the sequenced gesture recognizer has been accepted.");
if (activeIndex >= recognizers_.size()) {
return;
}
for (size_t touchId : refereePointers_) {
recognizers_[activeIndex]->SetCoordinateOffset(coordinateOffset_);
recognizers_[activeIndex]->OnAccepted(touchId);
}
recognizers_[activeIndex]->SetRefereeState(RefereeState::SUCCEED);
}
void SequencedRecognizer::OnRejected()
{
LOGD("the sequenced gesture recognizer has been rejected!");
if (activeIndex >= recognizers_.size()) {
return;
}
for (size_t touchId : refereePointers_) {
auto recognizer = AceType::DynamicCast<MultiFingersRecognizer>(recognizers_[activeIndex]);
if (recognizer && recognizer->GetRefereeState() == RefereeState::SUCCEED) {
recognizer->SetRefereePointer(touchId);
}
recognizers_[activeIndex]->OnRejected(touchId);
}
recognizers_[activeIndex]->SetRefereeState(RefereeState::FAIL);
if (activeIndex != 0) {
SendCancelMsg();
}
Reset();
}
void SequencedRecognizer::OnPending(size_t touchId)
{
LOGD("the sequenced gesture recognizer is in pending! the touch id is %{public}zu", touchId);
if (activeIndex >= recognizers_.size()) {
return;
}
if (recognizers_[activeIndex]->GetDetectState() == DetectState::DETECTED) {
recognizers_[activeIndex]->OnAccepted(touchId);
recognizers_[activeIndex]->SetRefereeState(RefereeState::SUCCEED);
} else {
recognizers_[activeIndex]->OnPending(touchId);
}
}
bool SequencedRecognizer::HandleEvent(const TouchEvent& point)
{
RefPtr<GestureRecognizer> curRecognizer = recognizers_[activeIndex];
LOGD("dispatch to the %{public}zu gesture recognizer, event type is %{public}zu", activeIndex, point.type);
switch (point.type) {
case TouchType::MOVE:
curPoints_[point.id] = point;
curRecognizer->HandleEvent(point);
break;
case TouchType::DOWN:
if (curPoints_.empty()) {
deadlineTimer_.Cancel();
}
curPoints_[point.id] = point;
curRecognizer->HandleEvent(point);
break;
case TouchType::UP:
curPoints_.erase(point.id);
curRecognizer->HandleEvent(point);
break;
case TouchType::CANCEL:
curPoints_.erase(point.id);
curRecognizer->HandleEvent(point);
break;
default:
LOGW("unknown touch type");
break;
}
DetectState currState = curRecognizer->GetDetectState();
if (curRecognizer->GetRefereeState() == RefereeState::SUCCEED && currState != DetectState::DETECTED) {
// The current recognizer has already been detected, but the touch event destroy the state.
// Should pass the touch point to the next recognizer.
activeIndex++;
if (activeIndex >= recognizers_.size()) {
LOGD("gesture reset to the initial state ");
Reset();
return true;
}
if (curPoints_.empty()) {
DeadlineTimer();
} else {
auto iter = curPoints_.begin();
while (iter != curPoints_.end()) {
iter->second.type = TouchType::DOWN;
recognizers_[activeIndex]->HandleEvent(iter->second);
iter++;
}
}
}
return true;
}
void SequencedRecognizer::OnFlushTouchEventsBegin()
{
for (auto& recognizer : recognizers_) {
recognizer->OnFlushTouchEventsBegin();
}
}
void SequencedRecognizer::OnFlushTouchEventsEnd()
{
for (auto& recognizer : recognizers_) {
recognizer->OnFlushTouchEventsEnd();
}
}
void SequencedRecognizer::BatchAdjudicate(
const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
{
if (disposal == GestureDisposal::ACCEPT) {
LOGD("the sub recognizer %{public}s ask for accept", AceType::TypeName(recognizer));
if (activeIndex == (recognizers_.size() - 1)) {
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
} else {
Adjudicate(AceType::Claim(this), GestureDisposal::PENDING);
}
} else if (disposal == GestureDisposal::REJECT) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
} else {
Adjudicate(AceType::Claim(this), GestureDisposal::PENDING);
}
}
void SequencedRecognizer::AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
{
if (state_ == DetectState::READY) {
state_ = DetectState::DETECTING;
}
recognizer->SetRefereeState(RefereeState::DETECTING);
MultiFingersRecognizer::AddToReferee(touchId, AceType::Claim(this));
}
void SequencedRecognizer::Reset()
{
activeIndex = 0;
state_ = DetectState::READY;
for (auto& recognizer : recognizers_) {
recognizer->SetRefereeState(RefereeState::DETECTING);
}
curPoints_.clear();
}
void SequencedRecognizer::DeadlineTimer()
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto&& callback = [weakPtr = AceType::WeakClaim(this)]() {
auto refPtr = weakPtr.Upgrade();
if (refPtr) {
refPtr->HandleOverdueDeadline();
} else {
LOGE("fail to handle overdue deadline due to context is nullptr");
}
};
deadlineTimer_.Reset(callback);
auto taskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
taskExecutor.PostDelayedTask(deadlineTimer_, SEQUENCE_GESTURE_TIMEOUT);
}
void SequencedRecognizer::HandleOverdueDeadline()
{
LOGI("sequence gesture recognizer does not receive touch down in time");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
bool SequencedRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<SequencedRecognizer> curr = AceType::DynamicCast<SequencedRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (recognizers_.size() != curr->recognizers_.size() || priorityMask_ != curr->priorityMask_) {
Reset();
return false;
}
for (size_t i = 0; i < recognizers_.size(); i++) {
if (!recognizers_[i]->ReconcileFrom(curr->recognizers_[i])) {
Reset();
return false;
}
}
onActionCancel_ = std::move(curr->onActionCancel_);
return true;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_SEQUENCED_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_SEQUENCED_RECOGNIZER_H
#include <functional>
#include "base/thread/cancelable_callback.h"
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
namespace OHOS::Ace::NG {
// SequencedRecognizer identifies only single click events.
// For long press and double click, see: LongPressRecognizer and DoubleClickRecognizer.
class ACE_EXPORT SequencedRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(SequencedRecognizer, MultiFingersRecognizer);
public:
SequencedRecognizer(const std::vector<RefPtr<GestureRecognizer>>& recognizers)
{
for (auto& recognizer : recognizers) {
recognizer->SetGestureGroup(AceType::WeakClaim(this));
}
recognizers_ = recognizers;
}
~SequencedRecognizer() override = default;
void OnAccepted() override;
void OnRejected() override;
bool HandleEvent(const TouchEvent& point) override;
void OnPending(size_t touchId) override;
void OnFlushTouchEventsBegin() override;
void OnFlushTouchEventsEnd() override;
private:
void HandleTouchDownEvent(const TouchEvent& event) override {};
void HandleTouchUpEvent(const TouchEvent& event) override {};
void HandleTouchMoveEvent(const TouchEvent& event) override {};
void HandleTouchCancelEvent(const TouchEvent& event) override {};
void BatchAdjudicate(const std::set<size_t>& touchIds, const RefPtr<GestureRecognizer>& recognizer,
GestureDisposal disposal) override;
void AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
void Reset();
void DeadlineTimer();
void HandleOverdueDeadline();
std::vector<RefPtr<GestureRecognizer>> recognizers_;
std::map<int32_t, TouchEvent> curPoints_;
size_t activeIndex = 0;
CancelableCallback<void()> deadlineTimer_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_SEQUENCED_RECOGNIZER_H

View File

@ -0,0 +1,483 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/recognizers/swipe_recognizer.h"
#include "base/geometry/offset.h"
#include "base/log/log.h"
#include "core/components_ng/gestures/gesture_referee.h"
namespace OHOS::Ace::NG {
namespace {
constexpr int32_t MAX_SWIPE_FINGERS = 10;
constexpr int32_t AXIS_SWIPE_FINGERS = 1;
constexpr int32_t RATIO_MS_TO_S = 1000;
constexpr int32_t RATIO_US_TO_MS = 1000;
constexpr double ANGLE_SUM_OF_TRIANGLE = 180.0;
double ChangeValueRange(double value)
{
double result = 0.0;
if (LessOrEqual(value, -180.0)) {
result = value + 360.0;
} else if (GreatNotEqual(value, 180.0)) {
result = value - 360.0;
} else {
result = value;
}
return result;
}
} // namespace
void SwipeRecognizer::OnAccepted()
{
if (slidingEnd_) {
LOGD("swipe gesture recognizer has sliding end event when waiting to be accepted");
Reset();
} else if (slidingCancel_) {
SendCancelMsg();
Reset();
}
}
void SwipeRecognizer::OnRejected()
{
LOGD("swipe gesture has been rejected!");
Reset();
}
void SwipeRecognizer::HandleTouchDownEvent(const TouchEvent& event)
{
LOGD("swipe recognizer receives touch down event, begin to detect swipe event");
fingers_ = newFingers_;
speed_ = newSpeed_;
direction_ = newDirection_;
if (fingers_ > MAX_SWIPE_FINGERS) {
return;
}
if (direction_.type == SwipeDirection::NONE) {
return;
}
touchPoints_[event.id] = event;
fingersDistance_[event.id] = Offset();
touchDownTime_ = event.time;
if (state_ == DetectState::READY) {
AddToReferee(event.id, AceType::Claim(this));
if (static_cast<int32_t>(refereePointers_.size()) == fingers_) {
initialAngle_ = ComputeAngle();
state_ = DetectState::DETECTING;
}
}
}
void SwipeRecognizer::HandleTouchDownEvent(const AxisEvent& event)
{
LOGD("swipe recognizer receives touch down event, begin to detect swipe event");
fingers_ = newFingers_;
speed_ = newSpeed_;
direction_ = newDirection_;
if (fingers_ != AXIS_SWIPE_FINGERS) {
return;
}
if (direction_.type == SwipeDirection::NONE) {
return;
}
axisEventStart_ = event;
axisVerticalTotal_ = 0.0;
axisHorizontalTotal_ = 0.0;
touchDownTime_ = event.time;
if (state_ == DetectState::READY) {
initialAngle_ = ComputeAngle(event);
state_ = DetectState::DETECTING;
}
}
void SwipeRecognizer::HandleTouchUpEvent(const TouchEvent& event)
{
LOGD("swipe recognizer receives touch up event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
auto itf = fingersDistance_.find(event.id);
if (itf == fingersDistance_.end()) {
return;
}
globalPoint_ = Point(event.x, event.y);
touchPoints_.erase(itr);
auto distanceData = fingersDistance_;
fingersDistance_.erase(itf);
if (state_ == DetectState::READY) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (state_ == DetectState::DETECTING) {
size_t inRefereeNum = refereePointers_.size();
bool inReferee = IsInReferee(static_cast<size_t>(event.id));
if (inReferee) {
inRefereeNum--;
}
if (static_cast<int32_t>(touchPoints_.size()) < fingers_ || inRefereeNum < 1) {
LOGD("this gesture is not swipe, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (inReferee) {
DelFromReferee(event.id, AceType::Claim(this));
}
return;
}
if (static_cast<int32_t>(touchPoints_.size()) <= fingers_) {
if (refereeState_ == RefereeState::SUCCEED) {
double averageSpeed = 0.0;
bool isAvailable = true;
for (const auto& element : distanceData) {
Offset offset = element.second;
double distance = 0.0;
if ((direction_.type & SwipeDirection::ALL) == SwipeDirection::ALL) {
distance = offset.GetDistance();
} else {
if ((direction_.type & SwipeDirection::HORIZONTAL) != 0) {
distance = std::abs(offset.GetX());
} else if ((direction_.type & SwipeDirection::VERTICAL) != 0) {
distance = std::abs(offset.GetY());
}
}
auto slidingTime = event.time - touchDownTime_;
auto duration_ms =
std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1, 1000>>>(slidingTime);
double slidingSpeed = (distance / duration_ms.count()) * 1000;
if (speed_ >= slidingSpeed) {
isAvailable = false;
break;
}
averageSpeed += slidingSpeed;
}
if (isAvailable) {
resultSpeed_ = averageSpeed / distanceData.size();
SendCallbackMsg(onAction_);
}
Reset();
} else {
slidingEnd_ = true;
}
}
}
void SwipeRecognizer::HandleTouchUpEvent(const AxisEvent& event)
{
LOGD("swipe recognizer receives touch up event");
if (fingers_ != AXIS_SWIPE_FINGERS) {
return;
}
globalPoint_ = Point(event.x, event.y);
if (state_ == DetectState::READY) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (state_ == DetectState::DETECTING) {
return;
}
auto slidingTime = event.time - touchDownTime_;
auto duration_ms =
std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1, RATIO_US_TO_MS>>>(slidingTime);
double verticalMoveTotal = axisVerticalTotal_ * DP_PER_LINE_DESKTOP * LINE_NUMBER_DESKTOP / MOUSE_WHEEL_DEGREES;
double horizontalMoveTotal = axisHorizontalTotal_ * DP_PER_LINE_DESKTOP * LINE_NUMBER_DESKTOP / MOUSE_WHEEL_DEGREES;
resultSpeed_ = Offset(horizontalMoveTotal, verticalMoveTotal).GetDistance() / duration_ms.count() * RATIO_MS_TO_S;
if (resultSpeed_ > speed_) {
SendCallbackMsg(onAction_);
}
Reset();
}
void SwipeRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
{
LOGD("swipe recognizer receives touch move event");
auto itr = touchPoints_.find(event.id);
if (itr == touchPoints_.end()) {
return;
}
auto itf = fingersDistance_.find(event.id);
if (itf == fingersDistance_.end()) {
return;
}
globalPoint_ = Point(event.x, event.y);
if (state_ == DetectState::READY) {
touchPoints_[event.id] = event;
return;
}
Offset moveDistance = event.GetOffset() - touchPoints_[event.id].GetOffset();
fingersDistance_[event.id] = itf->second + moveDistance;
touchPoints_[event.id] = event;
currentAngle_ = ComputeAngle();
time_ = event.time;
if (state_ == DetectState::DETECTING) {
double diffAngle = fabs((currentAngle_ - initialAngle_));
if (GreatOrEqual(diffAngle, angle_)) {
resultAngle_ = ChangeValueRange(currentAngle_ - initialAngle_);
}
auto result = ParseFingersOffset();
if (result == GestureAcceptResult::ACCEPT) {
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
} else if (result == GestureAcceptResult::REJECT) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
} else if (state_ == DetectState::DETECTED && refereeState_ == RefereeState::SUCCEED) {
resultAngle_ = ChangeValueRange(currentAngle_ - initialAngle_);
}
}
void SwipeRecognizer::HandleTouchMoveEvent(const AxisEvent& event)
{
LOGD("swipe recognizer receives touch move event");
if (fingers_ != AXIS_SWIPE_FINGERS) {
return;
}
globalPoint_ = Point(event.x, event.y);
if (state_ == DetectState::READY) {
axisEventStart_ = event;
return;
}
axisVerticalTotal_ += fabs(event.verticalAxis);
axisHorizontalTotal_ += fabs(event.horizontalAxis);
currentAngle_ = ComputeAngle(event);
time_ = event.time;
if (state_ == DetectState::DETECTING) {
if (GreatOrEqual(fabs(currentAngle_), angle_)) {
resultAngle_ = ChangeValueRange(currentAngle_);
}
auto result = ParseAxisOffset();
if (result == GestureAcceptResult::ACCEPT) {
state_ = DetectState::DETECTED;
Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
} else if (result == GestureAcceptResult::REJECT) {
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
}
} else if (state_ == DetectState::DETECTED) {
resultAngle_ = ChangeValueRange(currentAngle_);
}
}
void SwipeRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
{
LOGD("swipe recognizer receives touch cancel event");
if (state_ == DetectState::READY || state_ == DetectState::DETECTING) {
LOGD("cancel swipe gesture detect, try to reject it");
Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
return;
}
if (refereeState_ == RefereeState::SUCCEED) {
SendCancelMsg();
Reset();
} else {
slidingCancel_ = true;
}
}
void SwipeRecognizer::HandleTouchCancelEvent(const AxisEvent& event)
{
SendCancelMsg();
Reset();
}
SwipeRecognizer::GestureAcceptResult SwipeRecognizer::ParseFingersOffset() const
{
if ((direction_.type & SwipeDirection::ALL) == SwipeDirection::ALL) {
for (const auto& element : fingersDistance_) {
Offset offset = element.second;
double distance = offset.GetDistance();
if (fabs(distance) < DEFAULT_SLIDE_DISTANCE) {
return GestureAcceptResult::DETECTING;
}
}
return GestureAcceptResult::ACCEPT;
}
for (const auto& element : fingersDistance_) {
Offset offset = element.second;
if (fabs(offset.GetX()) > fabs(offset.GetY())) {
if ((direction_.type & SwipeDirection::HORIZONTAL) != 0) {
double offsetX = offset.GetX();
if (fabs(offsetX) < DEFAULT_SLIDE_DISTANCE) {
return GestureAcceptResult::DETECTING;
}
} else {
return GestureAcceptResult::REJECT;
}
} else {
if ((direction_.type & SwipeDirection::VERTICAL) != 0) {
double offsetY = offset.GetY();
if (fabs(offsetY) < DEFAULT_SLIDE_DISTANCE) {
return GestureAcceptResult::DETECTING;
}
} else {
return GestureAcceptResult::REJECT;
}
}
}
return GestureAcceptResult::ACCEPT;
}
SwipeRecognizer::GestureAcceptResult SwipeRecognizer::ParseAxisOffset() const
{
if ((direction_.type & SwipeDirection::ALL) == SwipeDirection::ALL) {
double distance = Offset(axisHorizontalTotal_, axisVerticalTotal_).GetDistance();
if (fabs(distance) < DEFAULT_SLIDE_DISTANCE) {
return GestureAcceptResult::DETECTING;
}
return GestureAcceptResult::ACCEPT;
}
if (axisHorizontalTotal_ > axisVerticalTotal_) {
if ((direction_.type & SwipeDirection::HORIZONTAL) != 0) {
if (axisHorizontalTotal_ < DEFAULT_SLIDE_DISTANCE) {
return GestureAcceptResult::DETECTING;
}
} else {
return GestureAcceptResult::REJECT;
}
} else {
if ((direction_.type & SwipeDirection::VERTICAL) != 0) {
if (axisVerticalTotal_ < DEFAULT_SLIDE_DISTANCE) {
return GestureAcceptResult::DETECTING;
}
} else {
return GestureAcceptResult::REJECT;
}
}
return GestureAcceptResult::ACCEPT;
}
void SwipeRecognizer::Reset()
{
axisHorizontalTotal_ = 0.0;
axisVerticalTotal_ = 0.0;
touchPoints_.clear();
fingersDistance_.clear();
resultSpeed_ = 0.0;
state_ = DetectState::READY;
slidingEnd_ = false;
slidingCancel_ = false;
}
void SwipeRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback)
{
if (callback && *callback) {
GestureEvent info;
info.SetTimeStamp(time_);
info.SetGlobalPoint(globalPoint_);
info.SetAngle(resultAngle_);
if (deviceType_ == SourceType::MOUSE) {
info.SetSpeed(0.0);
} else {
info.SetSpeed(resultSpeed_);
}
info.SetSourceDevice(deviceType_);
info.SetDeviceId(deviceId_);
info.SetTarget(GetEventTarget().value_or(EventTarget()));
(*callback)(info);
}
}
bool SwipeRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
{
RefPtr<SwipeRecognizer> curr = AceType::DynamicCast<SwipeRecognizer>(recognizer);
if (!curr) {
Reset();
return false;
}
if (curr->fingers_ != fingers_ || !NearEqual(curr->angle_, angle_) || curr->priorityMask_ != priorityMask_) {
Reset();
return false;
}
direction_.type = curr->direction_.type;
newDirection_.type = curr->newDirection_.type;
speed_ = curr->speed_;
newSpeed_ = curr->newSpeed_;
onAction_ = std::move(curr->onAction_);
return true;
}
void SwipeRecognizer::ChangeFingers(int32_t fingers)
{
if (fingers_ != fingers) {
newFingers_ = fingers;
}
}
void SwipeRecognizer::ChangeDirection(const SwipeDirection& direction)
{
if (direction_.type != direction.type) {
direction_.type = direction.type;
newDirection_.type = direction.type;
}
}
void SwipeRecognizer::ChangeSpeed(double speed)
{
if (speed_ != speed) {
if (state_ == DetectState::READY || state_ == DetectState::DETECTING) {
speed_ = speed;
}
newSpeed_ = speed;
}
}
double SwipeRecognizer::ComputeAngle()
{
double fx = touchPoints_[0].x;
double fy = touchPoints_[0].y;
double sx = touchPoints_[1].x;
double sy = touchPoints_[1].y;
return atan2(fy - sy, fx - sx) * ANGLE_SUM_OF_TRIANGLE / M_PI;
}
double SwipeRecognizer::ComputeAngle(AxisEvent event)
{
return atan2(event.verticalAxis, event.horizontalAxis) * ANGLE_SUM_OF_TRIANGLE / M_PI;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_SLIDE_RECOGNIZER_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_SLIDE_RECOGNIZER_H
#include <cmath>
#include <functional>
#include <map>
#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
namespace OHOS::Ace::NG {
class SwipeRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(SwipeRecognizer, MultiFingersRecognizer);
public:
SwipeRecognizer(int32_t fingers, const SwipeDirection& direction, double speed)
: direction_(direction), speed_(speed)
{
fingers_ = fingers;
newSpeed_ = speed_;
newFingers_ = fingers_;
newDirection_ = direction_;
}
void OnAccepted() override;
void OnRejected() override;
~SwipeRecognizer() override {}
private:
enum class GestureAcceptResult {
ACCEPT,
REJECT,
DETECTING,
};
void HandleTouchDownEvent(const TouchEvent& event) override;
void HandleTouchUpEvent(const TouchEvent& event) override;
void HandleTouchMoveEvent(const TouchEvent& event) override;
void HandleTouchCancelEvent(const TouchEvent& event) override;
void HandleTouchDownEvent(const AxisEvent& event) override;
void HandleTouchUpEvent(const AxisEvent& event) override;
void HandleTouchMoveEvent(const AxisEvent& event) override;
void HandleTouchCancelEvent(const AxisEvent& event) override;
bool ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer) override;
GestureAcceptResult ParseFingersOffset() const;
GestureAcceptResult ParseAxisOffset() const;
void Reset();
void SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback);
void ChangeFingers(int32_t fingers);
void ChangeDirection(const SwipeDirection& direction);
void ChangeSpeed(double speed);
double ComputeAngle();
double ComputeAngle(AxisEvent event);
const TouchRestrict& GetTouchRestrict() const
{
return touchRestrict_;
}
SwipeDirection direction_;
double speed_ = 0.0;
WeakPtr<PipelineBase> context_;
std::map<int32_t, TouchEvent> touchPoints_;
std::map<int32_t, Offset> fingersDistance_;
AxisEvent axisEventStart_;
double axisVerticalTotal_ = 0.0;
double axisHorizontalTotal_ = 0.0;
TimeStamp time_;
TimeStamp touchDownTime_;
bool slidingEnd_ = false;
bool slidingCancel_ = false;
Point globalPoint_;
OnSwipeFingersFunc onChangeFingers_;
OnSwipeDirectionFunc onChangeDirection_;
OnSwipeSpeedFunc onChangeSpeed_;
int32_t newFingers_ = 1;
double angle_ = 0.0;
double initialAngle_ = 0.0;
double currentAngle_ = 0.0;
double resultAngle_ = 0.0;
double resultSpeed_ = 0.0;
double newSpeed_ = 0.0;
SwipeDirection newDirection_;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_RECOGNIZERS_SLIDE_RECOGNIZER_H

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/rotation_gesture.h"
#include "core/components_ng/gestures/recognizers/rotation_recognizer.h"
namespace OHOS::Ace::NG {
RefPtr<GestureRecognizer> RotationGesture::CreateRecognizer()
{
auto rotationRecognizer = AceType::MakeRefPtr<RotationRecognizer>(fingers_, angle_);
if (onActionStartId_) {
rotationRecognizer->SetOnActionStart(*onActionStartId_);
}
if (onActionUpdateId_) {
rotationRecognizer->SetOnActionUpdate(*onActionUpdateId_);
}
if (onActionEndId_) {
rotationRecognizer->SetOnActionEnd(*onActionEndId_);
}
if (onActionCancelId_) {
rotationRecognizer->SetOnActionCancel(*onActionCancelId_);
}
rotationRecognizer->SetPriority(priority_);
rotationRecognizer->SetPriorityMask(gestureMask_);
return rotationRecognizer;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_ROTATION_GESTURE_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_ROTATION_GESTURE_H
#include <functional>
#include <string>
#include <vector>
#include "base/geometry/offset.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class ACE_EXPORT RotationGesture : public Gesture {
DECLARE_ACE_TYPE(RotationGesture, Gesture);
public:
RotationGesture() = default;
RotationGesture(int32_t fingers, double angle) : Gesture(fingers), angle_(angle) {}
~RotationGesture() override = default;
protected:
RefPtr<GestureRecognizer> CreateRecognizer() override;
private:
double angle_ = 1.0;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_ROTATION_GESTURE_H

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/swipe_gesture.h"
#include "base/geometry/dimension.h"
#include "core/components_ng/gestures/recognizers/swipe_recognizer.h"
#include "core/pipeline_ng/pipeline_context.h"
namespace OHOS::Ace::NG {
RefPtr<GestureRecognizer> SwipeGesture::CreateRecognizer()
{
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(context, nullptr);
double speed = context->NormalizeToPx(Dimension(speed_, DimensionUnit::VP));
RefPtr<SwipeRecognizer> swipeRecognizer;
LOGD("AceType::MakeRefPtr<SwipeRecognizer>(fingers_, direction_, speed)");
swipeRecognizer = AceType::MakeRefPtr<SwipeRecognizer>(fingers_, direction_, speed);
if (onActionId_) {
swipeRecognizer->SetOnAction(*onActionId_);
}
swipeRecognizer->SetPriority(priority_);
swipeRecognizer->SetPriorityMask(gestureMask_);
return swipeRecognizer;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_SLIDE_GESTURE_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_SLIDE_GESTURE_H
#include "base/geometry/offset.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class ACE_EXPORT SwipeGesture : public Gesture {
DECLARE_ACE_TYPE(SwipeGesture, Gesture);
public:
SwipeGesture(int32_t fingers, const SwipeDirection& direction, double speed)
{
fingers_ = fingers;
direction_ = direction;
speed_ = speed;
};
~SwipeGesture() override = default;
protected:
RefPtr<GestureRecognizer> CreateRecognizer() override;
private:
SwipeDirection direction_;
double speed_ = 0.0;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_SLIDE_GESTURE_H

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/components_ng/gestures/tap_gesture.h"
#include "core/components_ng/gestures/recognizers/click_recognizer.h"
namespace OHOS::Ace::NG {
RefPtr<GestureRecognizer> TapGesture::CreateRecognizer()
{
auto clickRecognizer = AceType::MakeRefPtr<ClickRecognizer>(fingers_, count_);
if (onActionId_) {
clickRecognizer->SetOnAction(*onActionId_);
}
clickRecognizer->SetPriority(priority_);
clickRecognizer->SetPriorityMask(gestureMask_);
return clickRecognizer;
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_TAP_GESTURE_H
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_TAP_GESTURE_H
#include <functional>
#include <string>
#include <vector>
#include "base/geometry/offset.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "core/components_ng/gestures/gesture_info.h"
namespace OHOS::Ace::NG {
class ACE_EXPORT TapGesture : public Gesture {
DECLARE_ACE_TYPE(TapGesture, Gesture);
public:
TapGesture() = default;
TapGesture(int32_t count, int32_t fingers) : Gesture(fingers), count_(count) {}
~TapGesture() override = default;
protected:
RefPtr<GestureRecognizer> CreateRecognizer() override;
private:
int32_t count_ = 1;
};
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GESTURES_TAP_GESTURE_H

View File

@ -20,20 +20,11 @@
#include "base/thread/cancelable_callback.h"
#include "core/gestures/multi_fingers_recognizer.h"
#include "core/gestures/gesture_info.h"
#include "core/pipeline/pipeline_base.h"
namespace OHOS::Ace {
class ClickInfo : public BaseEventInfo, public TouchLocationInfo {
DECLARE_RELATIONSHIP_OF_CLASSES(ClickInfo, BaseEventInfo, TouchLocationInfo);
public:
explicit ClickInfo(int32_t fingerId) : BaseEventInfo("onClick"), TouchLocationInfo(fingerId) {}
~ClickInfo() override = default;
};
using ClickCallback = std::function<void(const ClickInfo&)>;
class ClickRecognizer : public MultiFingersRecognizer {
DECLARE_ACE_TYPE(ClickRecognizer, MultiFingersRecognizer);

View File

@ -600,6 +600,16 @@ protected:
std::unique_ptr<GestureEventFunc> onActionEndId_;
std::unique_ptr<GestureEventNoParameter> onActionCancelId_;
};
class ClickInfo : public BaseEventInfo, public TouchLocationInfo {
DECLARE_RELATIONSHIP_OF_CLASSES(ClickInfo, BaseEventInfo, TouchLocationInfo);
public:
explicit ClickInfo(int32_t fingerId) : BaseEventInfo("onClick"), TouchLocationInfo(fingerId) {}
~ClickInfo() override = default;
};
using ClickCallback = std::function<void(const ClickInfo&)>;
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_GESTURES_GESTURE_INFO_H

View File

@ -19,6 +19,7 @@
#include <stack>
#include "base/memory/ace_type.h"
#include "core/components_ng/gestures/gesture_group.h"
#include "core/gestures/gesture_group.h"
#include "core/gestures/single_child_gesture.h"
@ -95,10 +96,51 @@ public:
return gesture;
}
void PushGestureNG(const RefPtr<NG::Gesture>& gesture)
{
gestureStackNG_.push(gesture);
}
void PopGestureNG()
{
if (gestureStackNG_.size() <= 1) {
return;
}
auto gesture = gestureStackNG_.top();
gestureStackNG_.pop();
auto gestureGroup = AceType::DynamicCast<NG::GestureGroup>(gestureStackNG_.top());
if (gestureGroup) {
gestureGroup->AddGesture(gesture);
}
}
RefPtr<NG::Gesture> TopGestureNG()
{
if (gestureStackNG_.empty()) {
return nullptr;
}
return gestureStackNG_.top();
}
RefPtr<NG::Gesture> FinishGestureNG()
{
if (gestureStackNG_.empty()) {
return nullptr;
}
auto gesture = gestureStackNG_.top();
gestureStackNG_.pop();
return gesture;
}
private:
GesturePriority priority_ = GesturePriority::Low;
GestureMask gestureMask_ = GestureMask::Normal;
std::stack<RefPtr<Gesture>> gestureStack_;
std::stack<RefPtr<NG::Gesture>> gestureStackNG_;
};
} // namespace OHOS::Ace

View File

@ -116,6 +116,7 @@ ohos_unittest("PipelineContextTest") {
"//foundation/arkui/ace_engine/frameworks/core/components/theme/theme_constants.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components/theme/theme_manager.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components/theme/theme_utils.cpp",
"//foundation/arkui/ace_engine/frameworks/core/components_ng/gestures/gesture_referee.cpp",
"//foundation/arkui/ace_engine/frameworks/core/event/back_end_event_manager.cpp",
"//foundation/arkui/ace_engine/frameworks/core/event/multimodal/multimodal_manager.cpp",
"//foundation/arkui/ace_engine/frameworks/core/event/multimodal/multimodal_scene.cpp",

View File

@ -372,7 +372,6 @@ void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe)
eventManager_->DispatchTouchEvent(lastMoveEvent.value());
}
}
eventManager_->DispatchTouchEvent(scalePoint);
hasIdleTasks_ = true;
window_->RequestFrame();
@ -440,7 +439,6 @@ void PipelineContext::FlushTouchEvents()
touchPoints.emplace_front(scalePoint);
}
}
auto maxSize = touchPoints.size();
for (auto iter = touchPoints.rbegin(); iter != touchPoints.rend(); ++iter) {
maxSize--;