build: get doxygen generating selective
[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 #include <tdm_helper.h>
14 #include <tbm_surface.h>
15 #include <system_info.h>
16
17 TizenImpl::TizenImpl()
18 : mFakeTouchHandle{0}, mFakeKeyboardHandle{0}, mFakeWheelHandle{0}, isTimerStarted{false}, mTouchSeq{}
19 {
20     LOG_SCOPE_F(INFO, "device implementation init");
21     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
22         TizenImpl *obj = static_cast<TizenImpl*>(data);
23         obj->mFakeTouchHandle = efl_util_input_initialize_generator(EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN);
24         obj->mFakeKeyboardHandle =
25             efl_util_input_initialize_generator(EFL_UTIL_INPUT_DEVTYPE_KEYBOARD);
26         obj->mFakeWheelHandle = efl_util_input_initialize_generator(EFL_UTIL_INPUT_DEVTYPE_POINTER);
27         return NULL;
28     }, this);
29 }
30
31 TizenImpl::~TizenImpl()
32 {
33     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
34         TizenImpl *obj = static_cast<TizenImpl*>(data);
35         efl_util_input_deinitialize_generator(obj->mFakeTouchHandle);
36         efl_util_input_deinitialize_generator(obj->mFakeKeyboardHandle);
37         efl_util_input_deinitialize_generator(obj->mFakeWheelHandle);
38         return NULL;
39     }, this);
40 }
41
42 bool TizenImpl::click(const int x, const int y)
43 {
44     return click(x, y, INTV_CLICK);
45 }
46
47 bool TizenImpl::click(const int x, const int y, const unsigned int intv)
48 {
49     int seq = touchDown(x, y);
50     if (seq < 0) return false;
51     usleep(intv * MSEC_PER_SEC);
52     touchUp(x, y, seq);
53
54     return true;
55 }
56
57
58 int TizenImpl::touchDown(const int x, const int y)
59 {
60     int seq = grabTouchSeqNumber();
61     LOG_F(INFO, "touch down %d %d , seq:%d", x, y, seq);
62     if (seq >= 0) {
63         auto args = std::make_tuple(this, x, y, seq);
64         long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
65             TizenImpl *obj;
66             int x, y, seq;
67             std::tie(obj, x, y, seq) = *static_cast<std::tuple<TizenImpl*, int, int, int>*>(data);
68             return (void*)efl_util_input_generate_touch(obj->mFakeTouchHandle, seq, EFL_UTIL_INPUT_TOUCH_BEGIN,
69                                     x, y);
70
71         }, (void*)(&args));
72
73         if (result != EFL_UTIL_ERROR_NONE) {
74             releaseTouchSeqNumber(seq);
75             return -1;
76         }
77     }
78     return seq;
79 }
80
81 bool TizenImpl::touchMove(const int x, const int y, const int seq)
82 {
83     LOG_F(INFO, "touch move %d %d, seq:%d", x, y, seq);
84     if (seq >= 0) {
85         auto args = std::make_tuple(this, x, y, seq);
86         long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
87             TizenImpl *obj;
88             int x, y, seq;
89             std::tie(obj, x, y, seq) = *static_cast<std::tuple<TizenImpl*, int, int, int>*>(data);
90
91             return (void*)efl_util_input_generate_touch(obj->mFakeTouchHandle, seq, EFL_UTIL_INPUT_TOUCH_UPDATE,
92                                     x, y);
93
94         }, (void*)(&args));
95         return result == EFL_UTIL_ERROR_NONE;
96     }
97     return false;
98 }
99
100 bool TizenImpl::touchUp(const int x, const int y, const int seq)
101 {
102     LOG_F(INFO, "touch up %d %d, seq:%d", x, y, seq);
103     if (seq >= 0) {
104         auto args = std::make_tuple(this, x, y, seq);
105         long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
106             TizenImpl *obj;
107             int x, y, seq;
108             std::tie(obj, x, y, seq) = *static_cast<std::tuple<TizenImpl*, int, int, int>*>(data);
109             return (void*)efl_util_input_generate_touch(obj->mFakeTouchHandle, seq, EFL_UTIL_INPUT_TOUCH_END,
110                                     x, y);
111         }, (void*)(&args));
112         return releaseTouchSeqNumber(seq) && result == EFL_UTIL_ERROR_NONE;
113     }
114     return false;
115 }
116
117 bool TizenImpl::wheelUp(int amount, const int durationMs)
118 {
119     LOG_F(INFO, "wheel up %d for %d", amount, durationMs);
120     auto args = std::make_tuple(this);
121     long result = -1;
122     for (int i = 0; i < amount; i++){
123         result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
124                 TizenImpl *obj;
125                 std::tie(obj) = *static_cast<std::tuple<TizenImpl*>*>(data);
126             return (void*)efl_util_input_generate_wheel(obj->mFakeWheelHandle, EFL_UTIL_INPUT_POINTER_WHEEL_HORZ, 1);
127         }, (void*)(&args));
128         usleep(durationMs*MSEC_PER_SEC/amount);
129     }
130
131     return result == EFL_UTIL_ERROR_NONE;
132 }
133
134 bool TizenImpl::wheelDown(int amount, const int durationMs)
135 {
136     LOG_F(INFO, "wheel down %d for %d", amount, durationMs);
137     auto args = std::make_tuple(this);
138     long result = -1;
139     for (int i = 0; i < amount; i++){
140         result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
141                 TizenImpl *obj;
142                 std::tie(obj) = *static_cast<std::tuple<TizenImpl*>*>(data);
143                 return (void*)efl_util_input_generate_wheel(obj->mFakeWheelHandle, EFL_UTIL_INPUT_POINTER_WHEEL_HORZ, -1);
144             return NULL;
145         }, (void*)(&args));
146         usleep(durationMs*MSEC_PER_SEC/amount);
147     }
148
149     return result == EFL_UTIL_ERROR_NONE;
150 }
151 void TizenImpl::startTimer(void)
152 {
153     isTimerStarted = true;
154     clock_gettime(CLOCK_MONOTONIC, &tStart);
155 }
156
157 int TizenImpl::stopTimer(void)
158 {
159     struct timespec tEnd;
160     if (!isTimerStarted) return 0;
161     isTimerStarted = false;
162     clock_gettime(CLOCK_MONOTONIC, &tEnd);
163     return ((tEnd.tv_sec + tEnd.tv_nsec/1000000000.0) - (tStart.tv_sec + tStart.tv_nsec/1000000000.0)) * 1000000;
164 }
165
166 bool TizenImpl::drag(const int sx, const int sy, const int ex, const int ey,
167                          const int steps, const int durationMs)
168 {
169     int i, j;
170     int _durationUs, _steps, _stepUs;
171     int dur;
172     int consumptionUs;
173
174     if (steps <= 0) _steps = 1;
175     else _steps = steps;
176
177     if (durationMs < MINIMUM_DURATION_DRAG) _durationUs = INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC;
178     else _durationUs = durationMs * MSEC_PER_SEC;
179
180     _stepUs = _durationUs / (_steps +1);
181
182     if (_stepUs < (INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC)) {
183         _steps = (int)(_durationUs / (INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC)) - 1;
184         _stepUs  = (INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC);
185     }
186     LOG_SCOPE_F(INFO, "flicking (%d, %d) -> (%d, %d) for (%d ms)", sx, sy, ex, ey, durationMs);
187     startTimer();
188     int seq = touchDown(sx, sy);
189     if (seq < 0) return false;
190     consumptionUs = stopTimer();
191
192     for ( int s = 1; s <= _steps + 1; s++) {
193         usleep((_stepUs - consumptionUs)>INTV_MINIMUM_USLEEP?(_stepUs - consumptionUs):INTV_MINIMUM_USLEEP);
194         startTimer();
195         touchMove(sx + (ex - sx) * s / (steps + 1), sy + (ey - sy) * s / (steps + 1), seq);
196         consumptionUs = stopTimer();
197     }
198     usleep((_stepUs - consumptionUs)>INTV_MINIMUM_USLEEP?(_stepUs - consumptionUs):INTV_MINIMUM_USLEEP);
199     touchMove(ex, ey, seq);
200     touchUp(ex, ey, seq);
201
202     return true;
203 }
204
205 bool TizenImpl::pressBack(KeyRequestType type)
206 {
207     return pressKeyCode("XF86Back", type);
208 }
209
210 bool TizenImpl::pressHome(KeyRequestType type)
211 {
212     return pressKeyCode("XF86Home", type);
213 }
214
215 bool TizenImpl::pressMenu(KeyRequestType type)
216 {
217     return pressKeyCode("XF86Menu", type);
218 }
219
220 bool TizenImpl::pressVolUp(KeyRequestType type)
221 {
222     return pressKeyCode("XF86AudioRaiseVolume", type);
223 }
224
225 bool TizenImpl::pressVolDown(KeyRequestType type)
226 {
227     return pressKeyCode("XF86AudioLowerVolume", type);
228 }
229
230 bool TizenImpl::pressPower(KeyRequestType type)
231 {
232     return pressKeyCode("XF86PowerOff", type);
233 }
234
235 bool TizenImpl::pressKeyCode(std::string keycode, KeyRequestType type)
236 {
237     if (type == KeyRequestType::STROKE)
238         return strokeKeyCode(keycode, INTV_SHORTSTROKE);
239     else if (type == KeyRequestType::LONG_STROKE)
240         return strokeKeyCode(keycode, INTV_LONGSTROKE);
241     else if (type == KeyRequestType::PRESS)
242         return pressKeyCode(keycode);
243     else if (type == KeyRequestType::RELEASE)
244         return releaseKeyCode(keycode);
245     return false;
246 }
247
248 bool TizenImpl::strokeKeyCode(std::string keycode, unsigned int intv)
249 {
250     pressKeyCode(keycode);
251     usleep(intv * 1000);
252     releaseKeyCode(keycode);
253     return true;
254 }
255
256 bool TizenImpl::pressKeyCode(std::string keycode)
257 {
258     auto args = std::make_tuple(this, keycode);
259     long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
260         TizenImpl *obj;
261         std::string keycode;
262         std::tie(obj, keycode) = *static_cast<std::tuple<TizenImpl*, std::string>*>(data);
263         return (void*)efl_util_input_generate_key(obj->mFakeKeyboardHandle, keycode.c_str(), 1);
264     }, (void*)(&args));
265     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{return NULL;}, NULL);
266     return result == EFL_UTIL_ERROR_NONE;
267 }
268
269 bool TizenImpl::releaseKeyCode(std::string keycode)
270 {
271     auto args = std::make_tuple(this, keycode);
272     long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
273         TizenImpl *obj;
274         std::string keycode;
275         std::tie(obj, keycode) = *static_cast<std::tuple<TizenImpl*, std::string>*>(data);
276         return (void*)efl_util_input_generate_key(obj->mFakeKeyboardHandle, keycode.c_str(), 0);
277     }, (void*)(&args));
278     ecore_main_loop_thread_safe_call_sync([](void *data)->void*{return NULL;}, NULL);
279     return result == EFL_UTIL_ERROR_NONE;
280 }
281
282 bool TizenImpl::takeScreenshot(std::string path, float scale, int quality)
283 {
284     efl_util_screenshot_h screenshot = NULL;
285     tbm_surface_h tbm_surface = NULL;
286
287     int width, height;
288     system_info_get_platform_int("http://tizen.org/feature/screen.width", &width);
289     system_info_get_platform_int("http://tizen.org/feature/screen.height", &height);
290
291     screenshot = efl_util_screenshot_initialize(width, height);
292
293     if (screenshot) {
294         tbm_surface = efl_util_screenshot_take_tbm_surface(screenshot);
295         if (tbm_surface) {
296             char path_cstr[PATH_MAX];
297             strcpy(path_cstr, path.c_str());
298             tdm_helper_dump_buffer(tbm_surface, path_cstr);
299             sync();
300         }
301         efl_util_screenshot_deinitialize(screenshot);
302     }
303
304     return true;
305 }
306
307 class Clock {
308 public:
309     virtual ~Clock(){};
310
311 public:
312     virtual long long getTime() = 0;
313 protected:
314     long long convertTime(struct timespec t){
315         return (long long)t.tv_sec * 1000L + (long long)(t.tv_nsec / 1000000);
316     }
317 };
318
319 class MonotonicClock : public Clock {
320 public:
321     virtual ~MonotonicClock(){};
322
323     long long getTime() override {
324         struct timespec t;
325         clock_gettime(CLOCK_MONOTONIC, &t);
326         return convertTime(t);
327     }
328
329 };
330
331 class WallClock : public Clock {
332 public:
333     virtual ~WallClock(){};
334
335     long long getTime() override {
336         struct timespec t;
337         clock_gettime(CLOCK_REALTIME, &t);
338         return convertTime(t);
339     }
340 };
341
342 long long TizenImpl::getSystemTime(TimeRequestType type)
343 {
344     std::unique_ptr<Clock> clock;
345     if (type == TimeRequestType::MONOTONIC)
346         clock = std::make_unique<MonotonicClock>();
347     else if (type == TimeRequestType::WALLCLOCK)
348         clock = std::make_unique<WallClock>();
349
350     return clock->getTime();
351
352 }
353
354 int TizenImpl::grabTouchSeqNumber()
355 {
356     for (int i = 0 ; i < MAX_FINGER_NUMBER; i++) {
357         if (mTouchSeq.count(i) == 0) {
358             mTouchSeq.insert(i);
359             return i;
360         }
361     }
362     return -1;
363 }
364
365 bool TizenImpl::releaseTouchSeqNumber(int seq)
366 {
367     auto k = mTouchSeq.find(seq);
368     if (k != mTouchSeq.end()) {
369         mTouchSeq.erase(k);
370         return true;
371     }
372     return false;
373 }