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