blob: ad639b4ef82ff23928bed695ab5cd298132cc2e7 [file] [log] [blame]
Siarhei Vishniakoua3c8e512022-02-10 19:46:34 -08001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "PreferStylusOverTouchBlocker.h"
18
19#include <android-base/stringprintf.h>
20
21using android::base::StringPrintf;
22
23static const char* toString(bool value) {
24 return value ? "true" : "false";
25}
26
27namespace android {
28
29ftl::StaticVector<NotifyMotionArgs, 2> PreferStylusOverTouchBlocker::processMotion(
30 const NotifyMotionArgs& args) {
31 const bool isStylusEvent = isFromSource(args.source, AINPUT_SOURCE_STYLUS);
32 if (isStylusEvent) {
33 for (size_t i = 0; i < args.pointerCount; i++) {
34 // Make sure we are canceling stylus pointers
35 const int32_t toolType = args.pointerProperties[i].toolType;
36 LOG_ALWAYS_FATAL_IF(toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS &&
37 toolType != AMOTION_EVENT_TOOL_TYPE_ERASER,
38 "The pointer %zu has toolType=%i, but the source is STYLUS. If "
39 "simultaneous touch and stylus is supported, "
40 "'PreferStylusOverTouchBlocker' should be disabled.",
41 i, toolType);
42 }
43 }
44 const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
45 const bool isUpOrCancel =
46 args.action == AMOTION_EVENT_ACTION_UP || args.action == AMOTION_EVENT_ACTION_CANCEL;
47 if (isStylusEvent) {
48 if (isDown) {
49 // Reject all touch while stylus is down
50 mIsStylusDown = true;
51 if (mIsTouchDown && !mCurrentTouchIsCanceled) {
52 // Cancel touch!
53 mCurrentTouchIsCanceled = true;
54 mLastTouchEvent.action = AMOTION_EVENT_ACTION_CANCEL;
55 mLastTouchEvent.flags |= AMOTION_EVENT_FLAG_CANCELED;
56 mLastTouchEvent.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
57 return {mLastTouchEvent, args};
58 }
59 }
60 if (isUpOrCancel) {
61 mIsStylusDown = false;
62 }
63 // Never drop stylus events
64 return {args};
65 }
66
67 const bool isTouchEvent =
68 isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN) && !isStylusEvent;
69 if (isTouchEvent) {
70 if (mIsStylusDown) {
71 mCurrentTouchIsCanceled = true;
72 }
73 // If we already canceled the current gesture, then continue to drop events from it, even if
74 // the stylus has been lifted.
75 if (mCurrentTouchIsCanceled) {
76 if (isUpOrCancel) {
77 mCurrentTouchIsCanceled = false;
78 }
79 return {};
80 }
81
82 // Update state
83 mLastTouchEvent = args;
84 if (isDown) {
85 mIsTouchDown = true;
86 }
87 if (isUpOrCancel) {
88 mIsTouchDown = false;
89 mCurrentTouchIsCanceled = false;
90 }
91 return {args};
92 }
93
94 // Not a touch or stylus event
95 return {args};
96}
97
98std::string PreferStylusOverTouchBlocker::dump() {
99 std::string out;
100 out += StringPrintf("mIsTouchDown: %s\n", toString(mIsTouchDown));
101 out += StringPrintf("mIsStylusDown: %s\n", toString(mIsStylusDown));
102 out += StringPrintf("mLastTouchEvent: %s\n", mLastTouchEvent.dump().c_str());
103 out += StringPrintf("mCurrentTouchIsCanceled: %s\n", toString(mCurrentTouchIsCanceled));
104 return out;
105}
106
107} // namespace android