libaurum: refactor a flick command and implementation
[platform/core/uifw/aurum.git] / libaurum / src / DeviceImpl / TizenImpl.cc
1 #include "DeviceImpl/TizenImpl.h"
2 #include <loguru.hpp>
3
4 #include <functional>
5 #include <tuple>
6 #include <iostream>
7 #include <memory>
8
9 #include <stdlib.h>
10 #include <time.h>
11 #include <Ecore.h>
12
13 TizenImpl::TizenImpl()
14 : mFakeTouchHandle{0}, mFakeKeyboardHandle{0}, mFakeWheelHandle{0}, isTimerStarted{false}
15 {
16     LOG_SCOPE_F(INFO, "device implementation init");
17     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
18         TizenImpl *obj = static_cast<TizenImpl*>(data);
19         obj->mFakeTouchHandle = efl_util_input_initialize_generator(EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN);
20         obj->mFakeKeyboardHandle =
21             efl_util_input_initialize_generator(EFL_UTIL_INPUT_DEVTYPE_KEYBOARD);
22         obj->mFakeWheelHandle = efl_util_input_initialize_generator(EFL_UTIL_INPUT_DEVTYPE_POINTER);
23         return NULL;
24     }, this);
25 }
26
27 TizenImpl::~TizenImpl()
28 {
29     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
30         TizenImpl *obj = static_cast<TizenImpl*>(data);
31         efl_util_input_deinitialize_generator(obj->mFakeTouchHandle);
32         efl_util_input_deinitialize_generator(obj->mFakeKeyboardHandle);
33         efl_util_input_deinitialize_generator(obj->mFakeWheelHandle);
34         return NULL;
35     }, this);
36 }
37
38 bool TizenImpl::click(const int x, const int y)
39 {
40     return click(x, y, INTV_CLICK);
41 }
42
43 bool TizenImpl::click(const int x, const int y, const unsigned int intv)
44 {
45     touchDown(x, y);
46     usleep(intv * MSEC_PER_SEC);
47     touchUp(x, y);
48
49     return true;
50 }
51
52
53 bool TizenImpl::touchDown(const int x, const int y)
54 {
55     LOG_F(INFO, "touch down %d %d", x, y);
56     auto args = std::make_tuple(this, x, y);
57     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
58         TizenImpl *obj;
59         int x, y;
60         std::tie(obj, x, y) = *static_cast<std::tuple<TizenImpl*, int, int>*>(data);
61         efl_util_input_generate_touch(obj->mFakeTouchHandle, 0, EFL_UTIL_INPUT_TOUCH_BEGIN,
62                                   x, y);
63
64         return NULL;
65     }, (void*)(&args));
66     return true;
67 }
68
69 bool TizenImpl::touchMove(const int x, const int y)
70 {
71     LOG_F(INFO, "touch move %d %d", x, y);
72     auto args = std::make_tuple(this, x, y);
73     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
74         TizenImpl *obj;
75         int x, y;
76         std::tie(obj, x, y) = *static_cast<std::tuple<TizenImpl*, int, int>*>(data);
77
78         efl_util_input_generate_touch(obj->mFakeTouchHandle, 0, EFL_UTIL_INPUT_TOUCH_UPDATE,
79                                   x, y);
80
81         return NULL;
82     }, (void*)(&args));
83     return true;
84 }
85
86 bool TizenImpl::touchUp(const int x, const int y)
87 {
88     LOG_F(INFO, "touch up %d %d", x, y);
89     auto args = std::make_tuple(this, x, y);
90     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
91         TizenImpl *obj;
92         int x, y;
93         std::tie(obj, x, y) = *static_cast<std::tuple<TizenImpl*, int, int>*>(data);
94         efl_util_input_generate_touch(obj->mFakeTouchHandle, 0, EFL_UTIL_INPUT_TOUCH_END,
95                                   x, y);
96         return NULL;
97     }, (void*)(&args));
98     return true;
99 }
100
101 bool TizenImpl::wheelUp(int amount, const int durationMs)
102 {
103     LOG_F(INFO, "wheel up %d for %d", amount, durationMs);
104     auto args = std::make_tuple(this);
105     for (int i = 0; i < amount; i++){
106         ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
107                 TizenImpl *obj;
108                 std::tie(obj) = *static_cast<std::tuple<TizenImpl*>*>(data);
109                 efl_util_input_generate_wheel(obj->mFakeWheelHandle, EFL_UTIL_INPUT_POINTER_WHEEL_HORZ, 1);
110             return NULL;
111         }, (void*)(&args));
112         usleep(durationMs*MSEC_PER_SEC/amount);
113     }
114
115     return true;
116 }
117
118 bool TizenImpl::wheelDown(int amount, const int durationMs)
119 {
120     LOG_F(INFO, "wheel down %d for %d", amount, durationMs);
121     auto args = std::make_tuple(this);
122     for (int i = 0; i < amount; i++){
123         ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
124                 TizenImpl *obj;
125                 std::tie(obj) = *static_cast<std::tuple<TizenImpl*>*>(data);
126                 efl_util_input_generate_wheel(obj->mFakeWheelHandle, EFL_UTIL_INPUT_POINTER_WHEEL_HORZ, -1);
127             return NULL;
128         }, (void*)(&args));
129         usleep(durationMs*MSEC_PER_SEC/amount);
130     }
131
132     return true;
133 }
134 void TizenImpl::startTimer(void)
135 {
136     isTimerStarted = true;
137     clock_gettime(CLOCK_MONOTONIC, &tStart);
138 }
139
140 int TizenImpl::stopTimer(void)
141 {
142     struct timespec tEnd;
143     if (!isTimerStarted) return 0;
144     isTimerStarted = false;
145     clock_gettime(CLOCK_MONOTONIC, &tEnd);
146     return ((tEnd.tv_sec + tEnd.tv_nsec/1000000000.0) - (tStart.tv_sec + tStart.tv_nsec/1000000000.0)) * 1000000;
147 }
148
149 bool TizenImpl::drag(const int sx, const int sy, const int ex, const int ey,
150                          const int steps, const int durationMs)
151 {
152     int i, j;
153     int _durationUs, _steps, _stepUs;
154     int dur;
155     int consumptionUs;
156
157     if (steps <= 0) _steps = 1;
158     else _steps = steps;
159
160     if (durationMs < MINIMUM_DURATION_DRAG) _durationUs = INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC;
161     else _durationUs = durationMs * MSEC_PER_SEC;
162
163     _stepUs = _durationUs / (_steps +1);
164
165     if (_stepUs < (INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC)) {
166         _steps = (int)(_durationUs / (INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC)) - 1;
167         _stepUs  = (INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC);
168     }
169     LOG_SCOPE_F(INFO, "flicking (%d, %d) -> (%d, %d) for (%d ms)", sx, sy, ex, ey, durationMs);
170     startTimer();
171     touchDown(sx, sy);
172     consumptionUs = stopTimer();
173
174     for ( int s = 1; s <= _steps + 1; s++) {
175         usleep((_stepUs - consumptionUs)>INTV_MINIMUM_USLEEP?(_stepUs - consumptionUs):INTV_MINIMUM_USLEEP);
176         startTimer();
177         touchMove(sx + (ex - sx) * s / (steps + 1), sy + (ey - sy) * s / (steps + 1));
178         consumptionUs = stopTimer();
179     }
180     usleep((_stepUs - consumptionUs)>INTV_MINIMUM_USLEEP?(_stepUs - consumptionUs):INTV_MINIMUM_USLEEP);
181     touchMove(ex, ey);
182     touchUp(ex, ey);
183
184     return true;
185 }
186
187 bool TizenImpl::pressBack()
188 {
189     return pressKeyCode("XF86Back");
190 }
191
192 bool TizenImpl::pressHome()
193 {
194     return pressKeyCode("XF86Home");
195 }
196
197 bool TizenImpl::pressMenu()
198 {
199     return pressKeyCode("XF86Menu");
200 }
201
202 bool TizenImpl::pressVolUp()
203 {
204     return pressKeyCode("XF86AudioRaiseVolume");
205 }
206
207 bool TizenImpl::pressVolDown()
208 {
209     return pressKeyCode("XF86AudioLowerVolume");
210 }
211
212 bool TizenImpl::pressPower()
213 {
214     return pressKeyCode("XF86PowerOff");
215 }
216
217 bool TizenImpl::pressKeyCode(std::string keycode)
218 {
219     return pressKeyCode(keycode, INTV_KEYPRESS);
220 }
221
222 bool TizenImpl::pressKeyCode(std::string keycode, unsigned int intv)
223 {
224     auto args = std::make_tuple(this, keycode);
225     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
226         TizenImpl *obj;
227         std::string keycode;
228         std::tie(obj, keycode) = *static_cast<std::tuple<TizenImpl*, std::string>*>(data);
229         efl_util_input_generate_key(obj->mFakeKeyboardHandle, keycode.c_str(), 1);
230         return NULL;
231     }, (void*)(&args));
232
233     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{return NULL;}, NULL);
234     usleep(intv * 1000);
235
236     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
237         TizenImpl *obj;
238         std::string keycode;
239         std::tie(obj, keycode) = *static_cast<std::tuple<TizenImpl*, std::string>*>(data);
240         efl_util_input_generate_key(obj->mFakeKeyboardHandle, keycode.c_str(), 0);
241         return NULL;
242     }, (void*)(&args));
243
244     return true;
245 }
246
247 bool TizenImpl::takeScreenshot(std::string path, float scale, int quality)
248 {
249     return false;
250 }
251
252 class Clock {
253 public:
254     virtual ~Clock(){};
255
256 public:
257     virtual long long getTime() = 0;
258 protected:
259     long long convertTime(struct timespec t){
260         return (long long)t.tv_sec * 1000L + (long long)(t.tv_nsec / 1000000);
261     }
262 };
263
264 class MonotonicClock : public Clock {
265 public:
266     virtual ~MonotonicClock(){};
267
268     long long getTime() override {
269         struct timespec t;
270         clock_gettime(CLOCK_MONOTONIC, &t);
271         return convertTime(t);
272     }
273
274 };
275
276 class WallClock : public Clock {
277 public:
278     virtual ~WallClock(){};
279
280     long long getTime() override {
281         struct timespec t;
282         clock_gettime(CLOCK_REALTIME, &t);
283         return convertTime(t);
284     }
285 };
286
287 long long TizenImpl::getSystemTime(TypeRequestType type)
288 {
289     std::unique_ptr<Clock> clock;
290     if (type == TypeRequestType::MONOTONIC)
291         clock = std::make_unique<MonotonicClock>();
292     else if (type == TypeRequestType::WALLCLOCK)
293         clock = std::make_unique<WallClock>();
294
295     return clock->getTime();
296
297 }