• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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