1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "focus_event_handler.h"
16
17 #include "core/components_ng/base/frame_node.h"
18 #include "core/event/focus_axis_event.h"
19 #include "core/pipeline_ng/pipeline_context.h"
20 #include "core/event/key_event.h"
21 #include "core/components_ng/event/event_constants.h"
22 namespace OHOS::Ace::NG {
GetFocusIntension(const NonPointerEvent & event)23 FocusIntension FocusEvent::GetFocusIntension(const NonPointerEvent& event)
24 {
25 if (event.eventType != UIInputEventType::KEY) {
26 return FocusIntension::NONE;
27 }
28 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event);
29 if (keyEvent.isPreIme || keyEvent.action != KeyAction::DOWN) {
30 return FocusIntension::NONE;
31 }
32 if (keyEvent.pressedCodes.size() != 1) {
33 return keyEvent.IsExactlyShiftWith(KeyCode::KEY_TAB) ? FocusIntension::SHIFT_TAB : FocusIntension::NONE;
34 }
35 switch (keyEvent.code) {
36 case KeyCode::KEY_TAB:
37 return FocusIntension::TAB;
38 case KeyCode::KEY_MOVE_HOME:
39 return FocusIntension::HOME;
40 case KeyCode::KEY_MOVE_END:
41 return FocusIntension::END;
42 case KeyCode::KEY_ENTER:
43 case KeyCode::KEY_NUMPAD_ENTER:
44 return FocusIntension::SELECT;
45 case KeyCode::KEY_SPACE:
46 return FocusIntension::SPACE;
47 default:;
48 }
49 switch (keyEvent.keyIntention) {
50 case KeyIntention::INTENTION_UP:
51 return FocusIntension::UP;
52 case KeyIntention::INTENTION_DOWN:
53 return FocusIntension::DOWN;
54 case KeyIntention::INTENTION_LEFT:
55 return FocusIntension::LEFT;
56 case KeyIntention::INTENTION_RIGHT:
57 return FocusIntension::RIGHT;
58 case KeyIntention::INTENTION_SELECT:
59 return FocusIntension::SELECT;
60 case KeyIntention::INTENTION_ESCAPE:
61 return FocusIntension::ESC;
62 case KeyIntention::INTENTION_HOME:
63 return FocusIntension::HOME;
64 default:;
65 return FocusIntension::NONE;
66 }
67 }
68
HasCustomKeyEventDispatch(const FocusEvent & event)69 bool FocusEventHandler::HasCustomKeyEventDispatch(const FocusEvent& event)
70 {
71 if (event.event.eventType != UIInputEventType::KEY) {
72 return false;
73 }
74 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event.event);
75 if (keyEvent.isPreIme) {
76 return false;
77 }
78 return GetOnKeyEventDispatchCallback() != nullptr;
79 }
80
HandleCustomEventDispatch(const FocusEvent & event)81 bool FocusEventHandler::HandleCustomEventDispatch(const FocusEvent& event)
82 {
83 auto onKeyEventDispatchCallback = GetOnKeyEventDispatchCallback();
84 if (onKeyEventDispatchCallback) {
85 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event.event);
86 auto info = KeyEventInfo(keyEvent);
87 return onKeyEventDispatchCallback(info);
88 }
89 return false;
90 }
91
OnFocusEvent(const FocusEvent & event)92 bool FocusEventHandler::OnFocusEvent(const FocusEvent& event)
93 {
94 if (!IsCurrentFocus()) {
95 return false;
96 }
97 if (HasCustomKeyEventDispatch(event)) {
98 return HandleCustomEventDispatch(event);
99 }
100 if (focusType_ == FocusType::SCOPE) {
101 return OnFocusEventScope(event);
102 }
103 if (focusType_ == FocusType::NODE) {
104 return OnFocusEventNode(event);
105 }
106 TAG_LOGW(AceLogTag::ACE_FOCUS, "Current node focus type: %{public}d is invalid.", focusType_);
107 return false;
108 }
109
OnFocusEventScope(const FocusEvent & event)110 bool FocusEventHandler::OnFocusEventScope(const FocusEvent& event)
111 {
112 ACE_DCHECK(IsCurrentFocus());
113 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
114 if (lastFocusNode && lastFocusNode->OnFocusEvent(event)) {
115 TAG_LOGD(AceLogTag::ACE_FOCUS,
116 "OnKeyEvent: Node %{public}s/%{public}d will not handle KeyEvent. "
117 "Because its child %{public}s/%{public}d already has consumed this event.",
118 GetFrameName().c_str(), GetFrameId(), lastFocusNode->GetFrameName().c_str(),
119 lastFocusNode->GetFrameId());
120 return true;
121 }
122 return OnFocusEventNode(event);
123 }
124
OnFocusEventNode(const FocusEvent & focusEvent)125 bool FocusEventHandler::OnFocusEventNode(const FocusEvent& focusEvent)
126 {
127 ACE_DCHECK(IsCurrentFocus());
128
129 bool ret = false;
130 if (focusEvent.event.eventType == UIInputEventType::KEY) {
131 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(focusEvent.event);
132 ret = HandleKeyEvent(keyEvent, focusEvent.intension);
133 }
134 if (focusEvent.event.eventType == UIInputEventType::FOCUS_AXIS) {
135 const FocusAxisEvent& focusAxisEvent = static_cast<const FocusAxisEvent&>(focusEvent.event);
136 return HandleFocusAxisEvent(focusAxisEvent);
137 }
138
139 auto keyProcessingMode = static_cast<KeyProcessingMode>(GetKeyProcessingMode());
140 if (keyProcessingMode == KeyProcessingMode::ANCESTOR_EVENT) {
141 return ret;
142 }
143 return ret ? true : HandleFocusTravel(focusEvent);
144 }
145
GetKeyProcessingMode()146 int32_t FocusEventHandler::GetKeyProcessingMode()
147 {
148 auto frameNode = GetFrameNode();
149 CHECK_NULL_RETURN(frameNode, static_cast<int32_t>(KeyProcessingMode::FOCUS_NAVIGATION));
150 auto context = frameNode->GetContextRefPtr();
151 CHECK_NULL_RETURN(context, static_cast<int32_t>(KeyProcessingMode::FOCUS_NAVIGATION));
152 auto focusManager = context->GetOrCreateFocusManager();
153 CHECK_NULL_RETURN(context, static_cast<int32_t>(KeyProcessingMode::FOCUS_NAVIGATION));
154
155 return static_cast<int32_t>(focusManager->GetKeyProcessingMode());
156 }
157
HandleKeyEvent(const KeyEvent & event,FocusIntension intension)158 bool FocusEventHandler::HandleKeyEvent(const KeyEvent& event, FocusIntension intension)
159 {
160 // ReDispatch event will not be consumed again.
161 if (event.isRedispatch) {
162 return false;
163 }
164
165 auto node = GetFrameNode();
166 CHECK_NULL_RETURN(node, false);
167 auto* pipeline = node->GetContext();
168 CHECK_NULL_RETURN(pipeline, false);
169 auto info = KeyEventInfo(event);
170 if (event.HasKey(KeyCode::KEY_META_LEFT) || event.HasKey(KeyCode::KEY_META_RIGHT)) {
171 info.SetMetaKey(1);
172 }
173 if (event.isPreIme) {
174 return OnKeyPreIme(info, event);
175 }
176
177 bool retInternal = OnKeyEventNodeInternal(event);
178 bool retCallback = OnKeyEventNodeUser(info, event);
179 if (retInternal || retCallback) {
180 return true;
181 }
182 // Handle on click
183 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FOURTEEN) &&
184 !pipeline->GetIsFocusActive()) {
185 return false;
186 }
187 if (intension == FocusIntension::SELECT && !IsTabStop()) {
188 intension = FocusIntension::SPACE;
189 }
190 auto ret = false;
191 if (intension == FocusIntension::SPACE) {
192 ret = OnClick(event);
193 TAG_LOGI(AceLogTag::ACE_FOCUS,
194 "OnClick: Node %{public}s/%{public}d handle KeyEvent(%{private}d, %{public}d) return: %{public}d",
195 GetFrameName().c_str(), GetFrameId(), event.code, event.action, ret);
196 }
197 return ret;
198 }
199
HandleFocusAxisEvent(const FocusAxisEvent & event)200 bool FocusEventHandler::HandleFocusAxisEvent(const FocusAxisEvent& event)
201 {
202 auto node = GetFrameNode();
203 CHECK_NULL_RETURN(node, false);
204 auto* pipeline = node->GetContext();
205 CHECK_NULL_RETURN(pipeline, false);
206 auto onFocusAxisCallback = GetOnFocusAxisCallback();
207 CHECK_NULL_RETURN(onFocusAxisCallback, false);
208 auto info = FocusAxisEventInfo(event);
209 auto eventHub = eventHub_.Upgrade();
210 if (eventHub) {
211 auto targetImpl = eventHub->CreateGetEventTargetImpl();
212 info.SetTarget(targetImpl().value_or(EventTarget()));
213 }
214 onFocusAxisCallback(info);
215 return info.IsStopPropagation();
216 }
217
OnKeyPreIme(KeyEventInfo & info,const KeyEvent & keyEvent)218 bool FocusEventHandler::OnKeyPreIme(KeyEventInfo& info, const KeyEvent& keyEvent)
219 {
220 auto onKeyPreIme = GetOnKeyPreIme();
221 if (onKeyPreIme) {
222 bool retPreIme = onKeyPreIme(info);
223 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
224 auto eventManager = pipeline->GetEventManager();
225 if (eventManager) {
226 eventManager->SetIsKeyConsumed(retPreIme);
227 }
228 return info.IsStopPropagation();
229 } else if (GetFrameName() == V2::UI_EXTENSION_COMPONENT_ETS_TAG) {
230 return ProcessOnKeyEventInternal(keyEvent);
231 } else {
232 return false;
233 }
234 }
235
OnClick(const KeyEvent & event)236 bool FocusEventHandler::OnClick(const KeyEvent& event)
237 {
238 auto onClickCallback = GetOnClickCallback();
239 if (onClickCallback) {
240 auto info = GestureEvent();
241 info.SetTimeStamp(event.timeStamp);
242 auto geometryNode = GetGeometryNode();
243 CHECK_NULL_RETURN(geometryNode, false);
244 auto rect = geometryNode->GetFrameRect();
245 auto centerToWindow = Offset((rect.Left() + rect.Right()) / 2, (rect.Top() + rect.Bottom()) / 2);
246 auto centerToNode = Offset((rect.Right() - rect.Left()) / 2, (rect.Bottom() - rect.Top()) / 2);
247 info.SetGlobalLocation(centerToWindow);
248 info.SetLocalLocation(centerToNode);
249 info.SetSourceDevice(event.sourceType);
250 info.SetDeviceId(event.deviceId);
251 auto node = GetFrameNode();
252 CHECK_NULL_RETURN(node, false);
253 auto pipelineContext = node->GetContextRefPtr();
254 if (pipelineContext) {
255 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset() + centerToWindow;
256 info.SetScreenLocation(windowOffset);
257 }
258 info.SetSourceTool(SourceTool::UNKNOWN);
259 auto eventHub = eventHub_.Upgrade();
260 if (eventHub) {
261 auto targetImpl = eventHub->CreateGetEventTargetImpl();
262 info.SetTarget(targetImpl().value_or(EventTarget()));
263 }
264 onClickCallback(info);
265 return true;
266 }
267 return false;
268 }
269
OnKeyEventNodeInternal(const KeyEvent & keyEvent)270 bool FocusEventHandler::OnKeyEventNodeInternal(const KeyEvent& keyEvent)
271 {
272 auto node = GetFrameNode();
273 CHECK_NULL_RETURN(node, false);
274 auto* pipeline = node->GetContext();
275 CHECK_NULL_RETURN(pipeline, false);
276 bool isBypassInner = keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline && pipeline->IsTabJustTriggerOnKeyEvent();
277 auto retInternal = false;
278 if ((GetFrameName() == V2::UI_EXTENSION_COMPONENT_ETS_TAG || GetFrameName() == V2::ISOLATED_COMPONENT_ETS_TAG)
279 && !IsCurrentFocus()) {
280 isBypassInner = false;
281 }
282 if (!isBypassInner && !onKeyEventsInternal_.empty()) {
283 retInternal = ProcessOnKeyEventInternal(keyEvent);
284 TAG_LOGI(AceLogTag::ACE_FOCUS,
285 "OnKeyEventInteral: Node %{public}s/%{public}d handle KeyEvent("
286 SEC_PLD(%{public}d)", %{public}d) return: %{public}d",
287 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(keyEvent.code), keyEvent.action, retInternal);
288 }
289 return retInternal;
290 }
291
OnKeyEventNodeUser(KeyEventInfo & info,const KeyEvent & keyEvent)292 bool FocusEventHandler::OnKeyEventNodeUser(KeyEventInfo& info, const KeyEvent& keyEvent)
293 {
294 auto node = GetFrameNode();
295 CHECK_NULL_RETURN(node, false);
296 auto* pipeline = node->GetContext();
297 CHECK_NULL_RETURN(pipeline, false);
298 auto retCallback = false;
299 auto onKeyEventCallback = GetOnKeyCallback();
300 if (onKeyEventCallback) {
301 auto result = onKeyEventCallback(info);
302 retCallback = info.IsStopPropagation() || result;
303 auto eventManager = pipeline->GetEventManager();
304 PrintOnKeyEventUserInfo(keyEvent, retCallback);
305 }
306
307 auto onJSFrameNodeKeyCallback = GetJSFrameNodeOnKeyCallback();
308 if (onJSFrameNodeKeyCallback) {
309 onJSFrameNodeKeyCallback(info);
310 retCallback = info.IsStopPropagation();
311 PrintOnKeyEventUserInfo(keyEvent, retCallback);
312 }
313 return retCallback;
314 }
315
PrintOnKeyEventUserInfo(const KeyEvent & keyEvent,bool retCallback)316 void FocusEventHandler::PrintOnKeyEventUserInfo(const KeyEvent& keyEvent, bool retCallback)
317 {
318 TAG_LOGI(AceLogTag::ACE_FOCUS,
319 "OnKeyEventUser: Node %{public}s/%{public}d handle KeyEvent("
320 SEC_PLD(%{public}d) ", %{public}d) return: %{public}d",
321 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(keyEvent.code), keyEvent.action, retCallback);
322 }
323
ProcessOnKeyEventInternal(const KeyEvent & event)324 bool FocusEventHandler::ProcessOnKeyEventInternal(const KeyEvent& event)
325 {
326 bool result = false;
327 for (const auto& onKeyEvent : onKeyEventsInternal_) {
328 auto callback = onKeyEvent.second;
329 if (callback && callback(event)) {
330 result = true;
331 }
332 }
333 return result;
334 }
335 } // namespace OHOS::Ace::NG