1 /*
2 * Copyright (c) 2021-2022 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
16 #include "window_input_channel.h"
17 #ifdef IMF_ENABLE
18 #include <input_method_controller.h>
19 #endif // IMF_ENABLE
20 #include "window_manager_hilog.h"
21 #include "window_helper.h"
22
23 namespace OHOS {
24 namespace Rosen {
25 namespace {
26 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InputChannel"};
27 }
WindowInputChannel(const sptr<Window> & window)28 WindowInputChannel::WindowInputChannel(const sptr<Window>& window): window_(window), isAvailable_(true)
29 {
30 }
31
~WindowInputChannel()32 WindowInputChannel::~WindowInputChannel()
33 {
34 WLOGI("windowName: %{public}s, windowId: %{public}d", window_->GetWindowName().c_str(), window_->GetWindowId());
35 window_->SetNeedRemoveWindowInputChannel(false);
36 }
37
DispatchKeyEventCallback(std::shared_ptr<MMI::KeyEvent> & keyEvent,bool consumed)38 void WindowInputChannel::DispatchKeyEventCallback(std::shared_ptr<MMI::KeyEvent>& keyEvent, bool consumed)
39 {
40 if (keyEvent == nullptr) {
41 WLOGFW("keyEvent is null");
42 return;
43 }
44
45 if (consumed) {
46 WLOGD("Input method has processed key event, id:%{public}d", keyEvent->GetId());
47 return;
48 }
49
50 if (window_ != nullptr) {
51 WLOGD("dispatch keyEvent to ACE");
52 window_->ConsumeKeyEvent(keyEvent);
53 } else {
54 keyEvent->MarkProcessed();
55 }
56 }
57
HandleKeyEvent(std::shared_ptr<MMI::KeyEvent> & keyEvent)58 __attribute__((no_sanitize("cfi"))) void WindowInputChannel::HandleKeyEvent(
59 std::shared_ptr<MMI::KeyEvent>& keyEvent)
60 {
61 if (keyEvent == nullptr) {
62 WLOGFE("keyEvent is nullptr");
63 return;
64 }
65
66 if (window_ == nullptr) {
67 TLOGE(WmsLogTag::WMS_EVENT, "window_ is nullptr");
68 return;
69 }
70 WLOGFD("Receive key event, Id: %{public}u, keyCode: %{public}d",
71 window_->GetWindowId(), keyEvent->GetKeyCode());
72 if (window_->GetType() == WindowType::WINDOW_TYPE_DIALOG) {
73 if (keyEvent->GetAgentWindowId() != keyEvent->GetTargetWindowId()) {
74 window_->NotifyTouchDialogTarget();
75 keyEvent->MarkProcessed();
76 return;
77 }
78 if (keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_BACK) {
79 if (keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_UP &&
80 window_->IsDialogSessionBackGestureEnabled()) {
81 window_->ConsumeBackEvent();
82 }
83 keyEvent->MarkProcessed();
84 return;
85 }
86 }
87 bool isConsumed = window_->PreNotifyKeyEvent(keyEvent);
88 if (isConsumed) {
89 TLOGI(WmsLogTag::WMS_EVENT, "PreNotifyKeyEvent id:%{public}d isConsumed:%{public}d",
90 keyEvent->GetId(), static_cast<int>(isConsumed));
91 return;
92 }
93 #ifdef IMF_ENABLE
94 bool isKeyboardEvent = IsKeyboardEvent(keyEvent);
95 if (isKeyboardEvent) {
96 WLOGD("Async dispatch keyEvent to input method");
97 auto callback = [weakThis = wptr(this)] (std::shared_ptr<MMI::KeyEvent>& keyEvent, bool consumed) {
98 auto promoteThis = weakThis.promote();
99 if (promoteThis == nullptr) {
100 keyEvent->MarkProcessed();
101 WLOGFW("promoteThis is nullptr");
102 return;
103 }
104 promoteThis->DispatchKeyEventCallback(keyEvent, consumed);
105 };
106 auto ret = MiscServices::InputMethodController::GetInstance()->DispatchKeyEvent(keyEvent, callback);
107 if (ret != 0) {
108 TLOGI(WmsLogTag::WMS_EVENT, "DispatchKeyEvent ret:%{public}d, id:%{public}d", ret, keyEvent->GetId());
109 DispatchKeyEventCallback(keyEvent, false);
110 }
111 return;
112 }
113 #endif // IMF_ENABLE
114 WLOGD("dispatch keyEvent to ACE");
115 window_->ConsumeKeyEvent(keyEvent);
116 }
117
ProcAncoEvent(std::shared_ptr<MMI::PointerEvent> & pointerEvent)118 void WindowInputChannel::ProcAncoEvent(std::shared_ptr<MMI::PointerEvent>& pointerEvent)
119 {
120 auto action = pointerEvent->GetPointerAction();
121 bool isPointDown = ((action == MMI::PointerEvent::POINTER_ACTION_DOWN) ||
122 (action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN));
123 if (!isPointDown) {
124 return;
125 }
126
127 MMI::PointerEvent::PointerItem pointerItem;
128 bool ret = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem);
129 if (!ret) {
130 TLOGE(WmsLogTag::WMS_EVENT, "get item failed, %{public}d", pointerEvent->GetId());
131 return;
132 }
133
134 auto x = pointerItem.GetDisplayX();
135 auto y = pointerItem.GetDisplayY();
136 window_->OnPointDown(pointerEvent->GetId(), x, y);
137 }
138
HandlePointerEvent(std::shared_ptr<MMI::PointerEvent> & pointerEvent)139 void WindowInputChannel::HandlePointerEvent(std::shared_ptr<MMI::PointerEvent>& pointerEvent)
140 {
141 if (pointerEvent == nullptr) {
142 TLOGE(WmsLogTag::WMS_EVENT, "pointerEvent is nullptr");
143 return;
144 }
145 if (window_ == nullptr) {
146 TLOGE(WmsLogTag::WMS_EVENT, "window_ is nullptr, id:%{public}d", pointerEvent->GetId());
147 return;
148 }
149
150 if (window_->IsAnco()) {
151 ProcAncoEvent(pointerEvent);
152 pointerEvent->MarkProcessed();
153 return;
154 }
155
156 auto action = pointerEvent->GetPointerAction();
157 TLOGD(WmsLogTag::WMS_EVENT, "Receive pointer event, Id: %{public}u, action: %{public}d",
158 window_->GetWindowId(), action);
159
160 bool isPointDown = action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
161 action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN;
162 MMI::PointerEvent::PointerItem pointerItem;
163 bool isValidPointItem = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem);
164 if ((window_->GetType() == WindowType::WINDOW_TYPE_DIALOG ||
165 WindowHelper::IsModalSubWindow(window_->GetType(), window_->GetWindowFlags()) ||
166 WindowHelper::IsModalMainWindow(window_->GetType(), window_->GetWindowFlags())) &&
167 pointerEvent->GetAgentWindowId() != pointerEvent->GetTargetWindowId() &&
168 action != MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
169 if (isPointDown && isValidPointItem) {
170 window_->NotifyTouchDialogTarget(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
171 }
172 pointerEvent->MarkProcessed();
173 return;
174 }
175 TLOGD(WmsLogTag::WMS_EVENT, "Dispatch move event, windowId: %{public}u, action: %{public}d",
176 window_->GetWindowId(), action);
177 window_->ConsumePointerEvent(pointerEvent);
178 window_->SetTouchEvent(action);
179 }
180
Destroy()181 void WindowInputChannel::Destroy()
182 {
183 std::lock_guard<std::mutex> lock(mtx_);
184 WLOGI("Destroy WindowInputChannel, windowId:%{public}u", window_->GetWindowId());
185 isAvailable_ = false;
186 }
187
GetWindowRect()188 Rect WindowInputChannel::GetWindowRect()
189 {
190 if (window_ == nullptr) {
191 return { 0, 0, 0, 0 };
192 }
193 return window_->GetRect();
194 }
195
IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent) const196 bool WindowInputChannel::IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent) const
197 {
198 int32_t keyCode = keyEvent->GetKeyCode();
199 bool isKeyFN = (keyCode == MMI::KeyEvent::KEYCODE_FN);
200 bool isKeyBack = (keyCode == MMI::KeyEvent::KEYCODE_BACK);
201 bool isKeyboard = (keyCode >= MMI::KeyEvent::KEYCODE_0 && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_RIGHT_PAREN);
202 bool isKeySound = (keyCode == MMI::KeyEvent::KEYCODE_SOUND);
203 TLOGD(WmsLogTag::WMS_EVENT, "isKeyFN:%{public}d, isKeyboard:%{public}d", isKeyFN, isKeyboard);
204 return (isKeyFN || isKeyboard || isKeyBack || isKeySound);
205 }
206 }
207 }
208