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 #include "i_input_windows_manager.h"
18 #include "mmi_log.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 
OnEvent(struct libinput_event * event)34 std::shared_ptr<PointerEvent> TabletToolTransformProcessor::OnEvent(struct libinput_event* event)
35 {
36     CHKPP(event);
37     if (pointerEvent_ == nullptr) {
38         pointerEvent_ = PointerEvent::Create();
39         CHKPP(pointerEvent_);
40     }
41     enum libinput_event_type type = libinput_event_get_type(event);
42     switch (type) {
43         case LIBINPUT_EVENT_TABLET_TOOL_AXIS: {
44             if (!OnTipMotion(event)) {
45                 MMI_HILOGE("OnTipMotion failed");
46                 return nullptr;
47             }
48             break;
49         }
50         case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: {
51             if (!OnTipProximity(event)) {
52                 MMI_HILOGE("OnTipProximity failed");
53                 return nullptr;
54             }
55             break;
56         }
57         case LIBINPUT_EVENT_TABLET_TOOL_TIP: {
58             if (!OnTip(event)) {
59                 MMI_HILOGE("OnTip failed");
60                 return nullptr;
61             }
62             break;
63         }
64         default: {
65             MMI_HILOGE("Unexpected event type");
66             return nullptr;
67         }
68     }
69     pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHSCREEN);
70     pointerEvent_->UpdateId();
71     StartLogTraceId(pointerEvent_->GetId(), pointerEvent_->GetEventType(), pointerEvent_->GetPointerAction());
72     WIN_MGR->UpdateTargetPointer(pointerEvent_);
73     return pointerEvent_;
74 }
75 
GetToolType(struct libinput_event_tablet_tool * tabletEvent)76 int32_t TabletToolTransformProcessor::GetToolType(struct libinput_event_tablet_tool* tabletEvent)
77 {
78     int32_t toolType = libinput_event_tablet_tool_get_tool_type(tabletEvent);
79     if (toolType != 0) {
80         return PointerEvent::TOOL_TYPE_PEN;
81     }
82     auto tool = libinput_event_tablet_tool_get_tool(tabletEvent);
83     CHKPR(tool, PointerEvent::TOOL_TYPE_PEN);
84     int32_t type = libinput_tablet_tool_get_type(tool);
85     switch (type) {
86         case LIBINPUT_TABLET_TOOL_TYPE_PEN: {
87             return PointerEvent::TOOL_TYPE_PEN;
88         }
89         case LIBINPUT_TABLET_TOOL_TYPE_ERASER: {
90             return PointerEvent::TOOL_TYPE_RUBBER;
91         }
92         case LIBINPUT_TABLET_TOOL_TYPE_BRUSH: {
93             return PointerEvent::TOOL_TYPE_BRUSH;
94         }
95         case LIBINPUT_TABLET_TOOL_TYPE_PENCIL: {
96             return PointerEvent::TOOL_TYPE_PENCIL;
97         }
98         case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH: {
99             return PointerEvent::TOOL_TYPE_AIRBRUSH;
100         }
101         case LIBINPUT_TABLET_TOOL_TYPE_MOUSE: {
102             return PointerEvent::TOOL_TYPE_MOUSE;
103         }
104         case LIBINPUT_TABLET_TOOL_TYPE_LENS: {
105             return PointerEvent::TOOL_TYPE_LENS;
106         }
107         default: {
108             MMI_HILOGW("Invalid type");
109             return PointerEvent::TOOL_TYPE_PEN;
110         }
111     }
112 }
113 
OnTip(struct libinput_event * event)114 bool TabletToolTransformProcessor::OnTip(struct libinput_event* event)
115 {
116     CHKPF(event);
117     auto tabletEvent = libinput_event_get_tablet_tool_event(event);
118     CHKPF(tabletEvent);
119     auto tipState = libinput_event_tablet_tool_get_tip_state(tabletEvent);
120     bool ret = false;
121     switch (tipState) {
122         case LIBINPUT_TABLET_TOOL_TIP_DOWN: {
123             ret = OnTipDown(tabletEvent);
124             if (!ret) {
125                 MMI_HILOGE("OnTipDown failed");
126             }
127             break;
128         }
129         case LIBINPUT_TABLET_TOOL_TIP_UP: {
130             ret = OnTipUp(tabletEvent);
131             if (!ret) {
132                 MMI_HILOGE("OnTipUp failed");
133             }
134             break;
135         }
136         default: {
137             MMI_HILOGE("Invalid tip state");
138             break;
139         }
140     }
141     return ret;
142 }
143 
OnTipDown(struct libinput_event_tablet_tool * event)144 bool TabletToolTransformProcessor::OnTipDown(struct libinput_event_tablet_tool* event)
145 {
146     CALL_DEBUG_ENTER;
147     CHKPF(event);
148     int32_t targetDisplayId = -1;
149     PhysicalCoordinate tCoord;
150     if (!WIN_MGR->CalculateTipPoint(event, targetDisplayId, tCoord)) {
151         MMI_HILOGE("CalculateTipPoint failed");
152         return false;
153     }
154     double tiltX = libinput_event_tablet_tool_get_tilt_x(event);
155     double tiltY = libinput_event_tablet_tool_get_tilt_y(event);
156     double pressure = libinput_event_tablet_tool_get_pressure(event);
157     int32_t toolType = GetToolType(event);
158 
159     uint64_t time = libinput_event_tablet_tool_get_time_usec(event);
160     pointerEvent_->SetActionStartTime(time);
161     pointerEvent_->SetTargetDisplayId(targetDisplayId);
162     pointerEvent_->SetActionTime(time);
163     pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN);
164 
165     PointerEvent::PointerItem item;
166     if (pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
167         pointerEvent_->RemovePointerItem(DEFAULT_POINTER_ID);
168     }
169     item.SetPointerId(DEFAULT_POINTER_ID);
170     item.SetDeviceId(deviceId_);
171     item.SetDownTime(time);
172     item.SetPressed(true);
173     item.SetDisplayX(static_cast<int32_t>(tCoord.x));
174     item.SetDisplayY(static_cast<int32_t>(tCoord.y));
175     item.SetDisplayXPos(tCoord.x);
176     item.SetDisplayYPos(tCoord.y);
177     item.SetTiltX(tiltX);
178     item.SetTiltY(tiltY);
179     item.SetToolType(toolType);
180     item.SetPressure(pressure);
181     item.SetTargetWindowId(-1);
182 
183     pointerEvent_->SetDeviceId(deviceId_);
184     pointerEvent_->AddPointerItem(item);
185     pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
186     return true;
187 }
188 
OnTipMotion(struct libinput_event * event)189 bool TabletToolTransformProcessor::OnTipMotion(struct libinput_event* event)
190 {
191     CALL_DEBUG_ENTER;
192     CHKPF(event);
193     auto tabletEvent = libinput_event_get_tablet_tool_event(event);
194     CHKPF(tabletEvent);
195     uint64_t time = libinput_event_tablet_tool_get_time_usec(tabletEvent);
196     pointerEvent_->SetActionTime(time);
197     pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
198 
199     int32_t targetDisplayId = pointerEvent_->GetTargetDisplayId();
200     PhysicalCoordinate tCoord;
201     if (!WIN_MGR->CalculateTipPoint(tabletEvent, targetDisplayId, tCoord)) {
202         MMI_HILOGE("CalculateTipPoint failed");
203         return false;
204     }
205     double tiltX = libinput_event_tablet_tool_get_tilt_x(tabletEvent);
206     double tiltY = libinput_event_tablet_tool_get_tilt_y(tabletEvent);
207     double pressure = libinput_event_tablet_tool_get_pressure(tabletEvent);
208     int32_t toolType = GetToolType(tabletEvent);
209 
210     PointerEvent::PointerItem item;
211     if (!pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
212         MMI_HILOGW("The pointer is expected, but not found");
213         pointerEvent_->SetActionStartTime(time);
214         pointerEvent_->SetTargetDisplayId(targetDisplayId);
215         pointerEvent_->SetDeviceId(deviceId_);
216         pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
217 
218         item.SetPointerId(DEFAULT_POINTER_ID);
219         item.SetDeviceId(deviceId_);
220         item.SetDownTime(time);
221         item.SetPressed(true);
222         item.SetToolType(toolType);
223     }
224     item.SetDisplayX(static_cast<int32_t>(tCoord.x));
225     item.SetDisplayY(static_cast<int32_t>(tCoord.y));
226     item.SetDisplayXPos(tCoord.x);
227     item.SetDisplayYPos(tCoord.y);
228     item.SetTiltX(tiltX);
229     item.SetTiltY(tiltY);
230     item.SetPressure(pressure);
231     pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, item);
232     return true;
233 }
234 
OnTipUp(struct libinput_event_tablet_tool * event)235 bool TabletToolTransformProcessor::OnTipUp(struct libinput_event_tablet_tool* event)
236 {
237     CALL_DEBUG_ENTER;
238     CHKPF(event);
239     uint64_t time = libinput_event_tablet_tool_get_time_usec(event);
240     pointerEvent_->SetActionTime(time);
241     pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
242 
243     PointerEvent::PointerItem item;
244     if (!pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
245         MMI_HILOGE("GetPointerItem failed");
246         return false;
247     }
248     item.SetPressed(false);
249     pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, item);
250     return true;
251 }
252 
OnTipProximity(struct libinput_event * event)253 bool TabletToolTransformProcessor::OnTipProximity(struct libinput_event* event)
254 {
255     CALL_DEBUG_ENTER;
256     CHKPF(event);
257     auto tabletEvent = libinput_event_get_tablet_tool_event(event);
258     CHKPF(tabletEvent);
259     uint64_t time = libinput_event_tablet_tool_get_time_usec(tabletEvent);
260     pointerEvent_->SetActionTime(time);
261 
262     bool tabletProximityState = libinput_event_tablet_tool_get_proximity_state(tabletEvent);
263     if (tabletProximityState) {
264         MMI_HILOGD("The pen is getting close and report proximity in event");
265         pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_PROXIMITY_IN);
266     } else {
267         MMI_HILOGD("The pen is getting away and report proximity out event");
268         pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_PROXIMITY_OUT);
269     }
270 
271     int32_t targetDisplayId = pointerEvent_->GetTargetDisplayId();
272     PhysicalCoordinate coord;
273     if (!WIN_MGR->CalculateTipPoint(tabletEvent, targetDisplayId, coord)) {
274         MMI_HILOGE("CalculateTipPoint failed");
275         return false;
276     }
277     double tiltX = libinput_event_tablet_tool_get_tilt_x(tabletEvent);
278     double tiltY = libinput_event_tablet_tool_get_tilt_y(tabletEvent);
279     double pressure = libinput_event_tablet_tool_get_pressure(tabletEvent);
280     int32_t toolType = GetToolType(tabletEvent);
281 
282     PointerEvent::PointerItem item;
283     if (!pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, item)) {
284         MMI_HILOGW("The pointer is expected, but not found");
285     }
286 
287     pointerEvent_->SetActionStartTime(time);
288     pointerEvent_->SetTargetDisplayId(targetDisplayId);
289     pointerEvent_->SetDeviceId(deviceId_);
290     pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
291 
292     item.SetPointerId(DEFAULT_POINTER_ID);
293     item.SetDeviceId(deviceId_);
294     item.SetDownTime(time);
295     item.SetPressed(false);
296     item.SetToolType(toolType);
297     item.SetDisplayX(static_cast<int32_t>(coord.x));
298     item.SetDisplayY(static_cast<int32_t>(coord.y));
299     item.SetDisplayXPos(coord.x);
300     item.SetDisplayYPos(coord.y);
301     item.SetTiltX(tiltX);
302     item.SetTiltY(tiltY);
303     item.SetPressure(pressure);
304     pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, item);
305     return true;
306 }
307 } // namespace MMI
308 } // namespace OHOS
309