• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用WindowManager管理多模输入事件(C/C++)
2<!--Kit: ArkUI-->
3<!--Subsystem: Window-->
4<!--Owner: @waterwin-->
5<!--Designer: @stupidb-->
6<!--Tester: @qinliwen0417-->
7<!--Adviser: @ge-yafang-->
8
9## 场景介绍
10
11[WindowManager](../reference/apis-arkui/capi-windowmanager.md)提供应用窗口的管理能力,可以用于管理多模输入事件。
12
13当前支持使用WindowManager进行多模输入事件的过滤,还可以将多模触摸事件注入目标窗口,具体开发步骤可见下文。
14
15## 过滤多模输入事件
16
17使用WindowManager模块提供的能力去拦截按键事件,让按键事件不往应用内部组件分发。
18
19### 在CMake脚本中链接动态库
20```
21target_link_libraries(entry PUBLIC libnative_window_manager.so libohinput.so)
22```
23
24### 添加头文件
25```c++
26#include "multimodalinput/oh_input_manager.h"
27#include "multimodalinput/oh_key_code.h"
28#include "window_manager/oh_window_comm.h"
29#include "window_manager/oh_window_event_filter.h"
30```
31
32### 接口使用说明
33
34| 接口名                                                       | 描述                                         |
35| ------------------------------------------------------------ | -------------------------------------------- |
36| OH_NativeWindowManager_RegisterKeyEventFilter (int32_t windowId, OH_NativeWindowManager_KeyEventFilter keyEventFilter) | 为指定的窗口注册过滤回调函数keyEventFilter。 |
37| OH_NativeWindowManager_UnregisterKeyEventFilter(int32_t windowId) | 取消指定窗口上的过滤回调函数。               |
38
39- 应用窗口创建后,使用窗口ID绑定按键事件过滤函数。
40- 应用窗口需要收到按键事件时,才触发按键事件的拦截。
41- 当回调函数返回true表示拦截,false表示不拦截。
42- 同一个窗口ID注册的回调函数只允许一个,最后注册的回调函数会覆盖之前注册过的回调函数。如需过滤多个按键的组合场景,建议在一个回调函数里面处理。
43
44### 示例代码
45
46以下示例代码中介绍了如何注册过滤函数和取消过滤函数,以过滤ESC退出按键和数字按键为例。
47```c++
48#include "napi/native_api.h"
49#include "window_manager/oh_window_comm.h"
50#include "window_manager/oh_window_event_filter.h"
51#include "multimodalinput/oh_input_manager.h"
52#include "multimodalinput/oh_key_code.h"
53
54// 设置过滤函数
55static bool filterFunc(Input_KeyEvent *event) {
56  auto keyCode = OH_Input_GetKeyEventKeyCode(event);
57  auto action = OH_Input_GetKeyEventAction(event);
58  // case1: 过滤escape
59  // return keyCode == Input_KeyCode::KEYCODE_ESCAPE;
60
61  // case2: 过滤数字键的按下,抬起不过滤
62  // return keyCode >= Input_KeyCode::KEYCODE_0 && keyCode <= Input_KeyCode::KEYCODE_9
63  //  && action == Input_KeyEventAction::KEY_ACTION_DOWN;
64
65  // 过滤escape和数字键的按下(case1 || case2)
66  return (keyCode >= Input_KeyCode::KEYCODE_0 && keyCode <= Input_KeyCode::KEYCODE_9
67     && action == Input_KeyEventAction::KEY_ACTION_DOWN) || (keyCode == Input_KeyCode::KEYCODE_ESCAPE);
68}
69
70static napi_value registerFilter(napi_env env, napi_callback_info info) {
71  size_t argc = 1;
72  napi_value args[1] = {nullptr};
73  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
74
75  int32_t windowId;
76  napi_get_value_int32(env, args[0], &windowId);
77
78  // 向windowId对应的窗口注册filterFunc的过滤函数
79  auto res = OH_NativeWindowManager_RegisterKeyEventFilter(windowId, filterFunc);
80
81  napi_value errCode;
82  napi_create_int32(env, res, &errCode);
83  return errCode;
84}
85
86static napi_value clearFilter(napi_env env, napi_callback_info info) {
87  size_t argc = 1;
88  napi_value args[1] = {nullptr};
89  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
90
91  int32_t windowId;
92  napi_get_value_int32(env, args[0], &windowId);
93
94  auto res = OH_NativeWindowManager_UnregisterKeyEventFilter(windowId);
95  napi_value errCode;
96  napi_create_int32(env, res, &errCode);
97  return errCode;
98
99}
100
101EXTERN_C_START
102static napi_value Init(napi_env env, napi_value exports) {
103  napi_property_descriptor desc[] = {
104    {"registerFilter", nullptr, registerFilter, nullptr, nullptr, nullptr, napi_default, nullptr},
105    {"clearFilter", nullptr, clearFilter, nullptr, nullptr, nullptr, napi_default, nullptr}};
106  napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
107  return exports;
108}
109EXTERN_C_END
110```
111
112## 将多模触摸事件注入给目标窗口
113
114使用WindowManager模块提供的能力为指定窗口注入触摸事件,仅支持同进程窗口。此操作不会触发窗口焦点、层级变化或拖拽,事件会直接发送给ArkUI。
115
116
117### 在CMake脚本中链接动态库
118
119```
120target_link_libraries(entry PUBLIC libnative_window_manager.so libohinput.so)
121```
122
123### 添加头文件
124
125```c++
126#include "multimodalinput/oh_input_manager.h"
127#include "window_manager/oh_window.h"
128#include "napi/native_api.h"
129```
130
131### 接口使用说明
132
133| 接口名                                                       | 描述                       |
134| ------------------------------------------------------------ | -------------------------- |
135| OH_WindowManager_InjectTouchEvent(int32_t windowId, Input_TouchEvent* touchEvent, int32_t windowX, int32_t windowY) | 为指定的窗口注入触摸事件。 |
136
137- 构造事件参数,向目标窗口ID注入事件。
138
139- 仅支持注入同进程窗口。注入不会触发窗口焦点、层级变化或拖拽,事件直接发送给ArkUI。
140
141- 接口需要在指定窗口加载UI后调用。
142
143- 完成窗口和多模触摸事件校验,确保事件参数正确,再将事件发送给ArkUI。具体参数说明如下:
144
145  | 参数名     | 描述                                                         |
146  | ---------- | ------------------------------------------------------------ |
147  | windowId   | 目标窗口ID,仅支持同进程的窗口,否则返回错误码1300002。窗口需完成UI加载,否则返回错误码1300003。 |
148  | touchEvent | 多模触摸事件,具体可见[Input_TouchEvent](../reference/apis-input-kit/capi-input-input-touchevent.md),事件定义在oh_input_manager.h中。调用[OH_Input_CreateTouchEvent](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_createtouchevent)接口创建touchEvent对象,使用完后调用[OH_Input_DestroyTouchEvent](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_destroytouchevent)接口销毁该对象。具体参数说明见下表。 |
149  | windowX    | 注入事件相对于注入窗口的落点横坐标。参数应为大于等于0的整数,否则返回错误码1300003。 |
150  | windowY    | 注入事件相对于注入窗口的落点纵坐标。参数应为大于等于0的整数,否则返回错误码1300003。 |
151
152  其中,touchEvent多模触摸事件具体参数说明如下:
153
154  | 参数名     | 方法                                                         | 描述                                                         |
155  | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
156  | action     | [OH_Input_SetTouchEventAction](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_settoucheventaction) | 表示事件行为,默认值为0。<br>当前只支持0-3的行为,分别表示为:<br>- 0:cancel,表示取消事件。<br>- 1:down,表示按下事件。<br/>- 2:move,表示移动事件。<br/>- 3:up,表示抬起事件。<br/>- 其他行为会返回错误码1300003。 |
157  | id         | [OH_Input_SetTouchEventFingerId](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_settoucheventfingerid) | 表示手指ID,默认值为0。<br>应为大于等于0的整数,否则返回错误码1300003。 |
158  | displayX   | [OH_Input_SetTouchEventDisplayX](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_settoucheventdisplayx) | 表示事件落点相对于屏幕的横坐标,默认值为0。<br>参数应为非负整数,否则返回错误码1300003。建议与windowX保持对应关系,即使不一致也不会返回错误码,仅校验入参合法范围。转换方法推荐使用[getWindowProperties()](../reference/apis-arkui/arkts-apis-window-Window.md#getwindowproperties9)方法获取windowRect属性,通过displayX减去windowRect中窗口左上角横坐标计算对应的windowX。 |
159  | displayY   | [OH_Input_SetTouchEventDisplayY](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_settoucheventdisplayy) | 表示事件落点相对于屏幕的纵坐标,默认值为0。<br/>参数应为非负整数,否则返回错误码1300003。建议与windowY保持对应关系,即使不一致也不会返回错误码,仅校验入参合法范围。转换方法推荐使用[getWindowProperties()](../reference/apis-arkui/arkts-apis-window-Window.md#getwindowproperties9)方法获取windowRect属性,通过displayY减去windowRect中窗口左上角横坐标计算对应的windowY。 |
160  | actionTime | [OH_Input_SetTouchEventActionTime](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_settoucheventactiontime) | 表示时间戳,默认值为-1。参数应为非负整数,否则返回错误码1300003。 |
161  | windowId   | [OH_Input_SetTouchEventWindowId](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_settoucheventwindowid) | 表示事件注入窗口ID,默认值为-1。若参数不为默认值且不等于[OH_WindowManager_InjectTouchEvent](../reference/apis-arkui/capi-oh-window-h.md#oh_windowmanager_injecttouchevent)接口参数windowId,将校验传入参数错误。 |
162  | displayId  | [OH_Input_SetTouchEventDisplayId](../reference/apis-input-kit/capi-oh-input-manager-h.md#oh_input_settoucheventdisplayid) | 表示事件注入屏幕ID,默认值为-1。无限制,但是应该尽量保证与[OH_WindowManager_InjectTouchEvent](../reference/apis-arkui/capi-oh-window-h.md#oh_windowmanager_injecttouchevent)接口参数windowId有相互对应关系,推荐使用[getWindowProperties()](../reference/apis-arkui/arkts-apis-window-Window.md#getwindowproperties9)方法获取displayId属性。 |
163
164### 示例代码
165
166以下示例代码介绍了如何将多模触摸事件注入目标窗口,以单次事件注入为例。
167
168```c++
169#include "window_manager/oh_window.h"
170#include "multimodalinput/oh_input_manager.h"
171#include "napi/native_api.h"
172
173static napi_value injectEvent(napi_env env, napi_callback_info info) {
174  size_t argc = 1;
175  napi_value args[10] = {nullptr};
176  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
177
178  int32_t windowId;
179  napi_get_value_int32(env, args[0], &windowId);
180
181  int32_t displayId;
182  napi_get_value_int32(env, args[1], &displayId);
183
184  int32_t windowX;
185  napi_get_value_int32(env, args[2], &windowX);
186
187  int32_t windowY;
188  napi_get_value_int32(env, args[3], &windowY);
189
190  int32_t action;
191  napi_get_value_int32(env, args[4], &action);
192
193  int32_t fingerId;
194  napi_get_value_int32(env, args[5], &fingerId);
195
196  int32_t displayX;
197  napi_get_value_int32(env, args[6], &displayX);
198
199  int32_t displayY;
200  napi_get_value_int32(env, args[7], &displayY);
201
202  int32_t actionTime;
203  napi_get_value_int32(env, args[8], &actionTime);
204
205  int32_t TE_WindowId;
206  napi_get_value_int32(env, args[9], &TE_WindowId);
207
208  // 构造多模事件touchEvent
209  Input_TouchEvent* touchEvent = OH_Input_CreateTouchEvent();
210  OH_Input_SetTouchEventAction(touchEvent, action);
211  OH_Input_SetTouchEventFingerId(touchEvent, fingerId);
212  OH_Input_SetTouchEventDisplayX(touchEvent, displayX);
213  OH_Input_SetTouchEventDisplayY(touchEvent, displayY);
214  OH_Input_SetTouchEventActionTime(touchEvent, actionTime);
215  OH_Input_SetTouchEventWindowId(touchEvent, TE_WindowId);
216  OH_Input_SetTouchEventDisplayId(touchEvent, displayId);
217
218  // 向windowId对应的窗口注入多模触摸事件
219  auto res = OH_WindowManager_InjectTouchEvent(windowId, touchEvent, windowX, windowY);
220
221  // 使用完touchEvent后销毁对象
222  OH_Input_DestroyTouchEvent(&touchEvent);
223
224  napi_value errCode;
225  napi_create_int32(env, res, &errCode);
226  return errCode;
227}
228
229EXTERN_C_START
230static napi_value Init(napi_env env, napi_value exports) {
231  napi_property_descriptor desc[] = {
232    {"injectEvent", nullptr, injectEvent, nullptr, nullptr, nullptr, napi_default, nullptr}};
233  napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
234  return exports;
235}
236EXTERN_C_END
237```