aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/edje/src/bin/edje_player.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/edje/src/bin/edje_player.c')
-rw-r--r--libraries/edje/src/bin/edje_player.c795
1 files changed, 795 insertions, 0 deletions
diff --git a/libraries/edje/src/bin/edje_player.c b/libraries/edje/src/bin/edje_player.c
new file mode 100644
index 0000000..4d0c0a3
--- /dev/null
+++ b/libraries/edje/src/bin/edje_player.c
@@ -0,0 +1,795 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <stdio.h>
6#include <string.h>
7#include <stdlib.h>
8#include <errno.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <ctype.h>
12
13#ifdef HAVE_EVIL
14# include <Evil.h>
15#endif
16
17#include <Evas.h>
18#include <Ecore.h>
19#include <Ecore_Getopt.h>
20#include <Ecore_Evas.h>
21#include <Edje.h>
22
23#ifdef _WIN32
24# define FMT_UCHAR "%c"
25#else
26# define FMT_UCHAR "%hhu"
27#endif
28
29struct opts {
30 char *file;
31 char *group;
32 Eina_Bool list_groups;
33 char *engine;
34 Eina_Rectangle size;
35 unsigned char color[3];
36 Eina_Bool borderless;
37 Eina_Bool sticky;
38 Eina_Bool shaped;
39 Eina_Bool alpha;
40 Eina_Bool print;
41 Eina_Bool slave_mode;
42 double scale;
43 char *title;
44};
45
46static Ecore_Evas *win;
47
48static void
49_win_title_set(const char *group, const char *file)
50{
51 char buf[1024];
52 snprintf(buf, sizeof(buf), "Edje_Player - %s of %s", group, file);
53 ecore_evas_title_set(win, buf);
54}
55
56static char *
57_slave_mode_tok(char **p_arg)
58{
59 char *s, *e;
60 Eina_Bool is_quoted;
61
62 if (!*p_arg) return NULL;
63
64 s = *p_arg;
65 while (isspace(*s))
66 s++;
67
68 if (*s == '\0')
69 {
70 *p_arg = NULL;
71 return NULL;
72 }
73 else if (*s == '"')
74 {
75 is_quoted = EINA_TRUE;
76 s++;
77 *p_arg = s;
78 }
79 else
80 {
81 is_quoted = EINA_FALSE;
82 *p_arg = s;
83 }
84
85 for (e = s; *e != '\0'; e++)
86 {
87 if ((!is_quoted) && (isspace(*e)))
88 break;
89 else if ((is_quoted) && (*e == '"'))
90 break;
91 }
92
93 if (*e == '\0') return NULL;
94
95 *e = '\0';
96 return e + 1;
97}
98
99static void
100_slave_mode_signal(Evas_Object *edje, char *args)
101{
102 char *emission, *source;
103
104 emission = args;
105 source = _slave_mode_tok(&emission);
106 _slave_mode_tok(&source);
107
108 if ((!emission) || (!source))
109 {
110 fputs("ERROR: Invalid command arguments.\n", stderr);
111 return;
112 }
113
114 edje_object_signal_emit(edje, emission, source);
115}
116
117static void
118_slave_mode_info(Evas_Object *edje, char *args)
119{
120 _slave_mode_tok(&args);
121
122 if (!args)
123 {
124 fputs("ERROR: Invalid command arguments.\n", stderr);
125 return;
126 }
127
128 if (!edje_object_part_exists(edje, args))
129 {
130 printf("INFO: \"%s\" does not exist.\n", args);
131 }
132 else
133 {
134 Evas_Coord x, y, w, h;
135 edje_object_part_geometry_get(edje, args, &x, &y, &w, &h);
136 printf("INFO: \"%s\" %d,%d,%d,%d\n", args, x, y, w, h);
137 }
138}
139
140static void
141_slave_mode_quit(Evas_Object *edje __UNUSED__, char *args __UNUSED__)
142{
143 puts("Bye!");
144 ecore_main_loop_quit();
145}
146
147static void
148_slave_mode_help(Evas_Object *edje __UNUSED__, char *args __UNUSED__)
149{
150 puts("Help:\n"
151 "One command per line, arguments separated by space. Strings may have "
152 "spaces if enclosed in quotes (\").\n"
153 "\n"
154 "\t<command> [arguments]\n"
155 "\n"
156 "Available commands:\n"
157 "\tsignal <emission> <source>\n"
158 "\t sends a signal to edje\n"
159 "\tinfo <part>\n"
160 "\t Print part geometry: <x>,<y>,<w>,<h>\n"
161 "\tquit\n"
162 "\t exit edje player.\n"
163 "\thelp\n"
164 "\t shows this message.\n");
165 /*
166 * Extension ideas (are they useful?):
167 * - message: send a message
168 * - data: show data value
169 * - color_class: set color class values (maybe also list?)
170 * - text_class: set text class values (maybe also list?)
171 * - play_set: change play state
172 * - animation_set: change animation state
173 */
174}
175
176struct slave_cmd
177{
178 const char *cmd;
179 void (*func)(Evas_Object *edje, char *args);
180} _slave_mode_commands[] = {
181 {"signal", _slave_mode_signal},
182 {"info", _slave_mode_info},
183 {"quit", _slave_mode_quit},
184 {"help", _slave_mode_help},
185 {NULL, NULL}
186};
187
188static Eina_Bool
189_slave_mode(void *data, Ecore_Fd_Handler *fd_handler)
190{
191 Evas_Object *edje = data;
192 char buf[1024], *p;
193 const struct slave_cmd *itr;
194 size_t len;
195
196 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
197 {
198 fputs("ERROR: error on stdin! Exit.\n", stderr);
199 ecore_main_loop_quit();
200 return ECORE_CALLBACK_CANCEL;
201 }
202 if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
203 return ECORE_CALLBACK_RENEW;
204
205 if (!fgets(buf, sizeof(buf), stdin))
206 {
207 fputs("ERROR: end of stdin! Exit.\n", stderr);
208 ecore_main_loop_quit();
209 return ECORE_CALLBACK_CANCEL;
210 }
211
212 len = strlen(buf);
213 if (len < 1)
214 {
215 fputs("ERROR: no input! Try: help\n", stderr);
216 return ECORE_CALLBACK_RENEW;
217 }
218 if (buf[len - 1] == '\n')
219 {
220 len--;
221 buf[len] = '\0';
222 }
223
224 p = strchr(buf, ' ');
225 if (p)
226 {
227 *p = '\0';
228 p++;
229
230 while (isspace(*p))
231 p++;
232 if (*p == '\0')
233 p = NULL;
234
235 if (p)
236 {
237 char *q = p + strlen(p) - 1;
238 while (isspace(*q))
239 {
240 *q = '\0';
241 q--;
242 }
243 }
244 }
245
246 for (itr = _slave_mode_commands; itr->cmd; itr++)
247 {
248 if (strcmp(itr->cmd, buf) == 0)
249 {
250 itr->func(edje, p);
251 break;
252 }
253 }
254
255 return ECORE_CALLBACK_RENEW;
256}
257
258static void
259_print_signal(void *data __UNUSED__, Evas_Object *o __UNUSED__, const char *emission, const char *source)
260{
261 printf("SIGNAL: \"%s\" \"%s\"\n", emission, source);
262}
263
264static void
265_print_message(void *data __UNUSED__, Evas_Object *edje __UNUSED__, Edje_Message_Type type, int id, void *msg)
266{
267 const char *typestr;
268 char buf[64];
269
270 switch (type)
271 {
272 case EDJE_MESSAGE_NONE:
273 typestr = "NONE";
274 break;
275 case EDJE_MESSAGE_SIGNAL:
276 typestr = "SIGNAL";
277 break;
278 case EDJE_MESSAGE_STRING:
279 typestr = "STRING";
280 break;
281 case EDJE_MESSAGE_INT:
282 typestr = "INT";
283 break;
284 case EDJE_MESSAGE_FLOAT:
285 typestr = "FLOAT";
286 break;
287 case EDJE_MESSAGE_STRING_SET:
288 typestr = "STRING_SET";
289 break;
290 case EDJE_MESSAGE_INT_SET:
291 typestr = "INT_SET";
292 break;
293 case EDJE_MESSAGE_FLOAT_SET:
294 typestr = "FLOAT_SET";
295 break;
296 case EDJE_MESSAGE_STRING_INT:
297 typestr = "STRING_INT";
298 break;
299 case EDJE_MESSAGE_STRING_FLOAT:
300 typestr = "STRING_FLOAT";
301 break;
302 case EDJE_MESSAGE_STRING_INT_SET:
303 typestr = "INT_SET";
304 break;
305 case EDJE_MESSAGE_STRING_FLOAT_SET:
306 typestr = "FLOAT_SET";
307 break;
308 default:
309 snprintf(buf, sizeof(buf), "UNKNOWN(%d)", type);
310 typestr = buf;
311 }
312
313 printf("MESSAGE: type=%s, id=%d", typestr, id);
314
315 switch (type)
316 {
317 case EDJE_MESSAGE_NONE: break;
318 case EDJE_MESSAGE_SIGNAL: break;
319 case EDJE_MESSAGE_STRING:
320 {
321 Edje_Message_String *m = msg;
322 printf(" \"%s\"", m->str);
323 }
324 break;
325 case EDJE_MESSAGE_INT:
326 {
327 Edje_Message_Int *m = msg;
328 printf(" %d", m->val);
329 }
330 break;
331 case EDJE_MESSAGE_FLOAT:
332 {
333 Edje_Message_Float *m = msg;
334 printf(" %f", m->val);
335 }
336 break;
337 case EDJE_MESSAGE_STRING_SET:
338 {
339 Edje_Message_String_Set *m = msg;
340 int i;
341 for (i = 0; i < m->count; i++)
342 printf(" \"%s\"", m->str[i]);
343 }
344 break;
345 case EDJE_MESSAGE_INT_SET:
346 {
347 Edje_Message_Int_Set *m = msg;
348 int i;
349 for (i = 0; i < m->count; i++)
350 printf(" %d", m->val[i]);
351 }
352 break;
353 case EDJE_MESSAGE_FLOAT_SET:
354 {
355 Edje_Message_Float_Set *m = msg;
356 int i;
357 for (i = 0; i < m->count; i++)
358 printf(" %f", m->val[i]);
359 }
360 break;
361 case EDJE_MESSAGE_STRING_INT:
362 {
363 Edje_Message_String_Int *m = msg;
364 printf(" \"%s\" %d", m->str, m->val);
365 }
366 break;
367 case EDJE_MESSAGE_STRING_FLOAT:
368 {
369 Edje_Message_String_Float *m = msg;
370 printf(" \"%s\" %f", m->str, m->val);
371 }
372 break;
373 case EDJE_MESSAGE_STRING_INT_SET:
374 {
375 Edje_Message_String_Int_Set *m = msg;
376 int i;
377 printf(" \"%s\"", m->str);
378 for (i = 0; i < m->count; i++)
379 printf(" %d", m->val[i]);
380 }
381 break;
382 case EDJE_MESSAGE_STRING_FLOAT_SET:
383 {
384 Edje_Message_String_Float_Set *m = msg;
385 int i;
386 printf(" \"%s\"", m->str);
387 for (i = 0; i < m->count; i++)
388 printf(" %f", m->val[i]);
389 }
390 break;
391 default:
392 break;
393 }
394
395 putchar('\n');
396}
397
398static void
399_reset_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *stack, void *event_info __UNUSED__)
400{
401 Evas_Coord minw, minh;
402 Evas_Object *edje = data;
403
404 edje_object_size_min_get(edje, &minw, &minh);
405 if ((minw <= 0) && (minh <= 0))
406 edje_object_size_min_calc(edje, &minw, &minh);
407
408 evas_object_size_hint_min_set(stack, minw, minh);
409}
410
411static void
412_key_down(void *data, Evas *e __UNUSED__, Evas_Object *stack __UNUSED__, void *event_info)
413{
414 Evas_Event_Key_Down *ev = event_info;
415 struct opts *opts = data;
416
417 if ((!strcmp(ev->keyname, "equal")) ||
418 (!strcmp(ev->keyname, "plus")))
419 opts->scale += 0.1;
420 else if ((!strcmp(ev->keyname, "minus")) ||
421 (!strcmp(ev->keyname, "underscore")))
422 opts->scale -= 0.1;
423 else if ((!strcmp(ev->keyname, "0")))
424 opts->scale = 1.0;
425 if (opts->scale < 0.1) opts->scale = 0.1;
426 else if (opts->scale > 10.0) opts->scale = 1.0;
427 edje_scale_set(opts->scale);
428}
429
430static Evas_Object *
431_create_stack(Evas *evas, const struct opts *opts)
432{
433 Evas_Object *stack = evas_object_box_add(evas);
434 if (!stack)
435 {
436 fputs("ERROR: could not create object stack (box).\n", stderr);
437 return NULL;
438 }
439 evas_object_box_layout_set(stack, evas_object_box_layout_stack, NULL, NULL);
440 evas_object_resize(stack, opts->size.w, opts->size.h);
441 evas_object_size_hint_weight_set(stack, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
442 evas_object_size_hint_align_set(stack, EVAS_HINT_FILL, EVAS_HINT_FILL);
443 evas_object_show(stack);
444 return stack;
445}
446
447static Evas_Object *
448_create_bg(Evas *evas, const struct opts *opts)
449{
450 const unsigned char *color = opts->color;
451 Evas_Object *bg = evas_object_rectangle_add(evas);
452 if (!bg)
453 {
454 fputs("ERROR: could not create background.\n", stderr);
455 return NULL;
456 }
457 evas_object_resize(bg, opts->size.w, opts->size.h);
458 evas_object_color_set(bg, color[0], color[1], color[2], 255);
459 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
460 evas_object_size_hint_align_set(bg, EVAS_HINT_FILL, EVAS_HINT_FILL);
461 evas_object_show(bg);
462 return bg;
463}
464
465static Eina_Bool
466_edje_load_or_show_error(Evas_Object *edje, const char *file, const char *group)
467{
468 const char *errmsg;
469 int err;
470
471 if (edje_object_file_set(edje, file, group))
472 {
473 evas_object_focus_set(edje, EINA_TRUE);
474 return EINA_TRUE;
475 }
476
477 err = edje_object_load_error_get(edje);
478 errmsg = edje_load_error_str(err);
479 fprintf(stderr, "ERROR: could not load edje file '%s', group '%s': %s\n",
480 file, group, errmsg);
481 return EINA_FALSE;
482}
483
484static Evas_Object *
485_create_edje(Evas *evas, const struct opts *opts)
486{
487 Evas_Coord minw, minh, maxw, maxh;
488 Evas_Object *edje = edje_object_add(evas);
489 if (!edje)
490 {
491 fputs("ERROR: could not create edje.\n", stderr);
492 return NULL;
493 }
494
495 if (opts->group)
496 {
497 if (!_edje_load_or_show_error(edje, opts->file, opts->group))
498 {
499 evas_object_del(edje);
500 return NULL;
501 }
502 if (!opts->title) _win_title_set(opts->group, opts->file);
503 }
504 else
505 {
506 if (edje_file_group_exists(opts->file, "main"))
507 {
508 if (!_edje_load_or_show_error(edje, opts->file, "main"))
509 {
510 evas_object_del(edje);
511 return NULL;
512 }
513 if (!opts->title) _win_title_set("main", opts->file);
514 }
515 else
516 {
517 Eina_List *groups = edje_file_collection_list(opts->file);
518 const char *group;
519 if (!groups)
520 {
521 fprintf(stderr, "ERROR: file '%s' has no groups!\n",
522 opts->file);
523 evas_object_del(edje);
524 return NULL;
525 }
526 group = groups->data;
527 if (!_edje_load_or_show_error(edje, opts->file, group))
528 {
529 edje_file_collection_list_free(groups);
530 evas_object_del(edje);
531 return NULL;
532 }
533 if (!opts->title) _win_title_set(group, opts->file);
534 edje_file_collection_list_free(groups);
535 }
536 }
537
538 edje_object_size_max_get(edje, &maxw, &maxh);
539 edje_object_size_min_get(edje, &minw, &minh);
540 if ((minw <= 0) && (minh <= 0))
541 edje_object_size_min_calc(edje, &minw, &minh);
542
543 evas_object_size_hint_max_set(edje, maxw, maxh);
544 evas_object_size_hint_min_set(edje, minw, minh);
545
546 evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
547 evas_object_size_hint_align_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
548 evas_object_show(edje);
549
550 return edje;
551}
552
553static unsigned char _parse_color(__UNUSED__ const Ecore_Getopt *parser, __UNUSED__ const Ecore_Getopt_Desc *desc, const char *str, __UNUSED__ void *data, Ecore_Getopt_Value *storage)
554{
555 unsigned char *color = (unsigned char *)storage->ptrp;
556
557 if (sscanf(str, FMT_UCHAR "," FMT_UCHAR "," FMT_UCHAR, color, color + 1, color + 2) != 3)
558 {
559 fprintf(stderr, "ERROR: incorrect color value '%s'\n", str);
560 return 0;
561 }
562
563 return 1;
564}
565
566static void _cb_delete(__UNUSED__ Ecore_Evas *ee)
567{
568 ecore_main_loop_quit();
569}
570
571const Ecore_Getopt optdesc = {
572 "edje_player",
573 "%prog [options] <filename.edj>",
574 PACKAGE_VERSION,
575 "(C) 2010 Enlightenment",
576 "BSD with advertisement clause",
577 "Simple application to view edje files.",
578 0,
579 {
580 ECORE_GETOPT_STORE_STR
581 ('g', "group", "The edje group to view (defaults to 'main')."),
582 ECORE_GETOPT_STORE_TRUE
583 ('G', "list-groups", "The groups in the given file."),
584 ECORE_GETOPT_STORE_STR
585 ('e', "engine", "The Ecore-Evas engine to use (see --list-engines)"),
586 ECORE_GETOPT_CALLBACK_NOARGS
587 ('E', "list-engines", "list Ecore-Evas engines",
588 ecore_getopt_callback_ecore_evas_list_engines, NULL),
589 ECORE_GETOPT_CALLBACK_ARGS
590 ('Z', "size", "size to use in wxh form.", "WxH",
591 ecore_getopt_callback_size_parse, NULL),
592 ECORE_GETOPT_CALLBACK_ARGS
593 ('c', "bg-color", "Color of the background (if not shaped or alpha)",
594 "RRGGBB", _parse_color, NULL),
595 ECORE_GETOPT_STORE_TRUE
596 ('b', "borderless", "Display window without border."),
597 ECORE_GETOPT_STORE_TRUE
598 ('y', "sticky", "Display window sticky."),
599 ECORE_GETOPT_STORE_TRUE
600 ('s', "shaped", "Display window shaped."),
601 ECORE_GETOPT_STORE_TRUE
602 ('a', "alpha", "Display window with alpha channel "
603 "(needs composite manager!)"),
604 ECORE_GETOPT_STORE_STR
605 ('t', "title", "Define the window title string"),
606 ECORE_GETOPT_STORE_TRUE
607 ('p', "print", "Print signals and messages to stdout"),
608 ECORE_GETOPT_STORE_TRUE
609 ('S', "slave-mode", "Listen for commands on stdin"),
610 ECORE_GETOPT_STORE_DOUBLE
611 ('z', "scale", "Set scale factor"),
612 ECORE_GETOPT_LICENSE('L', "license"),
613 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
614 ECORE_GETOPT_VERSION('V', "version"),
615 ECORE_GETOPT_HELP('h', "help"),
616 ECORE_GETOPT_SENTINEL
617 }
618};
619
620int main(int argc, char **argv)
621{
622 Evas *evas;
623 Evas_Object *stack, *edje;
624 struct opts opts;
625 Eina_Bool quit_option = EINA_FALSE;
626 int args;
627 Ecore_Getopt_Value values[] = {
628 ECORE_GETOPT_VALUE_STR(opts.group),
629 ECORE_GETOPT_VALUE_BOOL(opts.list_groups),
630 ECORE_GETOPT_VALUE_STR(opts.engine),
631 ECORE_GETOPT_VALUE_BOOL(quit_option),
632 ECORE_GETOPT_VALUE_PTR_CAST(opts.size),
633 ECORE_GETOPT_VALUE_PTR_CAST(opts.color),
634 ECORE_GETOPT_VALUE_BOOL(opts.borderless),
635 ECORE_GETOPT_VALUE_BOOL(opts.sticky),
636 ECORE_GETOPT_VALUE_BOOL(opts.shaped),
637 ECORE_GETOPT_VALUE_BOOL(opts.alpha),
638 ECORE_GETOPT_VALUE_STR(opts.title),
639 ECORE_GETOPT_VALUE_BOOL(opts.print),
640 ECORE_GETOPT_VALUE_BOOL(opts.slave_mode),
641 ECORE_GETOPT_VALUE_DOUBLE(opts.scale),
642 ECORE_GETOPT_VALUE_BOOL(quit_option),
643 ECORE_GETOPT_VALUE_BOOL(quit_option),
644 ECORE_GETOPT_VALUE_BOOL(quit_option),
645 ECORE_GETOPT_VALUE_BOOL(quit_option),
646 ECORE_GETOPT_VALUE_NONE
647 };
648
649 memset(&opts, 0, sizeof(opts));
650 opts.scale = 1.0;
651
652 if (!ecore_evas_init())
653 return EXIT_FAILURE;
654 if (!edje_init())
655 goto shutdown_ecore_evas;
656 edje_frametime_set(1.0/60.0);
657
658 args = ecore_getopt_parse(&optdesc, values, argc, argv);
659 if (args < 0)
660 {
661 fputs("Could not parse arguments.\n", stderr);
662 goto shutdown_edje;
663 }
664 else if (quit_option)
665 {
666 goto end;
667 }
668 else if (args >= argc)
669 {
670 fputs("Missing edje file to load.\n", stderr);
671 goto shutdown_edje;
672 }
673
674 ecore_app_args_set(argc, (const char **)argv);
675 edje_scale_set(opts.scale);
676
677 // check if the given edj file is there
678 if (access(argv[args], R_OK) == -1)
679 {
680 int e = errno;
681 fprintf(stderr, "ERROR: file '%s' not accessible, error %d (%s).\n",
682 argv[args], e, strerror(e));
683 goto end;
684 }
685
686 opts.file = argv[args];
687 if (opts.list_groups)
688 {
689 Eina_List *groups, *n;
690 const char *group;
691 groups = edje_file_collection_list(opts.file);
692 printf("%d groups in file '%s':\n", eina_list_count(groups), opts.file);
693 EINA_LIST_FOREACH(groups, n, group)
694 printf("\t'%s'\n", group);
695 edje_file_collection_list_free(groups);
696 goto end;
697 }
698
699 win = ecore_evas_new(opts.engine, 0, 0, opts.size.w, opts.size.h, NULL);
700 if (!win)
701 {
702 fprintf(stderr,
703 "ERROR: could not create window of "
704 "size %dx%d using engine %s.\n",
705 opts.size.w, opts.size.h, opts.engine ? opts.engine : "(auto)");
706 goto shutdown_edje;
707 }
708
709 ecore_evas_callback_delete_request_set(win, _cb_delete);
710 evas = ecore_evas_get(win);
711 stack = _create_stack(evas, &opts);
712 if (!stack)
713 {
714 goto free_ecore_evas;
715 }
716
717 ecore_evas_object_associate(win, stack, ECORE_EVAS_OBJECT_ASSOCIATE_BASE);
718
719 if (opts.alpha)
720 ecore_evas_alpha_set(win, EINA_TRUE);
721 else if (opts.shaped)
722 ecore_evas_shaped_set(win, EINA_TRUE);
723 else
724 {
725 Evas_Object *bg = _create_bg(evas, &opts);
726 if (bg) evas_object_box_append(stack, bg);
727 }
728
729 edje = _create_edje(evas, &opts);
730 if (edje)
731 evas_object_box_append(stack, edje);
732 else
733 {
734 goto free_ecore_evas;
735 }
736
737 evas_object_focus_set(stack, EINA_TRUE);
738 evas_object_event_callback_add(stack, EVAS_CALLBACK_KEY_DOWN,
739 _key_down, &opts);
740 evas_object_event_callback_add(stack, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
741 _reset_size_hints, edje);
742
743 if (opts.print)
744 {
745 edje_object_signal_callback_add(edje, "*", "*", _print_signal, NULL);
746 edje_object_message_handler_set(edje, _print_message, NULL);
747 }
748
749 if (opts.slave_mode)
750 {
751#ifndef _WIN32
752 int flags;
753 flags = fcntl(STDIN_FILENO, F_GETFL, 0);
754 flags |= O_NONBLOCK;
755 if (fcntl(STDIN_FILENO, F_SETFL, flags) < 0)
756 {
757 fprintf(stderr, "ERROR: Could not set stdin to non-block: %s\n",
758 strerror(errno));
759 goto free_ecore_evas;
760 }
761 ecore_main_fd_handler_add(STDIN_FILENO, ECORE_FD_READ | ECORE_FD_ERROR,
762 _slave_mode, edje, NULL, NULL);
763#else
764 /* TODO: port the code above to Windows */
765 fprintf (stderr, "ERROR: slave mode not working on Windows\n");
766 goto free_ecore_evas;
767#endif
768 }
769
770 ecore_evas_borderless_set(win, opts.borderless);
771 ecore_evas_sticky_set(win, opts.sticky);
772 if (opts.title)
773 ecore_evas_title_set(win, opts.title);
774
775 if (opts.size.w <= 0) opts.size.w = 320;
776 if (opts.size.h <= 0) opts.size.h = 240;
777 ecore_evas_resize(win, opts.size.w, opts.size.h);
778 ecore_evas_show(win);
779 ecore_main_loop_begin();
780
781 ecore_evas_free(win);
782 end:
783 edje_shutdown();
784 ecore_evas_shutdown();
785
786 return 0;
787
788 free_ecore_evas:
789 ecore_evas_free(win);
790 shutdown_edje:
791 edje_shutdown();
792 shutdown_ecore_evas:
793 ecore_evas_shutdown();
794 return EXIT_FAILURE;
795}