1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <getopt.h>
8 #include <unistd.h>
9
10 #include <Eina.h>
11 #include <Eet.h>
12 #include <Ecore.h>
13 #include <Ecore_Getopt.h>
14 #include <Elementary.h>
15
16 #include "common.h"
17
18 #define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
19 #define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
20
21 static int _log_domain = -1;
22
23 static Eina_Stringshare *_src_filename = NULL;
24 static Exactness_Unit *_src_unit = NULL;
25 static int _verbose = 0;
26
27 static Eina_Debug_Session *_session = NULL;
28 static int _cid = -1, _pid = -1;
29 static Eina_List *_cur_event_list = NULL;
30
31 static int _all_apps_get_op = EINA_DEBUG_OPCODE_INVALID;
32 static int _mouse_in_op = EINA_DEBUG_OPCODE_INVALID;
33 static int _mouse_out_op = EINA_DEBUG_OPCODE_INVALID;
34 static int _mouse_wheel_op = EINA_DEBUG_OPCODE_INVALID;
35 static int _multi_down_op = EINA_DEBUG_OPCODE_INVALID;
36 static int _multi_up_op = EINA_DEBUG_OPCODE_INVALID;
37 static int _multi_move_op = EINA_DEBUG_OPCODE_INVALID;
38 static int _key_down_op = EINA_DEBUG_OPCODE_INVALID;
39 static int _key_up_op = EINA_DEBUG_OPCODE_INVALID;
40 static int _take_shot_op = EINA_DEBUG_OPCODE_INVALID;
41 static int _efl_event_op = EINA_DEBUG_OPCODE_INVALID;
42 static int _click_on_op = EINA_DEBUG_OPCODE_INVALID;
43 static int _stabilize_op = EINA_DEBUG_OPCODE_INVALID;
44 static int _finish_op = EINA_DEBUG_OPCODE_INVALID;
45
46 static Eina_Bool _all_apps_get_cb(Eina_Debug_Session *, int , void *, int);
47
48 EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
49 {"Daemon/Client/register_observer", &_all_apps_get_op, NULL},
50 {"Daemon/Client/added", NULL, &_all_apps_get_cb},
51 {"Exactness/Actions/Mouse In", &_mouse_in_op, NULL},
52 {"Exactness/Actions/Mouse Out", &_mouse_out_op, NULL},
53 {"Exactness/Actions/Mouse Wheel", &_mouse_wheel_op, NULL},
54 {"Exactness/Actions/Multi Down", &_multi_down_op, NULL},
55 {"Exactness/Actions/Multi Up", &_multi_up_op, NULL},
56 {"Exactness/Actions/Multi Move", &_multi_move_op, NULL},
57 {"Exactness/Actions/Key Down", &_key_down_op, NULL},
58 {"Exactness/Actions/Key Up", &_key_up_op, NULL},
59 {"Exactness/Actions/Take Shot", &_take_shot_op, NULL},
60 {"Exactness/Actions/EFL Event", &_efl_event_op, NULL},
61 {"Exactness/Actions/Click On", &_click_on_op, NULL},
62 {"Exactness/Actions/Stabilize", &_stabilize_op, NULL},
63 {"Exactness/Actions/Finish", &_finish_op, NULL},
64 {NULL, NULL, NULL}
65 );
66
67 static void
_feed_event(Exactness_Action_Type type,unsigned int n_evas,void * data)68 _feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data)
69 {
70 switch (type)
71 {
72 case EXACTNESS_ACTION_MOUSE_IN:
73 {
74 INF("Mouse in\n");
75 DBG("%s evas_event_feed_mouse_in n_evas=<%d>\n", __func__, n_evas);
76 eina_debug_session_send(_session, _cid, _mouse_in_op, &n_evas, sizeof(int));
77 break;
78 }
79 case EXACTNESS_ACTION_MOUSE_OUT:
80 {
81 INF("Mouse out\n");
82 DBG("%s evas_event_feed_mouse_out n_evas=<%d>\n", __func__, n_evas);
83 eina_debug_session_send(_session, _cid, _mouse_out_op, &n_evas, sizeof(int));
84 break;
85 }
86 case EXACTNESS_ACTION_MOUSE_WHEEL:
87 {
88 Exactness_Action_Mouse_Wheel *t = data;
89 int len = 3*sizeof(int);
90 char *buf = malloc(len), *tmp = buf;
91 INF("Mouse wheel\n");
92 DBG("%s evas_event_feed_mouse_wheel n_evas=<%d>\n", __func__, n_evas);
93 STORE_INT(tmp, n_evas);
94 STORE_INT(tmp, t->direction);
95 STORE_INT(tmp, t->z);
96 eina_debug_session_send(_session, _cid, _mouse_wheel_op, buf, len);
97 free(buf);
98 break;
99 }
100 case EXACTNESS_ACTION_MULTI_DOWN:
101 case EXACTNESS_ACTION_MULTI_UP:
102 {
103 Exactness_Action_Multi_Event *t = data;
104 int len = 5*sizeof(int)+7*sizeof(double)+sizeof(int);
105 char *buf = malloc(len), *tmp = buf;
106 DBG("%s %s n_evas=<%d>\n", __func__,
107 type == EXACTNESS_ACTION_MULTI_DOWN ? "evas_event_feed_multi_down" :
108 "evas_event_feed_multi_up", n_evas);
109 STORE_INT(tmp, n_evas);
110 STORE_INT(tmp, t->d);
111 STORE_INT(tmp, t->b);
112 STORE_INT(tmp, t->x);
113 STORE_INT(tmp, t->y);
114 STORE_DOUBLE(tmp, t->rad);
115 STORE_DOUBLE(tmp, t->radx);
116 STORE_DOUBLE(tmp, t->rady);
117 STORE_DOUBLE(tmp, t->pres);
118 STORE_DOUBLE(tmp, t->ang);
119 STORE_DOUBLE(tmp, t->fx);
120 STORE_DOUBLE(tmp, t->fy);
121 STORE_INT(tmp, t->flags);
122 eina_debug_session_send(_session, _cid,
123 type == EXACTNESS_ACTION_MULTI_DOWN ? _multi_down_op : _multi_up_op,
124 buf, len);
125 free(buf);
126 break;
127 }
128 case EXACTNESS_ACTION_MULTI_MOVE:
129 {
130 Exactness_Action_Multi_Move *t = data;
131 int len = 4*sizeof(int)+7*sizeof(double);
132 char *buf = malloc(len), *tmp = buf;
133 DBG("%s evas_event_feed_multi_move n_evas=<%d>\n", __func__, n_evas);
134 STORE_INT(tmp, n_evas);
135 STORE_INT(tmp, t->d);
136 STORE_INT(tmp, t->x);
137 STORE_INT(tmp, t->y);
138 STORE_DOUBLE(tmp, t->rad);
139 STORE_DOUBLE(tmp, t->radx);
140 STORE_DOUBLE(tmp, t->rady);
141 STORE_DOUBLE(tmp, t->pres);
142 STORE_DOUBLE(tmp, t->ang);
143 STORE_DOUBLE(tmp, t->fx);
144 STORE_DOUBLE(tmp, t->fy);
145 eina_debug_session_send(_session, _cid, _multi_move_op, buf, len);
146 free(buf);
147 break;
148 }
149 case EXACTNESS_ACTION_KEY_DOWN:
150 case EXACTNESS_ACTION_KEY_UP:
151 {
152 Exactness_Action_Key_Down_Up *t = data;
153 int len = 2*sizeof(int) + 4 + 1;
154 len += t->keyname ? strlen(t->keyname) : 0;
155 len += t->key ? strlen(t->key) : 0;
156 len += t->string ? strlen(t->string) : 0;
157 len += t->compose ? strlen(t->compose) : 0;
158 char *buf = malloc(len), *tmp = buf;
159 DBG("%s %s n_evas=<%d>\n", __func__,
160 type == EXACTNESS_ACTION_KEY_DOWN ? "evas_event_feed_key_down " :
161 "evas_event_feed_key_up", n_evas);
162 STORE_INT(tmp, n_evas);
163 STORE_STRING(tmp, t->keyname);
164 STORE_STRING(tmp, t->key);
165 STORE_STRING(tmp, t->string);
166 STORE_STRING(tmp, t->compose);
167 STORE_INT(tmp, t->keycode);
168 eina_debug_session_send(_session, _cid,
169 type == EXACTNESS_ACTION_KEY_DOWN ? _key_down_op : _key_up_op,
170 buf, len);
171 free(buf);
172 break;
173 }
174 case EXACTNESS_ACTION_TAKE_SHOT:
175 {
176 DBG("%s take shot n_evas=<%d>\n", __func__, n_evas);
177 eina_debug_session_send(_session, _cid, _take_shot_op, &n_evas, sizeof(int));
178 break;
179 }
180 case EXACTNESS_ACTION_EFL_EVENT:
181 {
182 Exactness_Action_Efl_Event *t = data;
183 int len = 2;
184 len += t->wdg_name ? strlen(t->wdg_name) : 0;
185 len += t->event_name ? strlen(t->event_name) : 0;
186 char *buf = malloc(len), *tmp = buf;
187 DBG("%s %s\n", __func__, "EFL event");
188 STORE_STRING(tmp, t->wdg_name);
189 STORE_STRING(tmp, t->event_name);
190 eina_debug_session_send(_session, _cid, _efl_event_op, buf, len);
191 free(buf);
192 break;
193 }
194 case EXACTNESS_ACTION_CLICK_ON:
195 {
196 Exactness_Action_Click_On *t = data;
197 int len = 1;
198 len += t->wdg_name ? strlen(t->wdg_name) : 0;
199 char *buf = malloc(len), *tmp = buf;
200 DBG("%s %s\n", __func__, "Click On");
201 STORE_STRING(tmp, t->wdg_name);
202 eina_debug_session_send(_session, _cid, _click_on_op, buf, len);
203 free(buf);
204 break;
205 }
206 case EXACTNESS_ACTION_STABILIZE:
207 {
208 DBG("%s stabilize\n", __func__);
209 eina_debug_session_send(_session, _cid, _stabilize_op, NULL, 0);
210 break;
211 }
212 default: /* All non-input events are not handeled */
213 break;
214 }
215 }
216
217 static Eina_Bool
_feed_event_timer_cb(void * data EINA_UNUSED)218 _feed_event_timer_cb(void *data EINA_UNUSED)
219 {
220 Exactness_Action *act = eina_list_data_get(_cur_event_list);
221 _feed_event(act->type, act->n_evas, act->data);
222
223 _cur_event_list = eina_list_next(_cur_event_list);
224
225 if (!_cur_event_list)
226 { /* Finished reading all events */
227 eina_debug_session_send(_session, _cid, _finish_op, NULL, 0);
228 ecore_main_loop_quit();
229 }
230 else
231 {
232 Exactness_Action *cur_act = eina_list_data_get(_cur_event_list);
233 ecore_timer_add(cur_act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
234 }
235 return ECORE_CALLBACK_CANCEL;
236 }
237
238 static Eina_Bool
_src_open()239 _src_open()
240 {
241 double diff_time = 0; /* Time to wait before feeding the first event */
242
243 DBG("<%s> Source file is <%s>\n", __func__, _src_filename);
244 if (!strcmp(_src_filename + strlen(_src_filename) - 4,".exu"))
245 {
246 _src_unit = exactness_unit_file_read(_src_filename);
247 }
248 if (!_src_unit) return EINA_FALSE;
249 _cur_event_list = _src_unit->actions;
250 Exactness_Action *act = eina_list_data_get(_cur_event_list);
251
252 if (act->delay_ms)
253 {
254 DBG(" Waiting <%f>\n", diff_time);
255 ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
256 }
257 else
258 {
259 _feed_event_timer_cb(NULL);
260 }
261 return EINA_TRUE;
262 }
263
264 static void
_main_loop_all_apps_get_cb(Eina_Debug_Session * session EINA_UNUSED,int srcid EINA_UNUSED,void * buffer,int size EINA_UNUSED)265 _main_loop_all_apps_get_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
266 {
267 char *buf = buffer;
268 int chosen_cid = -1;
269 if (_cid != -1) return;
270 while (size > 0)
271 {
272 int cid, pid, len;
273 cid = EXTRACT_INT(buf);
274 pid = EXTRACT_INT(buf);
275 if (_pid != -1)
276 {
277 if (_pid == pid)
278 {
279 _cid = cid;
280 _src_open();
281 return;
282 }
283 }
284 else
285 {
286 if (!strcmp(buf, "exactness_play"))
287 {
288 if (chosen_cid != -1)
289 {
290 fprintf(stderr, "Need to specify a PID - too much choice\n");
291 return;
292 }
293 chosen_cid = cid;
294 }
295 }
296 len = strlen(buf) + 1;
297 buf += len;
298 size -= (2 * sizeof(int) + len);
299 }
300 if (chosen_cid != -1)
301 {
302 _cid = chosen_cid;
303 _src_open();
304 }
305 }
306
WRAPPER_TO_XFER_MAIN_LOOP(_all_apps_get_cb)307 WRAPPER_TO_XFER_MAIN_LOOP(_all_apps_get_cb)
308
309 static void
310 _ops_ready_cb(void *data EINA_UNUSED, Eina_Bool status)
311 {
312 if (status)
313 eina_debug_session_send(_session, 0, _all_apps_get_op, NULL, 0);
314 }
315
316 static const Ecore_Getopt optdesc = {
317 "exactness_inject",
318 "%prog [options] <-v|-p|-t|-h> command",
319 PACKAGE_VERSION,
320 "(C) 2018 Enlightenment",
321 "BSD",
322 "A scenario events injector for EFL based applications.",
323 1,
324 {
325 ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
326 ECORE_GETOPT_STORE_INT('p', "pid", "PID of the application to connect to"),
327 ECORE_GETOPT_STORE_INT('r', "remote-port", "Port to connect remotely to the daemon. Local connection if not specified"),
328 ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
329
330 ECORE_GETOPT_LICENSE('L', "license"),
331 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
332 ECORE_GETOPT_VERSION('V', "version"),
333 ECORE_GETOPT_HELP('h', "help"),
334 ECORE_GETOPT_SENTINEL
335 }
336 };
337
main(int argc,char ** argv)338 int main(int argc, char **argv)
339 {
340 int opt_args = 0, real__ = 1, port = -1;
341 char *src = NULL;
342 Eina_Value *ret__;
343 Eina_Bool want_quit = EINA_FALSE;
344
345 Ecore_Getopt_Value values[] = {
346 ECORE_GETOPT_VALUE_STR(src),
347 ECORE_GETOPT_VALUE_INT(_pid),
348 ECORE_GETOPT_VALUE_INT(port),
349 ECORE_GETOPT_VALUE_INT(_verbose),
350
351 ECORE_GETOPT_VALUE_BOOL(want_quit),
352 ECORE_GETOPT_VALUE_BOOL(want_quit),
353 ECORE_GETOPT_VALUE_BOOL(want_quit),
354 ECORE_GETOPT_VALUE_BOOL(want_quit),
355 ECORE_GETOPT_VALUE_NONE
356 };
357
358 _log_domain = eina_log_domain_register("exactness_injector", NULL);
359
360 if (!ecore_evas_init())
361 return EXIT_FAILURE;
362
363 opt_args = ecore_getopt_parse(&optdesc, values, argc, argv);
364 if (opt_args < 0)
365 {
366 fprintf(stderr, "Failed parsing arguments.\n");
367 goto end;
368 }
369 if (want_quit) goto end;
370
371 if (!src)
372 {
373 fprintf(stderr, "no test file specified\n");
374 goto end;
375 }
376 _src_filename = eina_stringshare_add(src);
377
378 if (port == -1)
379 _session = eina_debug_local_connect(EINA_TRUE);
380 else
381 _session = eina_debug_remote_connect(port);
382 eina_debug_opcodes_register(_session, _debug_ops(), _ops_ready_cb, NULL);
383
384 elm_init(argc, argv);
385 ret__ = efl_loop_begin(efl_main_loop_get());
386 real__ = efl_loop_exit_code_process(ret__);
387 elm_shutdown();
388 end:
389 ecore_evas_shutdown();
390 eina_log_domain_unregister(_log_domain);
391 _log_domain = -1;
392 return real__;
393 }
394