1 /*
2 * Copyright (c) 2023 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 "intention_event_manager.h"
16
17 #ifdef IMF_ENABLE
18 #include <input_method_controller.h>
19 #endif // IMF_ENABLE
20 #include "scene_session.h"
21 #include "session_helper.h"
22 #include "session_manager/include/scene_session_manager.h"
23 #include "window_manager_hilog.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 namespace {
28 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "IntentionEventManager" };
29 std::shared_ptr<MMI::PointerEvent> g_lastMouseEvent = nullptr;
30 int32_t g_lastLeaveWindowId = -1;
31 constexpr int32_t DELAY_TIME = 15;
32
LogPointInfo(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)33 void LogPointInfo(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
34 {
35 if (pointerEvent == nullptr) {
36 return;
37 }
38
39 uint32_t windowId = static_cast<uint32_t>(pointerEvent->GetTargetWindowId());
40 WLOGFD("point source:%{public}d", pointerEvent->GetSourceType());
41 auto actionId = pointerEvent->GetPointerId();
42 int32_t action = pointerEvent->GetPointerAction();
43 if (action == MMI::PointerEvent::POINTER_ACTION_MOVE) {
44 return;
45 }
46
47 MMI::PointerEvent::PointerItem item;
48 if (pointerEvent->GetPointerItem(actionId, item)) {
49 WLOGFI("[WMSEvent] action point info : windowid: %{public}d, id:%{public}d, displayx:%{public}d, "
50 "displayy:%{public}d, windowx:%{public}d, windowy :%{public}d, action :%{public}d pressure: "
51 "%{public}f, tiltx :%{public}f, tiltY :%{public}f",
52 windowId, actionId, item.GetDisplayX(), item.GetDisplayY(), item.GetWindowX(), item.GetWindowY(),
53 pointerEvent->GetPointerAction(), item.GetPressure(), item.GetTiltX(), item.GetTiltY());
54 }
55 auto ids = pointerEvent->GetPointerIds();
56 for (auto&& id :ids) {
57 MMI::PointerEvent::PointerItem item;
58 if (pointerEvent->GetPointerItem(id, item)) {
59 WLOGFD("[WMSEvent] all point info: id: %{public}d, x:%{public}d, y:%{public}d, isPressend:%{public}d, "
60 "pressure:%{public}f, tiltX:%{public}f, tiltY:%{public}f",
61 actionId, item.GetWindowX(), item.GetWindowY(), item.IsPressed(), item.GetPressure(),
62 item.GetTiltX(), item.GetTiltY());
63 }
64 }
65 }
66 } // namespace
67
IntentionEventManager()68 IntentionEventManager::IntentionEventManager() {}
~IntentionEventManager()69 IntentionEventManager::~IntentionEventManager() {}
70
~InputEventListener()71 IntentionEventManager::InputEventListener::~InputEventListener()
72 {
73 std::lock_guard<std::mutex> guard(mouseEventMutex_);
74 g_lastMouseEvent = nullptr;
75 }
76
EnableInputEventListener(Ace::UIContent * uiContent,std::shared_ptr<AppExecFwk::EventHandler> eventHandler)77 bool IntentionEventManager::EnableInputEventListener(Ace::UIContent* uiContent,
78 std::shared_ptr<AppExecFwk::EventHandler> eventHandler)
79 {
80 if (uiContent == nullptr) {
81 WLOGFE("EnableInputEventListener uiContent is null");
82 return false;
83 }
84 if (eventHandler == nullptr) {
85 WLOGFE("EnableInputEventListener eventHandler is null");
86 return false;
87 }
88 auto listener =
89 std::make_shared<IntentionEventManager::InputEventListener>(uiContent, eventHandler);
90 MMI::InputManager::GetInstance()->SetWindowInputEventConsumer(listener, eventHandler);
91 return true;
92 }
93
RegisterWindowChanged()94 void IntentionEventManager::InputEventListener::RegisterWindowChanged()
95 {}
96
ProcessEnterLeaveEventAsync()97 void IntentionEventManager::InputEventListener::ProcessEnterLeaveEventAsync()
98 {
99 auto task = [this]() {
100 std::lock_guard<std::mutex> guard(mouseEventMutex_);
101 if ((g_lastMouseEvent == nullptr) ||
102 (g_lastMouseEvent->GetButtonId() != MMI::PointerEvent::BUTTON_NONE &&
103 g_lastMouseEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_BUTTON_UP)) {
104 return;
105 }
106 auto enterSession = SceneSession::GetEnterWindow().promote();
107 if (enterSession == nullptr) {
108 WLOGFE("Enter session is null, do not reissuing enter leave events");
109 return;
110 }
111 if (g_lastLeaveWindowId == enterSession->GetPersistentId()) {
112 WLOGFI("g_lastLeaveWindowId:%{public}d equal enterSession id",
113 g_lastLeaveWindowId);
114 return;
115 }
116
117 WLOGFD("Reissue enter leave, enter persistentId:%{public}d",
118 enterSession->GetPersistentId());
119 auto leavePointerEvent = std::make_shared<MMI::PointerEvent>(*g_lastMouseEvent);
120 leavePointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW);
121 WSError ret = enterSession->TransferPointerEvent(leavePointerEvent);
122 if (ret != WSError::WS_OK && leavePointerEvent != nullptr) {
123 leavePointerEvent->MarkProcessed();
124 }
125 g_lastLeaveWindowId = enterSession->GetPersistentId();
126
127 auto enterPointerEvent = std::make_shared<MMI::PointerEvent>(*g_lastMouseEvent);
128 if (enterPointerEvent == nullptr) {
129 WLOGFE("The enter pointer event is nullptr");
130 return;
131 }
132 enterPointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW);
133 if (uiContent_ == nullptr) {
134 WLOGFE("ProcessEnterLeaveEventAsync uiContent_ is null");
135 return;
136 }
137 if (!(uiContent_->ProcessPointerEvent(enterPointerEvent))) {
138 WLOGFE("The UI content consumes pointer event failed");
139 enterPointerEvent->MarkProcessed();
140 }
141 };
142 auto eventHandler = weakEventConsumer_.lock();
143 if (eventHandler == nullptr) {
144 WLOGFE("ProcessEnterLeaveEventAsync eventHandler is null");
145 return;
146 }
147 eventHandler->PostTask(std::move(task), "wms:ProcessEventLeaveEventAsync",
148 DELAY_TIME, AppExecFwk::EventQueue::Priority::IMMEDIATE);
149 }
150
UpdateLastMouseEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const151 void IntentionEventManager::InputEventListener::UpdateLastMouseEvent(
152 std::shared_ptr<MMI::PointerEvent> pointerEvent) const
153 {
154 if (pointerEvent == nullptr) {
155 WLOGFE("UpdateLastMouseEvent pointerEvent is null");
156 return;
157 }
158 g_lastLeaveWindowId = -1;
159 if ((pointerEvent->GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_MOUSE) &&
160 (pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW)) {
161 std::lock_guard<std::mutex> guard(mouseEventMutex_);
162 g_lastMouseEvent = std::make_shared<MMI::PointerEvent>(*pointerEvent);
163 } else if (g_lastMouseEvent != nullptr) {
164 WLOGFD("Clear last mouse event");
165 std::lock_guard<std::mutex> guard(mouseEventMutex_);
166 g_lastMouseEvent = nullptr;
167 SceneSession::ClearEnterWindow();
168 }
169 }
170
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const171 void IntentionEventManager::InputEventListener::OnInputEvent(
172 std::shared_ptr<MMI::PointerEvent> pointerEvent) const
173 {
174 if (pointerEvent == nullptr) {
175 WLOGFE("OnInputEvent pointerEvent is null");
176 return;
177 }
178 if (uiContent_ == nullptr) {
179 WLOGFE("OnInputEvent uiContent_ is null");
180 pointerEvent->MarkProcessed();
181 return;
182 }
183 if (!SceneSessionManager::GetInstance().IsInputEventEnabled()) {
184 WLOGFD("OnInputEvent is disabled temporarily");
185 pointerEvent->MarkProcessed();
186 return;
187 }
188
189 LogPointInfo(pointerEvent);
190
191 int32_t action = pointerEvent->GetPointerAction();
192 if (action != MMI::PointerEvent::POINTER_ACTION_MOVE) {
193 WLOGFI("InputTracking id:%{public}d, EventListener OnInputEvent", pointerEvent->GetId());
194 }
195
196 uint32_t windowId = static_cast<uint32_t>(pointerEvent->GetTargetWindowId());
197 auto sceneSession = SceneSessionManager::GetInstance().GetSceneSession(windowId);
198 if (sceneSession == nullptr) {
199 WLOGFE("The scene session is nullptr");
200 pointerEvent->MarkProcessed();
201 return;
202 }
203
204 if (sceneSession->GetSessionInfo().isSystem_) {
205 WLOGI("[WMSEvent] InputEventListener::OnInputEvent id:%{public}d, wid:%{public}u windowName:%{public}s "
206 "action = %{public}d", pointerEvent->GetId(), windowId, sceneSession->GetSessionInfo().abilityName_.c_str(),
207 action);
208 sceneSession->SendPointerEventToUI(pointerEvent);
209
210 // notify touchOutside and touchDown event
211 MMI::PointerEvent::PointerItem pointerItem;
212 if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) {
213 sceneSession->ProcessPointDownSession(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
214 }
215 } else {
216 // transfer pointer event for move and drag
217 WSError ret = sceneSession->TransferPointerEvent(pointerEvent);
218 if (sceneSession->GetWindowType() == WindowType::WINDOW_TYPE_SYSTEM_FLOAT) {
219 sceneSession->NotifyOutsideDownEvent(pointerEvent);
220 }
221 if ((ret != WSError::WS_OK || static_cast<int32_t>(getprocpid()) != sceneSession->GetCallingPid()) &&
222 pointerEvent != nullptr) {
223 pointerEvent->MarkProcessed();
224 }
225 }
226 UpdateLastMouseEvent(pointerEvent);
227 }
228
DispatchKeyEventCallback(int32_t focusedSessionId,std::shared_ptr<MMI::KeyEvent> keyEvent,bool consumed) const229 void IntentionEventManager::InputEventListener::DispatchKeyEventCallback(
230 int32_t focusedSessionId, std::shared_ptr<MMI::KeyEvent> keyEvent, bool consumed) const
231 {
232 if (keyEvent == nullptr) {
233 WLOGFW("keyEvent is null, focusedSessionId:%{public}" PRId32
234 ", consumed:%{public}" PRId32, focusedSessionId, consumed);
235 return;
236 }
237
238 if (consumed) {
239 WLOGD("Input method has processed key event, id:%{public}" PRId32 ", focusedSessionId:%{public}" PRId32,
240 keyEvent->GetId(), focusedSessionId);
241 return;
242 }
243
244 auto focusedSceneSession = SceneSessionManager::GetInstance().GetSceneSession(focusedSessionId);
245 if (focusedSceneSession == nullptr) {
246 WLOGFE("focusedSceneSession is null");
247 keyEvent->MarkProcessed();
248 return;
249 }
250
251 if (uiContent_ == nullptr) {
252 WLOGFE("uiContent_ is null");
253 keyEvent->MarkProcessed();
254 return;
255 }
256
257 focusedSceneSession->SendKeyEventToUI(keyEvent);
258 }
259
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const260 void IntentionEventManager::InputEventListener::OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const
261 {
262 if (keyEvent == nullptr) {
263 WLOGFE("The key event is nullptr");
264 return;
265 }
266 if (!SceneSessionManager::GetInstance().IsInputEventEnabled()) {
267 WLOGFD("OnInputEvent is disabled temporarily");
268 keyEvent->MarkProcessed();
269 return;
270 }
271 auto focusedSessionId = SceneSessionManager::GetInstance().GetFocusedSession();
272 if (focusedSessionId == INVALID_SESSION_ID) {
273 WLOGFE("focusedSessionId is invalid");
274 keyEvent->MarkProcessed();
275 return;
276 }
277 auto focusedSceneSession = SceneSessionManager::GetInstance().GetSceneSession(focusedSessionId);
278 if (focusedSceneSession == nullptr) {
279 WLOGFE("focusedSceneSession is null");
280 keyEvent->MarkProcessed();
281 return;
282 }
283 auto isSystem = focusedSceneSession->GetSessionInfo().isSystem_;
284 WLOGFI("EventListener OnInputEvent InputTracking id:%{public}d, focusedSessionId:%{public}d, isSystem:%{public}d",
285 keyEvent->GetId(), focusedSessionId, isSystem);
286 if (!isSystem) {
287 WSError ret = focusedSceneSession->TransferKeyEvent(keyEvent);
288 if ((ret != WSError::WS_OK || static_cast<int32_t>(getprocpid()) != focusedSceneSession->GetCallingPid()) &&
289 keyEvent != nullptr) {
290 keyEvent->MarkProcessed();
291 }
292 return;
293 }
294 #ifdef IMF_ENABLE
295 bool isKeyboardEvent = IsKeyboardEvent(keyEvent);
296 if (isKeyboardEvent) {
297 WLOGD("Async dispatch keyEvent to input method");
298 auto callback = [this, focusedSessionId] (std::shared_ptr<MMI::KeyEvent>& keyEvent, bool consumed) {
299 this->DispatchKeyEventCallback(focusedSessionId, keyEvent, consumed);
300 };
301 auto ret = MiscServices::InputMethodController::GetInstance()->DispatchKeyEvent(keyEvent, callback);
302 if (ret != 0) {
303 WLOGFE("DispatchKeyEvent failed, ret:%{public}d, id:%{public}d, focusedSessionId:%{public}d",
304 ret, keyEvent->GetId(), focusedSessionId);
305 keyEvent->MarkProcessed();
306 }
307 return;
308 }
309 #endif // IMF_ENABLE
310 WLOGFD("Syetem window scene, transfer key event to root scene");
311 if (uiContent_ == nullptr) {
312 WLOGFE("uiContent_ is null");
313 keyEvent->MarkProcessed();
314 return;
315 }
316 focusedSceneSession->SendKeyEventToUI(keyEvent);
317 }
318
IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent) const319 bool IntentionEventManager::InputEventListener::IsKeyboardEvent(
320 const std::shared_ptr<MMI::KeyEvent>& keyEvent) const
321 {
322 int32_t keyCode = keyEvent->GetKeyCode();
323 bool isKeyFN = (keyCode == MMI::KeyEvent::KEYCODE_FN);
324 bool isKeyBack = (keyCode == MMI::KeyEvent::KEYCODE_BACK);
325 bool isKeyboard = (keyCode >= MMI::KeyEvent::KEYCODE_0 && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_RIGHT_PAREN);
326 WLOGI("isKeyFN: %{public}d, isKeyboard: %{public}d", isKeyFN, isKeyboard);
327 return (isKeyFN || isKeyboard || isKeyBack);
328 }
329
OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const330 void IntentionEventManager::InputEventListener::OnInputEvent(
331 std::shared_ptr<MMI::AxisEvent> axisEvent) const
332 {
333 if (axisEvent == nullptr) {
334 WLOGFE("axisEvent is nullptr");
335 }
336 if (uiContent_ == nullptr) {
337 WLOGFE("uiContent_ is null");
338 axisEvent->MarkProcessed();
339 return;
340 }
341 if (!(uiContent_->ProcessAxisEvent(axisEvent))) {
342 WLOGFI("The UI content consumes the axis event failed.");
343 axisEvent->MarkProcessed();
344 }
345 }
346 }
347 } // namespace OHOS::Rosen
348