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 WLOGFD("Receive key event, Id: %{public}u, keyCode: %{public}d",
66 window_->GetWindowId(), keyEvent->GetKeyCode());
67 if (window_->GetType() == WindowType::WINDOW_TYPE_DIALOG) {
68 if (keyEvent->GetAgentWindowId() != keyEvent->GetTargetWindowId()) {
69 window_->NotifyTouchDialogTarget();
70 keyEvent->MarkProcessed();
71 return;
72 }
73 if (keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_BACK) {
74 keyEvent->MarkProcessed();
75 return;
76 }
77 }
78 bool isConsumed = window_->PreNotifyKeyEvent(keyEvent);
79 if (isConsumed) {
80 TLOGI(WmsLogTag::WMS_EVENT, "PreNotifyKeyEvent id:%{public}d isConsumed:%{public}d",
81 keyEvent->GetId(), static_cast<int>(isConsumed));
82 return;
83 }
84 #ifdef IMF_ENABLE
85 bool isKeyboardEvent = IsKeyboardEvent(keyEvent);
86 if (isKeyboardEvent) {
87 WLOGD("Async dispatch keyEvent to input method");
88 auto callback = [weakThis = wptr(this)] (std::shared_ptr<MMI::KeyEvent>& keyEvent, bool consumed) {
89 auto promoteThis = weakThis.promote();
90 if (promoteThis == nullptr) {
91 keyEvent->MarkProcessed();
92 WLOGFW("promoteThis is nullptr");
93 return;
94 }
95 promoteThis->DispatchKeyEventCallback(keyEvent, consumed);
96 };
97 auto ret = MiscServices::InputMethodController::GetInstance()->DispatchKeyEvent(keyEvent, callback);
98 if (ret != 0) {
99 WLOGFE("DispatchKeyEvent failed, ret:%{public}d, id:%{public}d", ret, keyEvent->GetId());
100 DispatchKeyEventCallback(keyEvent, false);
101 }
102 return;
103 }
104 #endif // IMF_ENABLE
105 WLOGD("dispatch keyEvent to ACE");
106 window_->ConsumeKeyEvent(keyEvent);
107 }
108
HandlePointerEvent(std::shared_ptr<MMI::PointerEvent> & pointerEvent)109 void WindowInputChannel::HandlePointerEvent(std::shared_ptr<MMI::PointerEvent>& pointerEvent)
110 {
111 if (pointerEvent == nullptr) {
112 TLOGE(WmsLogTag::WMS_EVENT, "pointerEvent is nullptr");
113 return;
114 }
115 if (window_ == nullptr) {
116 TLOGE(WmsLogTag::WMS_EVENT, "window_ is nullptr, id:%{public}d", pointerEvent->GetId());
117 return;
118 }
119 auto action = pointerEvent->GetPointerAction();
120 TLOGD(WmsLogTag::WMS_EVENT, "Receive pointer event, Id: %{public}u, action: %{public}d",
121 window_->GetWindowId(), action);
122
123 bool isPointDown = action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
124 action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN;
125 MMI::PointerEvent::PointerItem pointerItem;
126 bool isValidPointItem = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem);
127 if ((window_->GetType() == WindowType::WINDOW_TYPE_DIALOG ||
128 WindowHelper::IsModalSubWindow(window_->GetType(), window_->GetWindowFlags()) ||
129 WindowHelper::IsModalMainWindow(window_->GetType(), window_->GetWindowFlags())) &&
130 pointerEvent->GetAgentWindowId() != pointerEvent->GetTargetWindowId() &&
131 action != MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
132 if (isPointDown && isValidPointItem) {
133 window_->NotifyTouchDialogTarget(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
134 }
135 pointerEvent->MarkProcessed();
136 return;
137 }
138 TLOGD(WmsLogTag::WMS_EVENT, "Dispatch move event, windowId: %{public}u, action: %{public}d",
139 window_->GetWindowId(), action);
140 window_->ConsumePointerEvent(pointerEvent);
141 }
142
Destroy()143 void WindowInputChannel::Destroy()
144 {
145 std::lock_guard<std::mutex> lock(mtx_);
146 WLOGI("Destroy WindowInputChannel, windowId:%{public}u", window_->GetWindowId());
147 isAvailable_ = false;
148 }
149
GetWindowRect()150 Rect WindowInputChannel::GetWindowRect()
151 {
152 if (window_ == nullptr) {
153 return { 0, 0, 0, 0 };
154 }
155 return window_->GetRect();
156 }
157
IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent) const158 bool WindowInputChannel::IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent) const
159 {
160 int32_t keyCode = keyEvent->GetKeyCode();
161 bool isKeyFN = (keyCode == MMI::KeyEvent::KEYCODE_FN);
162 bool isKeyBack = (keyCode == MMI::KeyEvent::KEYCODE_BACK);
163 bool isKeyboard = (keyCode >= MMI::KeyEvent::KEYCODE_0 && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_RIGHT_PAREN);
164 bool isKeySound = (keyCode == MMI::KeyEvent::KEYCODE_SOUND);
165 WLOGI("isKeyFN: %{public}d, isKeyboard: %{public}d", isKeyFN, isKeyboard);
166 return (isKeyFN || isKeyboard || isKeyBack || isKeySound);
167 }
168 }
169 }
170