1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci
16e0dac50fSopenharmony_ci#include "window_input_channel.h"
17e0dac50fSopenharmony_ci#ifdef IMF_ENABLE
18e0dac50fSopenharmony_ci#include <input_method_controller.h>
19e0dac50fSopenharmony_ci#endif // IMF_ENABLE
20e0dac50fSopenharmony_ci#include "window_manager_hilog.h"
21e0dac50fSopenharmony_ci#include "window_helper.h"
22e0dac50fSopenharmony_ci
23e0dac50fSopenharmony_cinamespace OHOS {
24e0dac50fSopenharmony_cinamespace Rosen {
25e0dac50fSopenharmony_cinamespace {
26e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InputChannel"};
27e0dac50fSopenharmony_ci}
28e0dac50fSopenharmony_ciWindowInputChannel::WindowInputChannel(const sptr<Window>& window): window_(window), isAvailable_(true)
29e0dac50fSopenharmony_ci{
30e0dac50fSopenharmony_ci}
31e0dac50fSopenharmony_ci
32e0dac50fSopenharmony_ciWindowInputChannel::~WindowInputChannel()
33e0dac50fSopenharmony_ci{
34e0dac50fSopenharmony_ci    WLOGI("windowName: %{public}s, windowId: %{public}d", window_->GetWindowName().c_str(), window_->GetWindowId());
35e0dac50fSopenharmony_ci    window_->SetNeedRemoveWindowInputChannel(false);
36e0dac50fSopenharmony_ci}
37e0dac50fSopenharmony_ci
38e0dac50fSopenharmony_civoid WindowInputChannel::DispatchKeyEventCallback(std::shared_ptr<MMI::KeyEvent>& keyEvent, bool consumed)
39e0dac50fSopenharmony_ci{
40e0dac50fSopenharmony_ci    if (keyEvent == nullptr) {
41e0dac50fSopenharmony_ci        WLOGFW("keyEvent is null");
42e0dac50fSopenharmony_ci        return;
43e0dac50fSopenharmony_ci    }
44e0dac50fSopenharmony_ci
45e0dac50fSopenharmony_ci    if (consumed) {
46e0dac50fSopenharmony_ci        WLOGD("Input method has processed key event, id:%{public}d", keyEvent->GetId());
47e0dac50fSopenharmony_ci        return;
48e0dac50fSopenharmony_ci    }
49e0dac50fSopenharmony_ci
50e0dac50fSopenharmony_ci    if (window_ != nullptr) {
51e0dac50fSopenharmony_ci        WLOGD("dispatch keyEvent to ACE");
52e0dac50fSopenharmony_ci        window_->ConsumeKeyEvent(keyEvent);
53e0dac50fSopenharmony_ci    } else {
54e0dac50fSopenharmony_ci        keyEvent->MarkProcessed();
55e0dac50fSopenharmony_ci    }
56e0dac50fSopenharmony_ci}
57e0dac50fSopenharmony_ci
58e0dac50fSopenharmony_ci__attribute__((no_sanitize("cfi"))) void WindowInputChannel::HandleKeyEvent(
59e0dac50fSopenharmony_ci    std::shared_ptr<MMI::KeyEvent>& keyEvent)
60e0dac50fSopenharmony_ci{
61e0dac50fSopenharmony_ci    if (keyEvent == nullptr) {
62e0dac50fSopenharmony_ci        WLOGFE("keyEvent is nullptr");
63e0dac50fSopenharmony_ci        return;
64e0dac50fSopenharmony_ci    }
65e0dac50fSopenharmony_ci    WLOGFD("Receive key event, Id: %{public}u, keyCode: %{public}d",
66e0dac50fSopenharmony_ci        window_->GetWindowId(), keyEvent->GetKeyCode());
67e0dac50fSopenharmony_ci    if (window_->GetType() == WindowType::WINDOW_TYPE_DIALOG) {
68e0dac50fSopenharmony_ci        if (keyEvent->GetAgentWindowId() != keyEvent->GetTargetWindowId()) {
69e0dac50fSopenharmony_ci            window_->NotifyTouchDialogTarget();
70e0dac50fSopenharmony_ci            keyEvent->MarkProcessed();
71e0dac50fSopenharmony_ci            return;
72e0dac50fSopenharmony_ci        }
73e0dac50fSopenharmony_ci        if (keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_BACK) {
74e0dac50fSopenharmony_ci            keyEvent->MarkProcessed();
75e0dac50fSopenharmony_ci            return;
76e0dac50fSopenharmony_ci        }
77e0dac50fSopenharmony_ci    }
78e0dac50fSopenharmony_ci    bool isConsumed = window_->PreNotifyKeyEvent(keyEvent);
79e0dac50fSopenharmony_ci    if (isConsumed) {
80e0dac50fSopenharmony_ci        TLOGI(WmsLogTag::WMS_EVENT, "PreNotifyKeyEvent id:%{public}d isConsumed:%{public}d",
81e0dac50fSopenharmony_ci            keyEvent->GetId(), static_cast<int>(isConsumed));
82e0dac50fSopenharmony_ci        return;
83e0dac50fSopenharmony_ci    }
84e0dac50fSopenharmony_ci#ifdef IMF_ENABLE
85e0dac50fSopenharmony_ci    bool isKeyboardEvent = IsKeyboardEvent(keyEvent);
86e0dac50fSopenharmony_ci    if (isKeyboardEvent) {
87e0dac50fSopenharmony_ci        WLOGD("Async dispatch keyEvent to input method");
88e0dac50fSopenharmony_ci        auto callback = [weakThis = wptr(this)] (std::shared_ptr<MMI::KeyEvent>& keyEvent, bool consumed) {
89e0dac50fSopenharmony_ci            auto promoteThis = weakThis.promote();
90e0dac50fSopenharmony_ci            if (promoteThis == nullptr) {
91e0dac50fSopenharmony_ci                keyEvent->MarkProcessed();
92e0dac50fSopenharmony_ci                WLOGFW("promoteThis is nullptr");
93e0dac50fSopenharmony_ci                return;
94e0dac50fSopenharmony_ci            }
95e0dac50fSopenharmony_ci            promoteThis->DispatchKeyEventCallback(keyEvent, consumed);
96e0dac50fSopenharmony_ci        };
97e0dac50fSopenharmony_ci        auto ret = MiscServices::InputMethodController::GetInstance()->DispatchKeyEvent(keyEvent, callback);
98e0dac50fSopenharmony_ci        if (ret != 0) {
99e0dac50fSopenharmony_ci            WLOGFE("DispatchKeyEvent failed, ret:%{public}d, id:%{public}d", ret, keyEvent->GetId());
100e0dac50fSopenharmony_ci            DispatchKeyEventCallback(keyEvent, false);
101e0dac50fSopenharmony_ci        }
102e0dac50fSopenharmony_ci        return;
103e0dac50fSopenharmony_ci    }
104e0dac50fSopenharmony_ci#endif // IMF_ENABLE
105e0dac50fSopenharmony_ci    WLOGD("dispatch keyEvent to ACE");
106e0dac50fSopenharmony_ci    window_->ConsumeKeyEvent(keyEvent);
107e0dac50fSopenharmony_ci}
108e0dac50fSopenharmony_ci
109e0dac50fSopenharmony_civoid WindowInputChannel::HandlePointerEvent(std::shared_ptr<MMI::PointerEvent>& pointerEvent)
110e0dac50fSopenharmony_ci{
111e0dac50fSopenharmony_ci    if (pointerEvent == nullptr) {
112e0dac50fSopenharmony_ci        TLOGE(WmsLogTag::WMS_EVENT, "pointerEvent is nullptr");
113e0dac50fSopenharmony_ci        return;
114e0dac50fSopenharmony_ci    }
115e0dac50fSopenharmony_ci    if (window_ == nullptr) {
116e0dac50fSopenharmony_ci        TLOGE(WmsLogTag::WMS_EVENT, "window_ is nullptr, id:%{public}d", pointerEvent->GetId());
117e0dac50fSopenharmony_ci        return;
118e0dac50fSopenharmony_ci    }
119e0dac50fSopenharmony_ci    auto action = pointerEvent->GetPointerAction();
120e0dac50fSopenharmony_ci    TLOGD(WmsLogTag::WMS_EVENT, "Receive pointer event, Id: %{public}u, action: %{public}d",
121e0dac50fSopenharmony_ci        window_->GetWindowId(), action);
122e0dac50fSopenharmony_ci
123e0dac50fSopenharmony_ci    bool isPointDown = action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
124e0dac50fSopenharmony_ci        action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN;
125e0dac50fSopenharmony_ci    MMI::PointerEvent::PointerItem pointerItem;
126e0dac50fSopenharmony_ci    bool isValidPointItem = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem);
127e0dac50fSopenharmony_ci    if ((window_->GetType() == WindowType::WINDOW_TYPE_DIALOG ||
128e0dac50fSopenharmony_ci         WindowHelper::IsModalSubWindow(window_->GetType(), window_->GetWindowFlags())) &&
129e0dac50fSopenharmony_ci        (pointerEvent->GetAgentWindowId() != pointerEvent->GetTargetWindowId()) &&
130e0dac50fSopenharmony_ci        action != MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
131e0dac50fSopenharmony_ci        if (isPointDown && isValidPointItem) {
132e0dac50fSopenharmony_ci            window_->NotifyTouchDialogTarget(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
133e0dac50fSopenharmony_ci        }
134e0dac50fSopenharmony_ci        pointerEvent->MarkProcessed();
135e0dac50fSopenharmony_ci        return;
136e0dac50fSopenharmony_ci    }
137e0dac50fSopenharmony_ci    TLOGD(WmsLogTag::WMS_EVENT, "Dispatch move event, windowId: %{public}u, action: %{public}d",
138e0dac50fSopenharmony_ci        window_->GetWindowId(), action);
139e0dac50fSopenharmony_ci    window_->ConsumePointerEvent(pointerEvent);
140e0dac50fSopenharmony_ci}
141e0dac50fSopenharmony_ci
142e0dac50fSopenharmony_civoid WindowInputChannel::Destroy()
143e0dac50fSopenharmony_ci{
144e0dac50fSopenharmony_ci    std::lock_guard<std::mutex> lock(mtx_);
145e0dac50fSopenharmony_ci    WLOGI("Destroy WindowInputChannel, windowId:%{public}u", window_->GetWindowId());
146e0dac50fSopenharmony_ci    isAvailable_ = false;
147e0dac50fSopenharmony_ci}
148e0dac50fSopenharmony_ci
149e0dac50fSopenharmony_ciRect WindowInputChannel::GetWindowRect()
150e0dac50fSopenharmony_ci{
151e0dac50fSopenharmony_ci    if (window_ == nullptr) {
152e0dac50fSopenharmony_ci        return { 0, 0, 0, 0 };
153e0dac50fSopenharmony_ci    }
154e0dac50fSopenharmony_ci    return window_->GetRect();
155e0dac50fSopenharmony_ci}
156e0dac50fSopenharmony_ci
157e0dac50fSopenharmony_cibool WindowInputChannel::IsKeyboardEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent) const
158e0dac50fSopenharmony_ci{
159e0dac50fSopenharmony_ci    int32_t keyCode = keyEvent->GetKeyCode();
160e0dac50fSopenharmony_ci    bool isKeyFN = (keyCode == MMI::KeyEvent::KEYCODE_FN);
161e0dac50fSopenharmony_ci    bool isKeyBack = (keyCode == MMI::KeyEvent::KEYCODE_BACK);
162e0dac50fSopenharmony_ci    bool isKeyboard = (keyCode >= MMI::KeyEvent::KEYCODE_0 && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_RIGHT_PAREN);
163e0dac50fSopenharmony_ci    bool isKeySound = (keyCode == MMI::KeyEvent::KEYCODE_SOUND);
164e0dac50fSopenharmony_ci    TLOGD(WmsLogTag::WMS_EVENT, "isKeyFN:%{public}d, isKeyboard:%{public}d", isKeyFN, isKeyboard);
165e0dac50fSopenharmony_ci    return (isKeyFN || isKeyboard || isKeyBack || isKeySound);
166e0dac50fSopenharmony_ci}
167e0dac50fSopenharmony_ci}
168e0dac50fSopenharmony_ci}
169