1 /*
2 * Copyright (C) 2024 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 "ime_event_monitor_manager_impl.h"
17
18 #include <algorithm>
19
20 #include "input_method_controller.h"
21
22 namespace OHOS {
23 namespace MiscServices {
ImeEventMonitorManagerImpl()24 ImeEventMonitorManagerImpl::ImeEventMonitorManagerImpl() { }
25
~ImeEventMonitorManagerImpl()26 ImeEventMonitorManagerImpl::~ImeEventMonitorManagerImpl() { }
27
GetInstance()28 ImeEventMonitorManagerImpl &ImeEventMonitorManagerImpl::GetInstance()
29 {
30 static ImeEventMonitorManagerImpl manager;
31 return manager;
32 }
33
RegisterImeEventListener(uint32_t eventFlag,const std::shared_ptr<ImeEventListener> & listener)34 int32_t ImeEventMonitorManagerImpl::RegisterImeEventListener(
35 uint32_t eventFlag, const std::shared_ptr<ImeEventListener> &listener)
36 {
37 std::lock_guard<std::mutex> lock(lock_);
38 uint32_t currentEventFlag = 0;
39 for (const auto &listenerTemp : listeners_) {
40 currentEventFlag |= listenerTemp.first;
41 }
42 auto finalEventFlag = currentEventFlag | eventFlag;
43 auto ret = InputMethodController::GetInstance()->UpdateListenEventFlag(finalEventFlag, eventFlag, true);
44 if (ret != ErrorCode::NO_ERROR) {
45 IMSA_HILOGE("failed to UpdateListenEventFlag: %{public}d!", ret);
46 return ret;
47 }
48 for (uint32_t i = 0; i < MAX_EVENT_NUM; i++) {
49 auto eventMask = eventFlag & (1u << i);
50 if (eventMask == 0) {
51 continue;
52 }
53 auto it = listeners_.find(eventMask);
54 if (it == listeners_.end()) {
55 listeners_.insert({ eventMask, { listener } });
56 continue;
57 }
58 it->second.insert(listener);
59 }
60 // Register inputStart callback when imf bound, need inputStart callback when register finish
61 if (EventStatusManager::IsInputStatusChangedOn(eventFlag)) {
62 bool isInputStart = false;
63 uint32_t callingWindowId = 0;
64 int32_t requestKeyboardReason = 0;
65 auto ret = InputMethodController::GetInstance()->GetInputStartInfo(isInputStart,
66 callingWindowId, requestKeyboardReason);
67 if (ret == ErrorCode::NO_ERROR && isInputStart && listener != nullptr) {
68 listener->OnInputStart(callingWindowId, requestKeyboardReason);
69 }
70 }
71 return ErrorCode::NO_ERROR;
72 }
73
UnRegisterImeEventListener(uint32_t eventFlag,const std::shared_ptr<ImeEventListener> & listener)74 int32_t ImeEventMonitorManagerImpl::UnRegisterImeEventListener(
75 uint32_t eventFlag, const std::shared_ptr<ImeEventListener> &listener)
76 {
77 std::lock_guard<std::mutex> lock(lock_);
78 bool isAbsentParam = false;
79 for (uint32_t i = 0; i < MAX_EVENT_NUM; i++) {
80 auto eventMask = eventFlag & (1u << i);
81 if (eventMask == 0) {
82 continue;
83 }
84 auto it = listeners_.find(eventMask);
85 if (it == listeners_.end()) {
86 isAbsentParam = true;
87 continue;
88 }
89 auto iter = it->second.find(listener);
90 if (iter == it->second.end()) {
91 isAbsentParam = true;
92 continue;
93 }
94 it->second.erase(iter);
95 if (it->second.empty()) {
96 listeners_.erase(it);
97 }
98 }
99 uint32_t finalEventFlag = 0;
100 for (const auto &listenerTemp : listeners_) {
101 finalEventFlag |= listenerTemp.first;
102 }
103 auto ret = InputMethodController::GetInstance()->UpdateListenEventFlag(finalEventFlag, eventFlag, false);
104 if (ret != ErrorCode::NO_ERROR) {
105 IMSA_HILOGE("failed to UpdateListenEventFlag: %{public}d!", ret);
106 return ret;
107 }
108 return isAbsentParam ? ErrorCode::ERROR_BAD_PARAMETERS : ErrorCode::NO_ERROR;
109 }
110
OnImeChange(const Property & property,const SubProperty & subProperty)111 int32_t ImeEventMonitorManagerImpl::OnImeChange(const Property &property, const SubProperty &subProperty)
112 {
113 auto listeners = GetListeners(EVENT_IME_CHANGE_MASK);
114 for (const auto &listener : listeners) {
115 listener->OnImeChange(property, subProperty);
116 }
117 return ErrorCode::NO_ERROR;
118 }
119
OnPanelStatusChange(const InputWindowStatus & status,const ImeWindowInfo & info)120 int32_t ImeEventMonitorManagerImpl::OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info)
121 {
122 if (status == InputWindowStatus::HIDE) {
123 return OnImeHide(info);
124 }
125 if (status == InputWindowStatus::SHOW) {
126 return OnImeShow(info);
127 }
128 return ErrorCode::ERROR_BAD_PARAMETERS;
129 }
130
OnInputStart(uint32_t callingWndId,int32_t requestKeyboardReason)131 int32_t ImeEventMonitorManagerImpl::OnInputStart(uint32_t callingWndId, int32_t requestKeyboardReason)
132 {
133 isInputStart_ = true;
134 callingWindow_ = callingWndId;
135 requestKeyboardReason_ = requestKeyboardReason;
136 auto listeners = GetListeners(EVENT_INPUT_STATUS_CHANGED_MASK);
137 for (const auto &listener : listeners) {
138 if (listener != nullptr) {
139 IMSA_HILOGD("listener start to callback, callingWndId: %{public}u", callingWndId);
140 listener->OnInputStart(callingWndId, requestKeyboardReason);
141 }
142 }
143 return ErrorCode::NO_ERROR;
144 }
145
OnInputStop()146 int32_t ImeEventMonitorManagerImpl::OnInputStop()
147 {
148 isInputStart_ = false;
149 auto listeners = GetListeners(EVENT_INPUT_STATUS_CHANGED_MASK);
150 for (const auto &listener : listeners) {
151 if (listener != nullptr) {
152 listener->OnInputStop();
153 }
154 }
155 return ErrorCode::NO_ERROR;
156 }
157
OnImeShow(const ImeWindowInfo & info)158 int32_t ImeEventMonitorManagerImpl::OnImeShow(const ImeWindowInfo &info)
159 {
160 auto listeners = GetListeners(EVENT_IME_SHOW_MASK);
161 for (const auto &listener : listeners) {
162 listener->OnImeShow(info);
163 }
164 return ErrorCode::NO_ERROR;
165 }
166
OnImeHide(const ImeWindowInfo & info)167 int32_t ImeEventMonitorManagerImpl::OnImeHide(const ImeWindowInfo &info)
168 {
169 auto listeners = GetListeners(EVENT_IME_HIDE_MASK);
170 for (const auto &listener : listeners) {
171 listener->OnImeHide(info);
172 }
173 return ErrorCode::NO_ERROR;
174 }
175
GetListeners(uint32_t eventMask)176 std::set<std::shared_ptr<ImeEventListener>> ImeEventMonitorManagerImpl::GetListeners(uint32_t eventMask)
177 {
178 std::lock_guard<std::mutex> lock(lock_);
179 auto it = listeners_.find(eventMask);
180 if (it == listeners_.end()) {
181 return {};
182 }
183 return it->second;
184 }
185 } // namespace MiscServices
186 } // namespace OHOS