1 /*
2 * Copyright (c) 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 "tablet_tool_tranform_processor.h"
17
18 #include "i_input_windows_manager.h"
19
20 #undef MMI_LOG_DOMAIN
21 #define MMI_LOG_DOMAIN MMI_LOG_DISPATCH
22 #undef MMI_LOG_TAG
23 #define MMI_LOG_TAG "TabletToolTransformProcessor"
24
25 namespace OHOS {
26 namespace MMI {
27 namespace {
28 constexpr int32_t DEFAULT_POINTER_ID { 0 };
29 } // namespace
30
TabletToolTransformProcessor(int32_t deviceId)31 TabletToolTransformProcessor::TabletToolTransformProcessor(int32_t deviceId)
32 : deviceId_(deviceId)
33 {
34 current_ = [this]() {
35 DrawTouchGraphicIdle();
36 };
37 }
38
OnEvent(struct libinput_event * event)39 std::shared_ptr<PointerEvent> TabletToolTransformProcessor::OnEvent(struct libinput_event* event)
40 {
41 CHKPP(event);
42 if (pointerEvent_ == nullptr) {
43 pointerEvent_ = PointerEvent::Create();
44 CHKPP(pointerEvent_);
45 }
46 enum libinput_event_type type = libinput_event_get_type(event);
47 switch (type) {
48 case LIBINPUT_EVENT_TABLET_TOOL_AXIS: {
49 if (!OnTipMotion(event)) {
50 MMI_HILOGE("OnTipMotion failed");
51 return nullptr;
52 }
53 break;
54 }
55 case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: {
56 if (!OnTipProximity(event)) {
57 MMI_HILOGE("OnTipProximity failed");
58 return nullptr;
59 }
60 break;
61 }
62 case LIBINPUT_EVENT_TABLET_TOOL_TIP: {
63 if (!OnTip(event)) {
64 MMI_HILOGE("OnTip failed");
65 return nullptr;
66 }
67 break;
68 }
69 default: {
70 MMI_HILOGE("Unexpected event type");
71 return nullptr;
72 }
73 }
74 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHSCREEN);
75 pointerEvent_->UpdateId();
76 StartLogTraceId(pointerEvent_->GetId(), pointerEvent_->GetEventType(), pointerEvent_->GetPointerAction());
77 WIN_MGR->UpdateTargetPointer(pointerEvent_);
78 DrawTouchGraphic();
79 return pointerEvent_;
80 }
81
GetToolType(struct libinput_event_tablet_tool * tabletEvent)82 int32_t TabletToolTransformProcessor::GetToolType(struct libinput_event_tablet_tool* tabletEvent)
83 {
84 int32_t toolType = libinput_event_tablet_tool_get_tool_type(tabletEvent);
85 if (toolType != 0) {
86 return PointerEvent::TOOL_TYPE_PEN;
87 }
88 auto tool = libinput_event_tablet_tool_get_tool(tabletEvent);
89 CHKPR(tool, PointerEvent::TOOL_TYPE_PEN);
90 int32_t type = libinput_tablet_tool_get_type(tool);
91 switch (type) {
92 case LIBINPUT_TABLET_TOOL_TYPE_PEN: {
93 return PointerEvent::TOOL_TYPE_PEN;
94 }
95 case LIBINPUT_TABLET_TOOL_TYPE_ERASER: {
96 return PointerEvent::TOOL_TYPE_RUBBER;
97 }
98 case LIBINPUT_TABLET_TOOL_TYPE_BRUSH: {
99 return PointerEvent::TOOL_TYPE_BRUSH;
100 }
101 case LIBINPUT_TABLET_TOOL_TYPE_PENCIL: {
102 return PointerEvent::TOOL_TYPE_PENCIL;
103 }
104 case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH: {
105 return PointerEvent::TOOL_TYPE_AIRBRUSH;
106 }
107 case LIBINPUT_TABLET_TOOL_TYPE_MOUSE: {
108 return PointerEvent::TOOL_TYPE_MOUSE;
109 }
110 case LIBINPUT_TABLET_TOOL_TYPE_LENS: {
111 return PointerEvent::TOOL_TYPE_LENS;
112 }
113 default: {
114 MMI_HILOGW("Invalid type");
115 return PointerEvent::TOOL_TYPE_PEN;
116 }
117 }
118 }
119
OnTip(struct libinput_event * event)120 bool TabletToolTransformProcessor::OnTip(struct libinput_event* event)
121 {
122 CHKPF(event);
123 auto tabletEvent = libinput_event_get_tablet_tool_event(event);
124 CHKPF(tabletEvent);
125 auto tipState = libinput_event_tablet_tool_get_tip_state(tabletEvent);
126 bool ret = false;
127 switch (tipState) {
128 case LIBINPUT_TABLET_TOOL_TIP_DOWN: {
129 ret = OnTipDown(tabletEvent);
130 if (!ret) {
131 MMI_HILOGE("OnTipDown failed");
132 }
133 break;
134 }
135 case LIBINPUT_TABLET_TOOL_TIP_UP: {
136 ret = OnTipUp(tabletEvent);
137 if (!ret) {
138 MMI_HILOGE("OnTipUp failed");
139 }
140 break;
141 }
142 default: {
143 MMI_HILOGE("Invalid tip state");
144 break;
145 }
146 }
147 return ret;
148 }
149
OnTipDown(struct libinput_event_tablet_tool * event)150 bool TabletToolTransformProcessor::OnTipDown(struct libinput_event_tablet_tool* event)
151 {
152 CALL_DEBUG_ENTER;
153 CHKPF(event);
154 int32_t targetDisplayId = -1;
155 PhysicalCoordinate tCoord;
156 if (!WIN_MGR->CalculateTipPoint(event, targetDisplayId, tCoord)) {
157 MMI_HILOGE("CalculateTipPoint failed");
158 return false;
159 }
160 double tiltX = libinput_event_tablet_tool_get_tilt_x(event);
161 double tiltY = libinput_event_tablet_tool_get_tilt_y(event);
162 double pressure = libinput_event_tablet_tool_get_pressure(event);
163 int32_t toolType = GetToolType(event);
164 int32_t twist = libinput_event_tablet_tool_get_twist(event);
165
166 uint64_t time = libinput_event_tablet_tool_get_time_usec(event);
167 pointerEvent_->SetActionStartTime(time);
168 pointerEvent_->SetTargetDisplayId(targetDisplayId);
169 pointerEvent_->SetActionTime(time);
170 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN);
171
172 PointerEvent::PointerItem item;
173 if (pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
174 pointerEvent_->RemovePointerItem(DEFAULT_POINTER_ID);
175 }
176 item.SetPointerId(DEFAULT_POINTER_ID);
177 item.SetDeviceId(deviceId_);
178 item.SetDownTime(time);
179 item.SetPressed(true);
180 item.SetDisplayX(static_cast<int32_t>(tCoord.x));
181 item.SetDisplayY(static_cast<int32_t>(tCoord.y));
182 item.SetDisplayXPos(tCoord.x);
183 item.SetDisplayYPos(tCoord.y);
184 item.SetRawDisplayX(static_cast<int32_t>(tCoord.x));
185 item.SetRawDisplayY(static_cast<int32_t>(tCoord.y));
186 item.SetTiltX(tiltX);
187 item.SetTiltY(tiltY);
188 item.SetToolType(toolType);
189 item.SetPressure(pressure);
190 item.SetTargetWindowId(-1);
191 item.SetTwist(twist);
192
193 pointerEvent_->SetDeviceId(deviceId_);
194 pointerEvent_->AddPointerItem(item);
195 pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
196 return true;
197 }
198
OnTipMotion(struct libinput_event * event)199 bool TabletToolTransformProcessor::OnTipMotion(struct libinput_event* event)
200 {
201 CALL_DEBUG_ENTER;
202 CHKPF(event);
203 auto tabletEvent = libinput_event_get_tablet_tool_event(event);
204 CHKPF(tabletEvent);
205 uint64_t time = libinput_event_tablet_tool_get_time_usec(tabletEvent);
206 pointerEvent_->SetActionTime(time);
207 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
208
209 int32_t targetDisplayId = pointerEvent_->GetTargetDisplayId();
210 PhysicalCoordinate tCoord;
211 if (!WIN_MGR->CalculateTipPoint(tabletEvent, targetDisplayId, tCoord)) {
212 MMI_HILOGE("CalculateTipPoint failed");
213 return false;
214 }
215 double tiltX = libinput_event_tablet_tool_get_tilt_x(tabletEvent);
216 double tiltY = libinput_event_tablet_tool_get_tilt_y(tabletEvent);
217 double pressure = libinput_event_tablet_tool_get_pressure(tabletEvent);
218 int32_t toolType = GetToolType(tabletEvent);
219 int32_t twist = libinput_event_tablet_tool_get_twist(tabletEvent);
220
221 PointerEvent::PointerItem item;
222 if (!pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
223 MMI_HILOGW("The pointer is expected, but not found");
224 pointerEvent_->SetActionStartTime(time);
225 pointerEvent_->SetTargetDisplayId(targetDisplayId);
226 pointerEvent_->SetDeviceId(deviceId_);
227 pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
228
229 item.SetPointerId(DEFAULT_POINTER_ID);
230 item.SetDeviceId(deviceId_);
231 item.SetDownTime(time);
232 }
233 item.SetPressed(true);
234 item.SetToolType(toolType);
235 item.SetDisplayX(static_cast<int32_t>(tCoord.x));
236 item.SetDisplayY(static_cast<int32_t>(tCoord.y));
237 item.SetDisplayXPos(tCoord.x);
238 item.SetDisplayYPos(tCoord.y);
239 item.SetRawDisplayX(static_cast<int32_t>(tCoord.x));
240 item.SetRawDisplayY(static_cast<int32_t>(tCoord.y));
241 item.SetTiltX(tiltX);
242 item.SetTiltY(tiltY);
243 item.SetPressure(pressure);
244 item.SetTwist(twist);
245 pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, item);
246 return true;
247 }
248
OnTipUp(struct libinput_event_tablet_tool * event)249 bool TabletToolTransformProcessor::OnTipUp(struct libinput_event_tablet_tool* event)
250 {
251 CALL_DEBUG_ENTER;
252 CHKPF(event);
253 uint64_t time = libinput_event_tablet_tool_get_time_usec(event);
254 pointerEvent_->SetActionTime(time);
255 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
256
257 PointerEvent::PointerItem item;
258 if (!pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
259 MMI_HILOGE("GetPointerItem failed");
260 return false;
261 }
262 item.SetPressed(false);
263 pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, item);
264 return true;
265 }
266
OnTipProximity(struct libinput_event * event)267 bool TabletToolTransformProcessor::OnTipProximity(struct libinput_event* event)
268 {
269 CALL_DEBUG_ENTER;
270 CHKPF(event);
271 auto tabletEvent = libinput_event_get_tablet_tool_event(event);
272 CHKPF(tabletEvent);
273 uint64_t time = libinput_event_tablet_tool_get_time_usec(tabletEvent);
274 pointerEvent_->SetActionTime(time);
275
276 bool tabletProximityState = libinput_event_tablet_tool_get_proximity_state(tabletEvent);
277 if (tabletProximityState) {
278 MMI_HILOGD("The pen is getting close and report proximity in event");
279 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_PROXIMITY_IN);
280 } else {
281 MMI_HILOGD("The pen is getting away and report proximity out event");
282 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_PROXIMITY_OUT);
283 }
284
285 int32_t targetDisplayId = pointerEvent_->GetTargetDisplayId();
286 PhysicalCoordinate coord;
287 if (!WIN_MGR->CalculateTipPoint(tabletEvent, targetDisplayId, coord)) {
288 MMI_HILOGE("CalculateTipPoint failed");
289 return false;
290 }
291 double tiltX = libinput_event_tablet_tool_get_tilt_x(tabletEvent);
292 double tiltY = libinput_event_tablet_tool_get_tilt_y(tabletEvent);
293 double pressure = libinput_event_tablet_tool_get_pressure(tabletEvent);
294 int32_t toolType = GetToolType(tabletEvent);
295
296 PointerEvent::PointerItem item;
297 if (!pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
298 MMI_HILOGW("The pointer is expected, but not found");
299 }
300
301 pointerEvent_->SetActionStartTime(time);
302 pointerEvent_->SetTargetDisplayId(targetDisplayId);
303 pointerEvent_->SetDeviceId(deviceId_);
304 pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
305
306 item.SetPointerId(DEFAULT_POINTER_ID);
307 item.SetDeviceId(deviceId_);
308 item.SetDownTime(time);
309 item.SetPressed(false);
310 item.SetToolType(toolType);
311 item.SetDisplayX(static_cast<int32_t>(coord.x));
312 item.SetDisplayY(static_cast<int32_t>(coord.y));
313 item.SetDisplayXPos(coord.x);
314 item.SetDisplayYPos(coord.y);
315 item.SetRawDisplayX(static_cast<int32_t>(coord.x));
316 item.SetRawDisplayY(static_cast<int32_t>(coord.y));
317 item.SetTiltX(tiltX);
318 item.SetTiltY(tiltY);
319 item.SetPressure(pressure);
320 pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, item);
321 return true;
322 }
323
DrawTouchGraphic()324 void TabletToolTransformProcessor::DrawTouchGraphic()
325 {
326 CHKPV(current_);
327 current_();
328 }
329
DrawTouchGraphicIdle()330 void TabletToolTransformProcessor::DrawTouchGraphicIdle()
331 {
332 CHKPV(pointerEvent_);
333 auto pointerAction = pointerEvent_->GetPointerAction();
334 switch (pointerAction) {
335 case PointerEvent::POINTER_ACTION_PROXIMITY_IN:
336 case PointerEvent::POINTER_ACTION_DOWN:
337 case PointerEvent::POINTER_ACTION_MOVE: {
338 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN);
339 current_ = [this]() {
340 DrawTouchGraphicDrawing();
341 };
342 break;
343 }
344 default: {
345 return;
346 }
347 }
348 WIN_MGR->DrawTouchGraphic(pointerEvent_);
349 pointerEvent_->SetPointerAction(pointerAction);
350 }
351
DrawTouchGraphicDrawing()352 void TabletToolTransformProcessor::DrawTouchGraphicDrawing()
353 {
354 CHKPV(pointerEvent_);
355 auto pointerAction = pointerEvent_->GetPointerAction();
356 switch (pointerAction) {
357 case PointerEvent::POINTER_ACTION_MOVE:
358 case PointerEvent::POINTER_ACTION_UP: {
359 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
360 break;
361 }
362 case PointerEvent::POINTER_ACTION_PROXIMITY_OUT: {
363 auto pointerEvent = std::make_shared<PointerEvent>(*pointerEvent_);
364 PointerEvent::PointerItem item {};
365 if (pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
366 item.SetPressed(true);
367 pointerEvent->UpdatePointerItem(pointerEvent->GetPointerId(), item);
368 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
369 WIN_MGR->DrawTouchGraphic(pointerEvent);
370 }
371 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
372 current_ = [this]() {
373 DrawTouchGraphicIdle();
374 };
375 break;
376 }
377 default: {
378 return;
379 }
380 }
381 WIN_MGR->DrawTouchGraphic(pointerEvent_);
382 pointerEvent_->SetPointerAction(pointerAction);
383 }
384 } // namespace MMI
385 } // namespace OHOS
386