1 /*
2 * Copyright (c) 2022-2023 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 "adapter/preview/entrance/event_dispatcher.h"
17
18 #include <map>
19
20 #include "adapter/preview/entrance/ace_container.h"
21 #include "adapter/preview/entrance/ace_view_preview.h"
22 #include "adapter/preview/entrance/editing/text_input_client_mgr.h"
23 #include "base/log/ace_trace.h"
24 #include "base/log/log.h"
25 #include "core/common/container_scope.h"
26 #include "core/event/key_event.h"
27 #include "core/event/touch_event.h"
28
29 namespace OHOS::Ace::Platform {
30 namespace {
31
32 const wchar_t UPPER_CASE_A = L'A';
33 const wchar_t LOWER_CASE_A = L'a';
34 const wchar_t CASE_0 = L'0';
35 const std::wstring NUM_SYMBOLS = L")!@#$%^&*(";
36 const std::map<MMI::KeyCode, wchar_t> PRINTABEL_SYMBOLS = {
37 { MMI::KeyCode::KEY_GRAVE, L'`' },
38 { MMI::KeyCode::KEY_MINUS, L'-' },
39 { MMI::KeyCode::KEY_EQUALS, L'=' },
40 { MMI::KeyCode::KEY_LEFT_BRACKET, L'[' },
41 { MMI::KeyCode::KEY_RIGHT_BRACKET, L']' },
42 { MMI::KeyCode::KEY_BACKSLASH, L'\\' },
43 { MMI::KeyCode::KEY_SEMICOLON, L';' },
44 { MMI::KeyCode::KEY_APOSTROPHE, L'\'' },
45 { MMI::KeyCode::KEY_COMMA, L',' },
46 { MMI::KeyCode::KEY_PERIOD, L'.' },
47 { MMI::KeyCode::KEY_SLASH, L'/' },
48 { MMI::KeyCode::KEY_SPACE, L' ' },
49 { MMI::KeyCode::KEY_NUMPAD_DIVIDE, L'/' },
50 { MMI::KeyCode::KEY_NUMPAD_MULTIPLY, L'*' },
51 { MMI::KeyCode::KEY_NUMPAD_SUBTRACT, L'-' },
52 { MMI::KeyCode::KEY_NUMPAD_ADD, L'+' },
53 { MMI::KeyCode::KEY_NUMPAD_DOT, L'.' },
54 { MMI::KeyCode::KEY_NUMPAD_COMMA, L',' },
55 { MMI::KeyCode::KEY_NUMPAD_EQUALS, L'=' },
56 };
57
58 const std::map<MMI::KeyCode, wchar_t> SHIFT_PRINTABEL_SYMBOLS = {
59 { MMI::KeyCode::KEY_GRAVE, L'~' },
60 { MMI::KeyCode::KEY_MINUS, L'_' },
61 { MMI::KeyCode::KEY_EQUALS, L'+' },
62 { MMI::KeyCode::KEY_LEFT_BRACKET, L'{' },
63 { MMI::KeyCode::KEY_RIGHT_BRACKET, L'}' },
64 { MMI::KeyCode::KEY_BACKSLASH, L'|' },
65 { MMI::KeyCode::KEY_SEMICOLON, L':' },
66 { MMI::KeyCode::KEY_APOSTROPHE, L'\"' },
67 { MMI::KeyCode::KEY_COMMA, L'<' },
68 { MMI::KeyCode::KEY_PERIOD, L'>' },
69 { MMI::KeyCode::KEY_SLASH, L'?' },
70 };
71
ConvertTouchEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,TouchEvent & event)72 void ConvertTouchEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, TouchEvent& event)
73 {
74 event.id = pointerEvent->id;
75 event.x = pointerEvent->x;
76 event.y = pointerEvent->y;
77 event.screenX = pointerEvent->screenX;
78 event.screenY = pointerEvent->screenY;
79 event.type = static_cast<TouchType>(static_cast<size_t>(pointerEvent->type));
80 event.pullType = static_cast<TouchType>(static_cast<size_t>(pointerEvent->pullType));
81 event.time = pointerEvent->time;
82 event.size = pointerEvent->size;
83 event.force = pointerEvent->force;
84 event.tiltX = pointerEvent->tiltX;
85 event.tiltY = pointerEvent->tiltY;
86 event.deviceId = pointerEvent->deviceId;
87 event.sourceType = static_cast<SourceType>(static_cast<int32_t>(pointerEvent->sourceType));
88 event.sourceTool = static_cast<SourceTool>(static_cast<int32_t>(pointerEvent->sourceTool));
89 event.pointerEvent = pointerEvent;
90 for (auto& item : pointerEvent->pointers) {
91 TouchPoint pointer;
92 pointer.id = item.id;
93 pointer.x = item.x;
94 pointer.y = item.y;
95 pointer.screenX = item.screenX;
96 pointer.screenY = item.screenY;
97 pointer.downTime = item.downTime;
98 pointer.size = item.size;
99 pointer.force = item.force;
100 pointer.tiltX = item.tiltX;
101 pointer.tiltY = item.tiltY;
102 pointer.sourceTool = static_cast<SourceTool>(static_cast<int32_t>(item.sourceTool));
103 pointer.isPressed = item.isPressed;
104 event.pointers.emplace_back(pointer);
105 }
106 }
107
ConvertKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent,KeyEvent & event)108 void ConvertKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent, KeyEvent& event)
109 {
110 event.code = static_cast<KeyCode>(static_cast<int32_t>(keyEvent->code));
111 event.key = keyEvent->key;
112 event.action = static_cast<KeyAction>(static_cast<int32_t>(keyEvent->action));
113 for (auto& item : keyEvent->pressedCodes) {
114 event.pressedCodes.push_back(static_cast<KeyCode>(static_cast<int32_t>(item)));
115 }
116 event.repeatTime = keyEvent->repeatTime;
117 event.timeStamp = keyEvent->timeStamp;
118 event.metaKey = keyEvent->metaKey;
119 event.deviceId = keyEvent->deviceId;
120 event.sourceType = static_cast<SourceType>(static_cast<int32_t>(keyEvent->sourceType));
121 event.rawKeyEvent = keyEvent;
122 event.enableCapsLock = keyEvent->enableCapsLock_;
123 }
124
125 } // namespace
126
GetTouchEventOriginOffset(const TouchEvent & event)127 Offset GetTouchEventOriginOffset(const TouchEvent& event)
128 {
129 if (event.pointerEvent) {
130 for (auto& item : event.pointerEvent->pointers) {
131 return Offset(item.x, item.y);
132 }
133 }
134 return Offset();
135 }
136
EventDispatcher()137 EventDispatcher::EventDispatcher() {}
138
139 EventDispatcher::~EventDispatcher() = default;
140
Initialize()141 void EventDispatcher::Initialize()
142 {
143 LOGI("Initialize event dispatcher");
144 // Initial the proxy of Input method
145 TextInputClientMgr::GetInstance().InitTextInputProxy();
146 // Register the idle event callback function.
147 #ifndef ENABLE_ROSEN_BACKEND
148 IdleCallback idleNoticeCallback = [](int64_t deadline) {
149 EventDispatcher::GetInstance().DispatchIdleEvent(deadline);
150 };
151 FlutterDesktopSetIdleCallback(controller_, idleNoticeCallback);
152 #else
153 // rosen process idle
154 #endif
155 }
156
DispatchIdleEvent(int64_t deadline)157 void EventDispatcher::DispatchIdleEvent(int64_t deadline)
158 {
159 ACE_SCOPED_TRACE("DispatchIdleEvent");
160 auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
161 if (!container) {
162 return;
163 }
164
165 auto aceView = container->GetAceView();
166 if (!aceView) {
167 return;
168 }
169
170 aceView->ProcessIdleEvent(deadline);
171 }
172
GetMouseEventAction(int32_t action,OHOS::Ace::MouseEvent & mouseEvent)173 static void GetMouseEventAction(int32_t action, OHOS::Ace::MouseEvent& mouseEvent)
174 {
175 switch (action) {
176 case OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN:
177 mouseEvent.action = MouseAction::PRESS;
178 break;
179 case OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_UP:
180 mouseEvent.action = MouseAction::RELEASE;
181 break;
182 case OHOS::MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW:
183 mouseEvent.action = MouseAction::WINDOW_ENTER;
184 break;
185 case OHOS::MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW:
186 mouseEvent.action = MouseAction::WINDOW_LEAVE;
187 break;
188 case OHOS::MMI::PointerEvent::POINTER_ACTION_MOVE:
189 mouseEvent.action = MouseAction::MOVE;
190 break;
191 case OHOS::MMI::PointerEvent::POINTER_ACTION_PULL_DOWN:
192 mouseEvent.action = MouseAction::PRESS;
193 break;
194 case OHOS::MMI::PointerEvent::POINTER_ACTION_PULL_MOVE:
195 mouseEvent.action = MouseAction::MOVE;
196 break;
197 case OHOS::MMI::PointerEvent::POINTER_ACTION_PULL_UP:
198 mouseEvent.action = MouseAction::RELEASE;
199 break;
200 default:
201 mouseEvent.action = MouseAction::NONE;
202 break;
203 }
204 }
205
GetMouseEventButton(int32_t button,Ace::MouseEvent & mouseEvent)206 static void GetMouseEventButton(int32_t button, Ace::MouseEvent& mouseEvent)
207 {
208 switch (button) {
209 case MMI::PointerEvent::MOUSE_BUTTON_LEFT:
210 mouseEvent.button = MouseButton::LEFT_BUTTON;
211 break;
212 case MMI::PointerEvent::MOUSE_BUTTON_RIGHT:
213 mouseEvent.button = MouseButton::RIGHT_BUTTON;
214 break;
215 case MMI::PointerEvent::MOUSE_BUTTON_MIDDLE:
216 mouseEvent.button = MouseButton::MIDDLE_BUTTON;
217 break;
218 case MMI::PointerEvent::MOUSE_BUTTON_SIDE:
219 mouseEvent.button = MouseButton::BACK_BUTTON;
220 break;
221 case MMI::PointerEvent::MOUSE_BUTTON_EXTRA:
222 mouseEvent.button = MouseButton::SIDE_BUTTON;
223 break;
224 case MMI::PointerEvent::MOUSE_BUTTON_FORWARD:
225 mouseEvent.button = MouseButton::FORWARD_BUTTON;
226 break;
227 case MMI::PointerEvent::MOUSE_BUTTON_BACK:
228 mouseEvent.button = MouseButton::BACK_BUTTON;
229 break;
230 case MMI::PointerEvent::MOUSE_BUTTON_TASK:
231 mouseEvent.button = MouseButton::TASK_BUTTON;
232 break;
233 default:
234 mouseEvent.button = MouseButton::NONE_BUTTON;
235 break;
236 }
237 }
238
ConvertMouseEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,Ace::MouseEvent & mouseEvent)239 static void ConvertMouseEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, Ace::MouseEvent& mouseEvent)
240 {
241 mouseEvent.id = pointerEvent->id;
242 mouseEvent.x = pointerEvent->x;
243 mouseEvent.y = pointerEvent->y;
244 mouseEvent.screenX = pointerEvent->screenX;
245 mouseEvent.screenY = pointerEvent->screenY;
246 GetMouseEventAction(pointerEvent->pointerAction_, mouseEvent);
247 GetMouseEventButton(pointerEvent->buttonId_, mouseEvent);
248 mouseEvent.sourceType = SourceType::MOUSE;
249 mouseEvent.targetDisplayId = pointerEvent->targetDisplayId_;
250 mouseEvent.deviceId = pointerEvent->deviceId;
251 std::set<int32_t> buttonSet = pointerEvent->pressedButtons_;
252 if (pointerEvent->pressedButtons_.empty()) {
253 pointerEvent->pressedButtons_.insert(pointerEvent->buttonId_);
254 }
255 uint32_t buttons = 0;
256 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_LEFT)) {
257 buttons &= static_cast<uint32_t>(MouseButton::LEFT_BUTTON);
258 }
259 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_RIGHT)) {
260 buttons &= static_cast<uint32_t>(MouseButton::RIGHT_BUTTON);
261 }
262 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_MIDDLE)) {
263 buttons &= static_cast<uint32_t>(MouseButton::MIDDLE_BUTTON);
264 }
265 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_SIDE)) {
266 buttons &= static_cast<uint32_t>(MouseButton::SIDE_BUTTON);
267 }
268 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_EXTRA)) {
269 buttons &= static_cast<uint32_t>(MouseButton::EXTRA_BUTTON);
270 }
271 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_FORWARD)) {
272 buttons &= static_cast<uint32_t>(MouseButton::FORWARD_BUTTON);
273 }
274 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_BACK)) {
275 buttons &= static_cast<uint32_t>(MouseButton::BACK_BUTTON);
276 }
277 if (buttonSet.end() != buttonSet.find(MMI::PointerEvent::MOUSE_BUTTON_TASK)) {
278 buttons &= static_cast<uint32_t>(MouseButton::TASK_BUTTON);
279 }
280 mouseEvent.pressedButtons = static_cast<int32_t>(buttons);
281 }
282
GetAxisEventAction(int32_t action,Ace::AxisEvent & event)283 static void GetAxisEventAction(int32_t action, Ace::AxisEvent& event)
284 {
285 switch (action) {
286 case MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN:
287 event.action = Ace::AxisAction::BEGIN;
288 break;
289 case MMI::PointerEvent::POINTER_ACTION_AXIS_UPDATE:
290 event.action = Ace::AxisAction::UPDATE;
291 break;
292 case MMI::PointerEvent::POINTER_ACTION_AXIS_END:
293 event.action = Ace::AxisAction::END;
294 break;
295 default:
296 event.action = Ace::AxisAction::NONE;
297 break;
298 }
299 }
300
GetAxisValue(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,MMI::PointerEvent::AxisType axis)301 static double GetAxisValue(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, MMI::PointerEvent::AxisType axis)
302 {
303 double axisValue {};
304 if ((axis >= MMI::PointerEvent::AXIS_TYPE_UNKNOWN) && (axis < MMI::PointerEvent::AXIS_TYPE_MAX)) {
305 axisValue = pointerEvent->axisValues_[axis];
306 }
307 return axisValue;
308 }
309
ConvertAxisEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent,Ace::AxisEvent & event)310 static void ConvertAxisEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, Ace::AxisEvent& event)
311 {
312 event.id = pointerEvent->id;
313 event.x = pointerEvent->x;
314 event.y = pointerEvent->y;
315 event.screenX = pointerEvent->screenX;
316 event.screenY = pointerEvent->screenY;
317 event.horizontalAxis = GetAxisValue(pointerEvent, MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_HORIZONTAL);
318 event.verticalAxis = GetAxisValue(pointerEvent, MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_VERTICAL);
319 event.pinchAxisScale = GetAxisValue(pointerEvent, MMI::PointerEvent::AxisType::AXIS_TYPE_PINCH);
320 GetAxisEventAction(pointerEvent->pointerAction_, event);
321 event.sourceType = SourceType::MOUSE;
322 event.sourceTool = SourceTool::MOUSE;
323 event.pointerEvent = pointerEvent;
324 }
325
DispatchTouchEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)326 bool EventDispatcher::DispatchTouchEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
327 {
328 ACE_SCOPED_TRACE("DispatchTouchEvent");
329 auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
330 CHECK_NULL_RETURN(container, false);
331 auto aceView = container->GetAceView();
332 CHECK_NULL_RETURN(aceView, false);
333 if (pointerEvent->sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) {
334 if (pointerEvent->pointerAction_ >= MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN &&
335 pointerEvent->pointerAction_ <= MMI::PointerEvent::POINTER_ACTION_AXIS_END) {
336 OHOS::Ace::AxisEvent axisEvent;
337 ConvertAxisEvent(pointerEvent, axisEvent);
338 return aceView->HandleAxisEvent(axisEvent);
339 } else {
340 OHOS::Ace::MouseEvent mouseEvent;
341 ConvertMouseEvent(pointerEvent, mouseEvent);
342 return aceView->HandleMouseEvent(mouseEvent);
343 }
344 }
345
346 TouchEvent touchEvent;
347 ConvertTouchEvent(pointerEvent, touchEvent);
348 return aceView->HandleTouchEvent(touchEvent);
349 }
350
DispatchBackPressedEvent()351 bool EventDispatcher::DispatchBackPressedEvent()
352 {
353 ACE_SCOPED_TRACE("DispatchBackPressedEvent");
354 auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
355 CHECK_NULL_RETURN(container, false);
356 auto context = container->GetPipelineContext();
357 CHECK_NULL_RETURN(context, false);
358
359 std::promise<bool> backPromise;
360 std::future<bool> backFuture = backPromise.get_future();
361 auto weak = AceType::WeakClaim(AceType::RawPtr(context));
362 container->GetTaskExecutor()->PostTask(
363 [weak, &backPromise]() {
364 auto context = weak.Upgrade();
365 if (context == nullptr) {
366 return;
367 }
368 bool canBack = false;
369 if (!context->IsLastPage()) {
370 canBack = context->CallRouterBackToPopPage();
371 }
372 backPromise.set_value(canBack);
373 },
374 TaskExecutor::TaskType::PLATFORM);
375 return backFuture.get();
376 }
377
DispatchInputMethodEvent(unsigned int codePoint)378 bool EventDispatcher::DispatchInputMethodEvent(unsigned int codePoint)
379 {
380 ACE_SCOPED_TRACE("DispatchInputMethodEvent");
381 return TextInputClientMgr::GetInstance().AddCharacter(static_cast<wchar_t>(codePoint));
382 }
383
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)384 bool EventDispatcher::DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
385 {
386 ACE_SCOPED_TRACE("DispatchKeyEvent");
387 if (HandleTextKeyEvent(keyEvent)) {
388 return true;
389 }
390 auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
391 CHECK_NULL_RETURN(container, false);
392 auto aceView = container->GetAceView();
393 CHECK_NULL_RETURN(aceView, false);
394
395 KeyEvent event;
396 ConvertKeyEvent(keyEvent, event);
397 return aceView->HandleKeyEvent(event);
398 }
399
HandleTextKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)400 bool EventDispatcher::HandleTextKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
401 {
402 // Only the keys involved in the input component are processed here, and the other keys will be forwarded.
403 if (!TextInputClientMgr::GetInstance().IsValidClientId()) {
404 return false;
405 }
406
407 const static size_t maxKeySizes = 2;
408 wchar_t keyChar;
409 if (keyEvent->pressedCodes.size() == 1) {
410 auto iterCode = PRINTABEL_SYMBOLS.find(keyEvent->code);
411 if (iterCode != PRINTABEL_SYMBOLS.end()) {
412 keyChar = iterCode->second;
413 } else if (MMI::KeyCode::KEY_0 <= keyEvent->code && keyEvent->code <= MMI::KeyCode::KEY_9) {
414 keyChar = static_cast<wchar_t>(keyEvent->code) - static_cast<wchar_t>(MMI::KeyCode::KEY_0) + CASE_0;
415 } else if (MMI::KeyCode::KEY_NUMPAD_0 <= keyEvent->code && keyEvent->code <= MMI::KeyCode::KEY_NUMPAD_9) {
416 if (!keyEvent->enableNumLock_) {
417 return true;
418 }
419 keyChar = static_cast<wchar_t>(keyEvent->code) - static_cast<wchar_t>(MMI::KeyCode::KEY_NUMPAD_0) + CASE_0;
420 } else if (MMI::KeyCode::KEY_A <= keyEvent->code && keyEvent->code <= MMI::KeyCode::KEY_Z) {
421 keyChar = static_cast<wchar_t>(keyEvent->code) - static_cast<wchar_t>(MMI::KeyCode::KEY_A);
422 keyChar += (keyEvent->enableCapsLock_ ? UPPER_CASE_A : LOWER_CASE_A);
423 } else {
424 return false;
425 }
426 } else if (keyEvent->pressedCodes.size() == maxKeySizes &&
427 keyEvent->pressedCodes[0] == MMI::KeyCode::KEY_SHIFT_LEFT) {
428 auto iterCode = SHIFT_PRINTABEL_SYMBOLS.find(keyEvent->code);
429 if (iterCode != SHIFT_PRINTABEL_SYMBOLS.end()) {
430 keyChar = iterCode->second;
431 } else if (MMI::KeyCode::KEY_A <= keyEvent->code && keyEvent->code <= MMI::KeyCode::KEY_Z) {
432 keyChar = static_cast<wchar_t>(keyEvent->code) - static_cast<wchar_t>(MMI::KeyCode::KEY_A);
433 keyChar += (keyEvent->enableCapsLock_ ? LOWER_CASE_A : UPPER_CASE_A);
434 } else if (MMI::KeyCode::KEY_0 <= keyEvent->code && keyEvent->code <= MMI::KeyCode::KEY_9) {
435 keyChar = NUM_SYMBOLS[static_cast<int32_t>(keyEvent->code) - static_cast<int32_t>(MMI::KeyCode::KEY_0)];
436 } else {
437 return false;
438 }
439 } else {
440 return false;
441 }
442 if (keyEvent->action != MMI::KeyAction::DOWN) {
443 return true;
444 }
445 return TextInputClientMgr::GetInstance().AddCharacter(keyChar);
446 }
447
448 } // namespace OHOS::Ace::Platform
449