1 #include "DeviceImpl/TizenImpl.h"
13 #include <tdm_helper.h>
14 #include <tbm_surface.h>
15 #include <system_info.h>
17 TizenImpl::TizenImpl()
18 : mFakeTouchHandle{0}, mFakeKeyboardHandle{0}, mFakeWheelHandle{0}, isTimerStarted{false}, mTouchSeq{}
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);
31 TizenImpl::~TizenImpl()
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);
42 bool TizenImpl::click(const int x, const int y)
44 return click(x, y, INTV_CLICK);
47 bool TizenImpl::click(const int x, const int y, const unsigned int intv)
49 int seq = touchDown(x, y);
50 if (seq < 0) return false;
51 usleep(intv * MSEC_PER_SEC);
58 int TizenImpl::touchDown(const int x, const int y)
60 int seq = grabTouchSeqNumber();
61 LOG_F(INFO, "touch down %d %d , seq:%d", x, y, seq);
63 auto args = std::make_tuple(this, x, y, seq);
64 long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
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,
73 if (result != EFL_UTIL_ERROR_NONE) {
74 releaseTouchSeqNumber(seq);
81 bool TizenImpl::touchMove(const int x, const int y, const int seq)
83 LOG_F(INFO, "touch move %d %d, seq:%d", x, y, seq);
85 auto args = std::make_tuple(this, x, y, seq);
86 long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
89 std::tie(obj, x, y, seq) = *static_cast<std::tuple<TizenImpl*, int, int, int>*>(data);
91 return (void*)efl_util_input_generate_touch(obj->mFakeTouchHandle, seq, EFL_UTIL_INPUT_TOUCH_UPDATE,
95 return result == EFL_UTIL_ERROR_NONE;
100 bool TizenImpl::touchUp(const int x, const int y, const int seq)
102 LOG_F(INFO, "touch up %d %d, seq:%d", x, y, seq);
104 auto args = std::make_tuple(this, x, y, seq);
105 long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
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,
112 return releaseTouchSeqNumber(seq) && result == EFL_UTIL_ERROR_NONE;
117 bool TizenImpl::wheelUp(int amount, const int durationMs)
119 LOG_F(INFO, "wheel up %d for %d", amount, durationMs);
120 auto args = std::make_tuple(this);
122 for (int i = 0; i < amount; i++){
123 result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
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);
128 usleep(durationMs*MSEC_PER_SEC/amount);
131 return result == EFL_UTIL_ERROR_NONE;
134 bool TizenImpl::wheelDown(int amount, const int durationMs)
136 LOG_F(INFO, "wheel down %d for %d", amount, durationMs);
137 auto args = std::make_tuple(this);
139 for (int i = 0; i < amount; i++){
140 result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
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);
146 usleep(durationMs*MSEC_PER_SEC/amount);
149 return result == EFL_UTIL_ERROR_NONE;
151 void TizenImpl::startTimer(void)
153 isTimerStarted = true;
154 clock_gettime(CLOCK_MONOTONIC, &tStart);
157 int TizenImpl::stopTimer(void)
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;
166 bool TizenImpl::drag(const int sx, const int sy, const int ex, const int ey,
167 const int steps, const int durationMs)
170 int _durationUs, _steps, _stepUs;
174 if (steps <= 0) _steps = 1;
177 if (durationMs < MINIMUM_DURATION_DRAG) _durationUs = INTV_MINIMUM_DRAG_MS * MSEC_PER_SEC;
178 else _durationUs = durationMs * MSEC_PER_SEC;
180 _stepUs = _durationUs / (_steps +1);
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);
186 LOG_SCOPE_F(INFO, "flicking (%d, %d) -> (%d, %d) for (%d ms)", sx, sy, ex, ey, durationMs);
188 int seq = touchDown(sx, sy);
189 if (seq < 0) return false;
190 consumptionUs = stopTimer();
192 for ( int s = 1; s <= _steps + 1; s++) {
193 usleep((_stepUs - consumptionUs)>INTV_MINIMUM_USLEEP?(_stepUs - consumptionUs):INTV_MINIMUM_USLEEP);
195 touchMove(sx + (ex - sx) * s / (steps + 1), sy + (ey - sy) * s / (steps + 1), seq);
196 consumptionUs = stopTimer();
198 usleep((_stepUs - consumptionUs)>INTV_MINIMUM_USLEEP?(_stepUs - consumptionUs):INTV_MINIMUM_USLEEP);
199 touchMove(ex, ey, seq);
200 touchUp(ex, ey, seq);
205 bool TizenImpl::pressBack(KeyRequestType type)
207 return pressKeyCode("XF86Back", type);
210 bool TizenImpl::pressHome(KeyRequestType type)
212 return pressKeyCode("XF86Home", type);
215 bool TizenImpl::pressMenu(KeyRequestType type)
217 return pressKeyCode("XF86Menu", type);
220 bool TizenImpl::pressVolUp(KeyRequestType type)
222 return pressKeyCode("XF86AudioRaiseVolume", type);
225 bool TizenImpl::pressVolDown(KeyRequestType type)
227 return pressKeyCode("XF86AudioLowerVolume", type);
230 bool TizenImpl::pressPower(KeyRequestType type)
232 return pressKeyCode("XF86PowerOff", type);
235 bool TizenImpl::pressKeyCode(std::string keycode, KeyRequestType type)
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);
248 bool TizenImpl::strokeKeyCode(std::string keycode, unsigned int intv)
250 pressKeyCode(keycode);
252 releaseKeyCode(keycode);
256 bool TizenImpl::pressKeyCode(std::string keycode)
258 auto args = std::make_tuple(this, keycode);
259 long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
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);
265 ecore_main_loop_thread_safe_call_sync([](void *data)->void*{return NULL;}, NULL);
266 return result == EFL_UTIL_ERROR_NONE;
269 bool TizenImpl::releaseKeyCode(std::string keycode)
271 auto args = std::make_tuple(this, keycode);
272 long result = (long)ecore_main_loop_thread_safe_call_sync([](void *data)->void*{
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);
278 ecore_main_loop_thread_safe_call_sync([](void *data)->void*{return NULL;}, NULL);
279 return result == EFL_UTIL_ERROR_NONE;
282 bool TizenImpl::takeScreenshot(std::string path, float scale, int quality)
284 efl_util_screenshot_h screenshot = NULL;
285 tbm_surface_h tbm_surface = NULL;
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);
291 screenshot = efl_util_screenshot_initialize(width, height);
294 tbm_surface = efl_util_screenshot_take_tbm_surface(screenshot);
296 char path_cstr[PATH_MAX];
297 strcpy(path_cstr, path.c_str());
298 tdm_helper_dump_buffer(tbm_surface, path_cstr);
301 efl_util_screenshot_deinitialize(screenshot);
312 virtual long long getTime() = 0;
314 long long convertTime(struct timespec t){
315 return (long long)t.tv_sec * 1000L + (long long)(t.tv_nsec / 1000000);
319 class MonotonicClock : public Clock {
321 virtual ~MonotonicClock(){};
323 long long getTime() override {
325 clock_gettime(CLOCK_MONOTONIC, &t);
326 return convertTime(t);
331 class WallClock : public Clock {
333 virtual ~WallClock(){};
335 long long getTime() override {
337 clock_gettime(CLOCK_REALTIME, &t);
338 return convertTime(t);
342 long long TizenImpl::getSystemTime(TimeRequestType type)
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>();
350 return clock->getTime();
354 int TizenImpl::grabTouchSeqNumber()
356 for (int i = 0 ; i < MAX_FINGER_NUMBER; i++) {
357 if (mTouchSeq.count(i) == 0) {
365 bool TizenImpl::releaseTouchSeqNumber(int seq)
367 auto k = mTouchSeq.find(seq);
368 if (k != mTouchSeq.end()) {