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/components_ng/event/event_constants.h"
19 #include "core/components/theme/app_theme.h"
20 #include "core/event/focus_axis_event.h"
21 #include "core/event/key_event.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 #include "core/event/crown_event.h"
24 namespace OHOS::Ace::NG {
GetFocusIntension(const NonPointerEvent & event)25 FocusIntension FocusEvent::GetFocusIntension(const NonPointerEvent& event)
26 {
27 if (event.eventType != UIInputEventType::KEY) {
28 return FocusIntension::NONE;
29 }
30 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event);
31 if (keyEvent.isPreIme || keyEvent.action != KeyAction::DOWN) {
32 return FocusIntension::NONE;
33 }
34 // Arrow key event is used to trasfer focus regardless of its pressed keys
35 switch (keyEvent.code) {
36 case KeyCode::KEY_DPAD_UP:
37 return FocusIntension::UP;
38 case KeyCode::KEY_DPAD_DOWN:
39 return FocusIntension::DOWN;
40 case KeyCode::KEY_DPAD_LEFT:
41 return FocusIntension::LEFT;
42 case KeyCode::KEY_DPAD_RIGHT:
43 return FocusIntension::RIGHT;
44 default:;
45 }
46
47 if (keyEvent.pressedCodes.size() != 1) {
48 return keyEvent.IsExactlyShiftWith(KeyCode::KEY_TAB) ? FocusIntension::SHIFT_TAB : FocusIntension::NONE;
49 }
50 switch (keyEvent.code) {
51 case KeyCode::KEY_TAB:
52 return FocusIntension::TAB;
53 case KeyCode::KEY_MOVE_HOME:
54 return FocusIntension::HOME;
55 case KeyCode::KEY_MOVE_END:
56 return FocusIntension::END;
57 case KeyCode::KEY_ENTER:
58 case KeyCode::KEY_NUMPAD_ENTER:
59 return FocusIntension::SELECT;
60 case KeyCode::KEY_SPACE:
61 return FocusIntension::SPACE;
62 default:;
63 }
64 return GetFocusIntensionFromKey(keyEvent.keyIntention);
65 }
66
GetFocusIntensionFromKey(KeyIntention keyIntention)67 FocusIntension FocusEvent::GetFocusIntensionFromKey(KeyIntention keyIntention)
68 {
69 switch (keyIntention) {
70 case KeyIntention::INTENTION_SELECT:
71 return FocusIntension::SELECT;
72 case KeyIntention::INTENTION_ESCAPE:
73 return FocusIntension::ESC;
74 case KeyIntention::INTENTION_HOME:
75 return FocusIntension::HOME;
76 default:;
77 return FocusIntension::NONE;
78 }
79 }
80
HasCustomKeyEventDispatch(const FocusEvent & event)81 bool FocusEventHandler::HasCustomKeyEventDispatch(const FocusEvent& event)
82 {
83 if (event.event.eventType != UIInputEventType::KEY) {
84 return false;
85 }
86 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event.event);
87 if (keyEvent.isPreIme) {
88 return false;
89 }
90 return GetOnKeyEventDispatchCallback() != nullptr;
91 }
92
HandleCustomEventDispatch(const FocusEvent & event)93 bool FocusEventHandler::HandleCustomEventDispatch(const FocusEvent& event)
94 {
95 auto onKeyEventDispatchCallback = GetOnKeyEventDispatchCallback();
96 if (onKeyEventDispatchCallback) {
97 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event.event);
98 auto info = KeyEventInfo(keyEvent);
99 return onKeyEventDispatchCallback(info);
100 }
101 return false;
102 }
103
OnFocusEvent(const FocusEvent & event)104 bool FocusEventHandler::OnFocusEvent(const FocusEvent& event)
105 {
106 if (!IsCurrentFocus()) {
107 TAG_LOGI(AceLogTag::ACE_FOCUS,
108 "node: %{public}s/%{public}d cannot handle key event because is not current focus",
109 GetFrameName().c_str(), GetFrameId());
110 return false;
111 }
112
113 if (HasCustomKeyEventDispatch(event)) {
114 return HandleCustomEventDispatch(event);
115 }
116
117 if (focusType_ == FocusType::SCOPE) {
118 return OnFocusEventScope(event);
119 }
120 if (focusType_ == FocusType::NODE) {
121 return OnFocusEventNode(event);
122 }
123 TAG_LOGW(AceLogTag::ACE_FOCUS, "Current node focus type: %{public}d is invalid.", focusType_);
124 return false;
125 }
126
OnFocusEventScope(const FocusEvent & event)127 bool FocusEventHandler::OnFocusEventScope(const FocusEvent& event)
128 {
129 ACE_DCHECK(IsCurrentFocus());
130 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
131 if (lastFocusNode && lastFocusNode->OnFocusEvent(event)) {
132 TAG_LOGD(AceLogTag::ACE_FOCUS,
133 "OnKeyEvent: Node %{public}s/%{public}d will not handle Event(type:%{private}d). "
134 "Because its child %{public}s/%{public}d already has consumed this event.",
135 GetFrameName().c_str(), GetFrameId(), event.event.eventType, lastFocusNode->GetFrameName().c_str(),
136 lastFocusNode->GetFrameId());
137 return true;
138 }
139 return OnFocusEventNode(event);
140 }
141
OnFocusEventNode(const FocusEvent & focusEvent)142 bool FocusEventHandler::OnFocusEventNode(const FocusEvent& focusEvent)
143 {
144 ACE_DCHECK(IsCurrentFocus());
145
146 bool ret = false;
147 if (focusEvent.event.eventType == UIInputEventType::KEY) {
148 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(focusEvent.event);
149 ret = HandleKeyEvent(keyEvent, focusEvent.intension);
150 }
151 if (focusEvent.event.eventType == UIInputEventType::FOCUS_AXIS) {
152 const FocusAxisEvent& focusAxisEvent = static_cast<const FocusAxisEvent&>(focusEvent.event);
153 return HandleFocusAxisEvent(focusAxisEvent);
154 }
155 if (focusEvent.event.eventType == UIInputEventType::CROWN) {
156 const CrownEvent& crownEvent = static_cast<const CrownEvent&>(focusEvent.event);
157 return HandleCrownEvent(crownEvent);
158 }
159
160 auto keyProcessingMode = static_cast<KeyProcessingMode>(GetKeyProcessingMode());
161 if (keyProcessingMode == KeyProcessingMode::ANCESTOR_EVENT) {
162 return ret;
163 }
164 return ret ? true : HandleFocusTravel(focusEvent);
165 }
166
GetKeyProcessingMode()167 int32_t FocusEventHandler::GetKeyProcessingMode()
168 {
169 auto frameNode = GetFrameNode();
170 CHECK_NULL_RETURN(frameNode, static_cast<int32_t>(KeyProcessingMode::FOCUS_NAVIGATION));
171 auto context = frameNode->GetContextRefPtr();
172 CHECK_NULL_RETURN(context, static_cast<int32_t>(KeyProcessingMode::FOCUS_NAVIGATION));
173 auto focusManager = context->GetOrCreateFocusManager();
174 CHECK_NULL_RETURN(focusManager, static_cast<int32_t>(KeyProcessingMode::FOCUS_NAVIGATION));
175 return static_cast<int32_t>(focusManager->GetKeyProcessingMode());
176 }
177
HandleKeyEvent(const KeyEvent & event,FocusIntension intension)178 bool FocusEventHandler::HandleKeyEvent(const KeyEvent& event, FocusIntension intension)
179 {
180 // ReDispatch event will not be consumed again.
181 if (event.isRedispatch) {
182 return false;
183 }
184
185 auto node = GetFrameNode();
186 CHECK_NULL_RETURN(node, false);
187 auto* pipeline = node->GetContext();
188 CHECK_NULL_RETURN(pipeline, false);
189 auto info = KeyEventInfo(event);
190 if (event.HasKey(KeyCode::KEY_META_LEFT) || event.HasKey(KeyCode::KEY_META_RIGHT)) {
191 info.SetMetaKey(1);
192 }
193 if (event.isPreIme) {
194 return OnKeyPreIme(info, event);
195 }
196
197 bool retInternal = OnKeyEventNodeInternal(event);
198 bool retCallback = OnKeyEventNodeUser(info, event);
199 if (retInternal || retCallback) {
200 return true;
201 }
202 // Handle on click
203 auto appTheme = pipeline->GetTheme<AppTheme>();
204 CHECK_NULL_RETURN(appTheme, false);
205 if (!pipeline->GetIsFocusActive() && (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) ||
206 !appTheme->NeedFocusHandleClick())) {
207 return false;
208 }
209 if (intension == FocusIntension::SELECT && !IsTabStop()) {
210 intension = FocusIntension::SPACE;
211 }
212 auto ret = false;
213 if (intension == FocusIntension::SPACE) {
214 ret = OnClick(event);
215 TAG_LOGI(AceLogTag::ACE_FOCUS,
216 "OnClick: Node %{public}s/%{public}d handle KeyEvent("
217 SEC_PLD(%{private}d) ", %{public}d) return: %{public}d",
218 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(event.code), event.action, ret);
219 }
220 return ret;
221 }
222
HandleFocusAxisEvent(const FocusAxisEvent & event)223 bool FocusEventHandler::HandleFocusAxisEvent(const FocusAxisEvent& event)
224 {
225 auto node = GetFrameNode();
226 CHECK_NULL_RETURN(node, false);
227 auto* pipeline = node->GetContext();
228 CHECK_NULL_RETURN(pipeline, false);
229 auto onFocusAxisCallback = GetOnFocusAxisCallback();
230 CHECK_NULL_RETURN(onFocusAxisCallback, false);
231 auto info = FocusAxisEventInfo(event);
232 auto eventHub = node->GetEventHub<EventHub>();
233 if (eventHub) {
234 auto targetImpl = eventHub->CreateGetEventTargetImpl();
235 info.SetTarget(targetImpl().value_or(EventTarget()));
236 }
237 onFocusAxisCallback(info);
238 return info.IsStopPropagation();
239 }
240
HandleCrownEvent(const CrownEvent & CrownEvent)241 bool FocusEventHandler::HandleCrownEvent(const CrownEvent& CrownEvent)
242 {
243 ACE_DCHECK(IsCurrentFocus());
244 bool retCallback = false;
245 auto onCrownEventCallback = GetOnCrownCallback();
246 if (onCrownEventCallback) {
247 CrownEventInfo crownInfo(CrownEvent);
248 onCrownEventCallback(crownInfo);
249 retCallback = crownInfo.IsStopPropagation();
250 TAG_LOGI(AceLogTag::ACE_FOCUS,
251 "OnCrownEventUser: Node %{public}s/%{public}d handle CrownAction:%{public}d",
252 GetFrameName().c_str(), GetFrameId(), CrownEvent.action);
253 } else {
254 retCallback = ProcessOnCrownEventInternal(CrownEvent);
255 TAG_LOGI(AceLogTag::ACE_FOCUS,
256 "OnCrownEventInternal: Node %{public}s/%{public}d handle CrownAction:%{public}d",
257 GetFrameName().c_str(), GetFrameId(), CrownEvent.action);
258 }
259 return retCallback;
260 }
261
ProcessOnCrownEventInternal(const CrownEvent & event)262 bool FocusEventHandler::ProcessOnCrownEventInternal(const CrownEvent& event)
263 {
264 bool result = false;
265 auto onCrownEventCallbackInternal = GetOnCrownEventInternal();
266 if (onCrownEventCallbackInternal) {
267 onCrownEventCallbackInternal(event);
268 result = true;
269 }
270 return result;
271 }
272
OnKeyPreIme(KeyEventInfo & info,const KeyEvent & keyEvent)273 bool FocusEventHandler::OnKeyPreIme(KeyEventInfo& info, const KeyEvent& keyEvent)
274 {
275 TAG_LOGD(AceLogTag::ACE_FOCUS,
276 "node: %{public}s/%{public}d try to handle OnKeyPreIme by "
277 "code:%{private}d/action:%{public}d/isPreIme:%{public}d",
278 GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, keyEvent.isPreIme);
279 auto onKeyPreIme = GetOnKeyPreIme();
280 if (onKeyPreIme) {
281 bool retPreIme = onKeyPreIme(info);
282 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
283 auto eventManager = pipeline->GetEventManager();
284 if (eventManager) {
285 eventManager->SetIsKeyConsumed(retPreIme);
286 }
287 TAG_LOGI(AceLogTag::ACE_FOCUS, "node: %{public}s/%{public}d handle OnKeyPreIme",
288 GetFrameName().c_str(), GetFrameId());
289 return info.IsStopPropagation();
290 } else if (GetFrameName() == V2::UI_EXTENSION_COMPONENT_ETS_TAG ||
291 GetFrameName() == V2::EMBEDDED_COMPONENT_ETS_TAG) {
292 TAG_LOGI(AceLogTag::ACE_FOCUS, "node: %{public}s/%{public}d try to process OnKeyEventInternal",
293 GetFrameName().c_str(), GetFrameId());
294 return ProcessOnKeyEventInternal(keyEvent);
295 } else {
296 return false;
297 }
298 }
299
OnClick(const KeyEvent & event)300 bool FocusEventHandler::OnClick(const KeyEvent& event)
301 {
302 auto onClickCallback = GetOnClickCallback();
303 if (onClickCallback) {
304 auto info = GestureEvent();
305 info.SetTimeStamp(event.timeStamp);
306 auto geometryNode = GetGeometryNode();
307 CHECK_NULL_RETURN(geometryNode, false);
308 auto rect = geometryNode->GetFrameRect();
309 auto centerToWindow = Offset((rect.Left() + rect.Right()) / 2, (rect.Top() + rect.Bottom()) / 2);
310 auto centerToNode = Offset((rect.Right() - rect.Left()) / 2, (rect.Bottom() - rect.Top()) / 2);
311 info.SetGlobalLocation(centerToWindow);
312 info.SetLocalLocation(centerToNode);
313 info.SetSourceDevice(event.sourceType);
314 info.SetDeviceId(event.deviceId);
315 auto node = GetFrameNode();
316 CHECK_NULL_RETURN(node, false);
317 auto pipelineContext = node->GetContextRefPtr();
318 if (pipelineContext) {
319 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset() + centerToWindow;
320 info.SetScreenLocation(windowOffset);
321 }
322 info.SetSourceTool(SourceTool::UNKNOWN);
323 auto eventHub = node->GetEventHub<EventHub>();
324 if (eventHub) {
325 auto targetImpl = eventHub->CreateGetEventTargetImpl();
326 info.SetTarget(targetImpl().value_or(EventTarget()));
327 }
328 onClickCallback(info);
329 return true;
330 }
331 return false;
332 }
333
OnKeyEventNodeInternal(const KeyEvent & keyEvent)334 bool FocusEventHandler::OnKeyEventNodeInternal(const KeyEvent& keyEvent)
335 {
336 auto node = GetFrameNode();
337 CHECK_NULL_RETURN(node, false);
338 auto* pipeline = node->GetContext();
339 CHECK_NULL_RETURN(pipeline, false);
340 bool isBypassInner = keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline && pipeline->IsTabJustTriggerOnKeyEvent();
341 auto retInternal = false;
342 if (isNodeNeedKey_) {
343 retInternal = ProcessOnKeyEventInternal(keyEvent);
344 TAG_LOGI(AceLogTag::ACE_FOCUS,
345 "OnKeyEventInteral Node process self: Node %{public}s/%{public}d handle KeyEvent(%{private}d, %{public}d) "
346 "return: %{public}d",
347 GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, retInternal);
348 return retInternal;
349 }
350 if (!isBypassInner && !onKeyEventsInternal_.empty()) {
351 retInternal = ProcessOnKeyEventInternal(keyEvent);
352 TAG_LOGI(AceLogTag::ACE_FOCUS,
353 "OnKeyEventInteral Node process self: Node %{public}s/%{public}d"
354 "handle KeyEvent(" SEC_PLD(%{private}d) ", %{public}d) "
355 "return: %{public}d",
356 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(keyEvent.code), keyEvent.action, retInternal);
357 }
358 return retInternal;
359 }
360
OnKeyEventNodeUser(KeyEventInfo & info,const KeyEvent & keyEvent)361 bool FocusEventHandler::OnKeyEventNodeUser(KeyEventInfo& info, const KeyEvent& keyEvent)
362 {
363 auto node = GetFrameNode();
364 CHECK_NULL_RETURN(node, false);
365 auto* pipeline = node->GetContext();
366 CHECK_NULL_RETURN(pipeline, false);
367 auto retCallback = false;
368 auto onKeyEventCallback = GetOnKeyCallback();
369 if (onKeyEventCallback) {
370 auto result = onKeyEventCallback(info);
371 retCallback = info.IsStopPropagation() || result;
372 auto eventManager = pipeline->GetEventManager();
373 PrintOnKeyEventUserInfo(keyEvent, retCallback);
374 }
375
376 auto onJSFrameNodeKeyCallback = GetJSFrameNodeOnKeyCallback();
377 if (onJSFrameNodeKeyCallback) {
378 onJSFrameNodeKeyCallback(info);
379 retCallback = info.IsStopPropagation();
380 PrintOnKeyEventUserInfo(keyEvent, retCallback);
381 }
382 return retCallback;
383 }
384
PrintOnKeyEventUserInfo(const KeyEvent & keyEvent,bool retCallback)385 void FocusEventHandler::PrintOnKeyEventUserInfo(const KeyEvent& keyEvent, bool retCallback)
386 {
387 TAG_LOGI(AceLogTag::ACE_FOCUS,
388 "OnKeyEventUser: Node %{public}s/%{public}d"
389 "handle KeyEvent(" SEC_PLD(%{private}d) ", %{public}d) return: %{public}d",
390 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(keyEvent.code), keyEvent.action, retCallback);
391 }
392
ProcessOnKeyEventInternal(const KeyEvent & event)393 bool FocusEventHandler::ProcessOnKeyEventInternal(const KeyEvent& event)
394 {
395 bool result = false;
396 for (const auto& onKeyEvent : onKeyEventsInternal_) {
397 auto callback = onKeyEvent.second;
398 if (callback && callback(event)) {
399 result = true;
400 }
401 }
402 return result;
403 }
404 } // namespace OHOS::Ace::NG