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->GetOrCreateEventHub<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 GetFrameName() == V2::DYNAMIC_COMPONENT_ETS_TAG) {
293 TAG_LOGI(AceLogTag::ACE_FOCUS, "node: %{public}s/%{public}d try to process OnKeyEventInternal",
294 GetFrameName().c_str(), GetFrameId());
295 return ProcessOnKeyEventInternal(keyEvent);
296 } else {
297 return false;
298 }
299 }
300
OnClick(const KeyEvent & event)301 bool FocusEventHandler::OnClick(const KeyEvent& event)
302 {
303 auto onClickCallback = GetOnClickCallback();
304 if (onClickCallback) {
305 auto info = GestureEvent();
306 info.SetTimeStamp(event.timeStamp);
307 auto geometryNode = GetGeometryNode();
308 CHECK_NULL_RETURN(geometryNode, false);
309 auto rect = geometryNode->GetFrameRect();
310 auto centerToWindow = Offset((rect.Left() + rect.Right()) / 2, (rect.Top() + rect.Bottom()) / 2);
311 auto centerToNode = Offset((rect.Right() - rect.Left()) / 2, (rect.Bottom() - rect.Top()) / 2);
312 info.SetGlobalLocation(centerToWindow);
313 info.SetLocalLocation(centerToNode);
314 info.SetSourceDevice(event.sourceType);
315 info.SetDeviceId(event.deviceId);
316 info.SetInputEventType(InputEventType::KEYBOARD);
317 auto node = GetFrameNode();
318 CHECK_NULL_RETURN(node, false);
319 auto pipelineContext = node->GetContextRefPtr();
320 if (pipelineContext) {
321 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset() + centerToWindow;
322 auto globalWindowOffset = pipelineContext->GetGlobalDisplayWindowRect().GetOffset() + centerToWindow;
323 info.SetScreenLocation(windowOffset);
324 info.SetGlobalDisplayLocation(globalWindowOffset);
325 }
326 info.SetSourceTool(SourceTool::UNKNOWN);
327 info.SetPatternName(node->GetTag().c_str());
328 auto eventHub = node->GetOrCreateEventHub<EventHub>();
329 if (eventHub) {
330 auto targetImpl = eventHub->CreateGetEventTargetImpl();
331 info.SetTarget(targetImpl().value_or(EventTarget()));
332 }
333 info.SetTargetDisplayId(event.targetDisplayId);
334 onClickCallback(info);
335 return true;
336 }
337 return false;
338 }
339
OnKeyEventNodeInternal(const KeyEvent & keyEvent)340 bool FocusEventHandler::OnKeyEventNodeInternal(const KeyEvent& keyEvent)
341 {
342 auto node = GetFrameNode();
343 CHECK_NULL_RETURN(node, false);
344 auto* pipeline = node->GetContext();
345 CHECK_NULL_RETURN(pipeline, false);
346 bool isBypassInner = keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline && pipeline->IsTabJustTriggerOnKeyEvent();
347 auto retInternal = false;
348 if (isNodeNeedKey_) {
349 retInternal = ProcessOnKeyEventInternal(keyEvent);
350 TAG_LOGI(AceLogTag::ACE_FOCUS,
351 "OnKeyEventInteral Node process self: Node %{public}s/%{public}d"
352 "handle KeyEvent(" SEC_PLD(%{private}d) ", %{public}d) "
353 "return: %{public}d",
354 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(keyEvent.code), keyEvent.action, retInternal);
355 return retInternal;
356 }
357 if (!isBypassInner && !onKeyEventsInternal_.empty()) {
358 retInternal = ProcessOnKeyEventInternal(keyEvent);
359 TAG_LOGI(AceLogTag::ACE_FOCUS,
360 "OnKeyEventInteral: Node %{public}s/%{public}d"
361 "handle KeyEvent(" SEC_PLD(%{private}d) ", %{public}d) "
362 "return: %{public}d",
363 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(keyEvent.code), keyEvent.action, retInternal);
364 }
365 return retInternal;
366 }
367
OnKeyEventNodeUser(KeyEventInfo & info,const KeyEvent & keyEvent)368 bool FocusEventHandler::OnKeyEventNodeUser(KeyEventInfo& info, const KeyEvent& keyEvent)
369 {
370 auto node = GetFrameNode();
371 CHECK_NULL_RETURN(node, false);
372 auto* pipeline = node->GetContext();
373 CHECK_NULL_RETURN(pipeline, false);
374 auto retCallback = false;
375 auto onKeyEventCallback = GetOnKeyCallback();
376 if (onKeyEventCallback) {
377 auto result = onKeyEventCallback(info);
378 retCallback = info.IsStopPropagation() || result;
379 auto eventManager = pipeline->GetEventManager();
380 PrintOnKeyEventUserInfo(keyEvent, retCallback);
381 }
382
383 auto onJSFrameNodeKeyCallback = GetJSFrameNodeOnKeyCallback();
384 if (onJSFrameNodeKeyCallback) {
385 onJSFrameNodeKeyCallback(info);
386 retCallback = info.IsStopPropagation();
387 PrintOnKeyEventUserInfo(keyEvent, retCallback);
388 }
389 return retCallback;
390 }
391
PrintOnKeyEventUserInfo(const KeyEvent & keyEvent,bool retCallback)392 void FocusEventHandler::PrintOnKeyEventUserInfo(const KeyEvent& keyEvent, bool retCallback)
393 {
394 TAG_LOGI(AceLogTag::ACE_FOCUS,
395 "OnKeyEventUser: Node %{public}s/%{public}d"
396 "handle KeyEvent(" SEC_PLD(%{private}d) ", %{public}d) return: %{public}d",
397 GetFrameName().c_str(), GetFrameId(), SEC_PARAM(keyEvent.code), keyEvent.action, retCallback);
398 }
399
ProcessOnKeyEventInternal(const KeyEvent & event)400 bool FocusEventHandler::ProcessOnKeyEventInternal(const KeyEvent& event)
401 {
402 bool result = false;
403 for (const auto& onKeyEvent : onKeyEventsInternal_) {
404 auto callback = onKeyEvent.second;
405 if (callback && callback(event)) {
406 result = true;
407 }
408 }
409 return result;
410 }
411 } // namespace OHOS::Ace::NG