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 (pointerEvent->GetAgentWindowId() != pointerEvent->GetTargetWindowId()) &&
130 action != MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
131 if (isPointDown && isValidPointItem) {
132 window_->NotifyTouchDialogTarget(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
133 }
134 pointerEvent->MarkProcessed();
135 return;
136 }
137 TLOGD(WmsLogTag::WMS_EVENT, "Dispatch move event, windowId: %{public}u, action: %{public}d",
138 window_->GetWindowId(), action);
139 window_->ConsumePointerEvent(pointerEvent);
140 }
141
Destroy()142 void WindowInputChannel::Destroy()
143 {
144 std::lock_guard<std::mutex> lock(mtx_);
145 WLOGI("Destroy WindowInputChannel, windowId:%{public}u", window_->GetWindowId());
146 isAvailable_ = false;
147 }
148
GetWindowRect()149 Rect WindowInputChannel::GetWindowRect()
150 {
151 if (window_ == nullptr) {
152 return { 0, 0, 0, 0 };
153 }
154 return window_->GetRect();
155 }
156
IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent) const157 bool WindowInputChannel::IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent) const
158 {
159 int32_t keyCode = keyEvent->GetKeyCode();
160 bool isKeyFN = (keyCode == MMI::KeyEvent::KEYCODE_FN);
161 bool isKeyBack = (keyCode == MMI::KeyEvent::KEYCODE_BACK);
162 bool isKeyboard = (keyCode >= MMI::KeyEvent::KEYCODE_0 && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_RIGHT_PAREN);
163 bool isKeySound = (keyCode == MMI::KeyEvent::KEYCODE_SOUND);
164 TLOGD(WmsLogTag::WMS_EVENT, "isKeyFN:%{public}d, isKeyboard:%{public}d", isKeyFN, isKeyboard);
165 return (isKeyFN || isKeyboard || isKeyBack || isKeySound);
166 }
167 }
168 }
169