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