[WM_ROT] support for rotating prediction window without virtual keyboard
[platform/core/uifw/e17.git] / src / bin / e_init_main.c
1 #include "config.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <Ecore.h>
7 #include <Ecore_X.h>
8 #include <Ecore_Evas.h>
9 #include <Ecore_Ipc.h>
10 #include <Evas.h>
11 #include <Edje.h>
12
13 #ifdef EAPI
14 #undef EAPI
15 #endif
16 #ifdef WIN32
17 # ifdef BUILDING_DLL
18 #  define EAPI __declspec(dllexport)
19 # else
20 #  define EAPI __declspec(dllimport)
21 # endif
22 #else
23 # ifdef __GNUC__
24 #  if __GNUC__ >= 4
25 /* BROKEN in gcc 4 on amd64 */
26 #if 0
27 #   pragma GCC visibility push(hidden)
28 #endif
29 #   define EAPI __attribute__ ((visibility("default")))
30 #  else
31 #   define EAPI
32 #  endif
33 # else
34 #  define EAPI
35 # endif
36 #endif
37
38 #ifdef EINTERN
39 #undef EINTERN
40 #endif
41 #ifdef __GNUC__
42 # if __GNUC__ >= 4
43 #  define EINTERN __attribute__ ((visibility("hidden")))
44 # else
45 #  define EINTERN
46 # endif
47 #else
48 # define EINTERN
49 #endif
50
51 #define E_TYPEDEFS 1
52 #include "e_xinerama.h"
53 #undef E_TYPEDEFS
54 #include "e_xinerama.h"
55
56 EINTERN int e_init_init(void);
57 EINTERN int e_init_shutdown(void);
58 EAPI void e_init_show(void);
59 EAPI void e_init_hide(void);
60 EAPI void e_init_title_set(const char *str);
61 EAPI void e_init_version_set(const char *str);
62 EAPI void e_init_status_set(const char *str);
63 EAPI void e_init_done(void);
64
65 /* local subsystem functions */
66 static int _e_ipc_init(void);
67 static Eina_Bool _e_ipc_cb_server_add(void *data, int type, void *event);
68 static Eina_Bool _e_ipc_cb_server_del(void *data, int type, void *event);
69 static Eina_Bool _e_ipc_cb_server_data(void *data, int type, void *event);
70
71 /* local subsystem globals */
72 static Ecore_Ipc_Server *_e_ipc_server = NULL;
73 static const char *theme = NULL;
74 static int font_hinting = -1;
75 static const char *title = NULL;
76 static const char *verstr = NULL;
77 static Eina_List *fpath = NULL;
78 static Ecore_X_Window *initwins = NULL;
79 static int initwins_num = 0;
80 static Ecore_Ipc_Server *server = NULL;
81
82 static Eina_Bool
83 delayed_ok(void *data __UNUSED__)
84 {
85    kill(getppid(), SIGUSR1);
86    return ECORE_CALLBACK_CANCEL;
87 }
88
89 int
90 main(int argc, char **argv)
91 {
92    int i;
93    char *s;
94    double scale;
95
96    for (i = 1; i < argc; i++)
97      {
98         if ((i == 1) &&
99             ((!strcmp(argv[i], "-h")) ||
100              (!strcmp(argv[i], "-help")) ||
101              (!strcmp(argv[i], "--help"))))
102           {
103              printf(
104                     "This is an internal tool for Enlightenment.\n"
105                     "do not use it.\n"
106                     );
107              exit(0);
108           }
109         else if (!theme) theme = argv[i];
110         else if (font_hinting < 0) font_hinting = atoi(argv[i]);
111         else if (!title) title = argv[i];
112         else if (!verstr) verstr = argv[i];
113         else fpath = eina_list_append(fpath, argv[i]);
114      }
115
116    ecore_init();
117    ecore_x_init(NULL);
118    ecore_app_args_set(argc, (const char **)argv);
119    evas_init();
120    ecore_evas_init();
121    edje_init();
122    edje_frametime_set(1.0 / 30.0);
123    s = getenv("E_SCALE");
124    scale = 1.0;
125    if (s) scale = atof(s);
126    edje_scale_set(scale);
127    ecore_ipc_init();
128
129    if (_e_ipc_init())
130      {
131         e_init_init();
132         e_init_show();
133         e_init_title_set(title);
134         e_init_version_set(verstr);
135         e_init_status_set("");
136         ecore_timer_add(0.2, delayed_ok, NULL);
137         ecore_main_loop_begin();
138      }
139
140    if (_e_ipc_server)
141      {
142         ecore_ipc_server_del(_e_ipc_server);
143         _e_ipc_server = NULL;
144      }
145
146    ecore_ipc_shutdown();
147    ecore_evas_shutdown();
148    edje_shutdown();
149    evas_shutdown();
150    ecore_x_shutdown();
151    ecore_shutdown();
152
153    return 0;
154 }
155
156 /* local subsystem functions */
157 static int
158 _e_ipc_init(void)
159 {
160    char *sdir;
161
162    sdir = getenv("E_IPC_SOCKET");
163    if (!sdir)
164      {
165         printf("The E_IPC_SOCKET environment variable is not set. This is\n"
166                "exported by Enlightenment to all processes it launches.\n"
167                "This environment variable must be set and must point to\n"
168                "Enlightenment's IPC socket file (minus port number).\n");
169         return 0;
170      }
171    _e_ipc_server = ecore_ipc_server_connect(ECORE_IPC_LOCAL_SYSTEM, sdir, 0, NULL);
172    if (!_e_ipc_server) return 0;
173
174    ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _e_ipc_cb_server_add, NULL);
175    ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _e_ipc_cb_server_del, NULL);
176    ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _e_ipc_cb_server_data, NULL);
177
178    return 1;
179 }
180
181 static Eina_Bool
182 _e_ipc_cb_server_add(void *data __UNUSED__, int type __UNUSED__, void *event)
183 {
184    Ecore_Ipc_Event_Server_Add *e;
185
186    e = event;
187    server = e->server;
188    ecore_ipc_server_send(server,
189                          7/*E_IPC_DOMAIN_INIT*/,
190                          1/*hello*/,
191                          0, 0, 0,
192                          initwins, initwins_num * sizeof(Ecore_X_Window));
193    ecore_ipc_server_flush(server);
194    return ECORE_CALLBACK_PASS_ON;
195 }
196
197 static Eina_Bool
198 _e_ipc_cb_server_del(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
199 {
200    /* quit now */
201    ecore_main_loop_quit();
202    return ECORE_CALLBACK_PASS_ON;
203 }
204
205 static Eina_Bool
206 _e_ipc_cb_server_data(void *data __UNUSED__, int type __UNUSED__, void *event)
207 {
208    Ecore_Ipc_Event_Server_Data *e;
209
210    e = event;
211    if (e->major != 7/*E_IPC_DOMAIN_INIT*/) return ECORE_CALLBACK_PASS_ON;
212    switch (e->minor)
213      {
214       case 1:
215         if (e->data) e_init_status_set(e->data);
216         break;
217       case 2:
218         /* quit now */
219         e_init_done();
220         break;
221       default:
222         break;
223      }
224    return ECORE_CALLBACK_PASS_ON;
225 }
226
227 static void _e_init_cb_signal_disable(void *data, Evas_Object *obj, const char *emission, const char *source);
228 static void _e_init_cb_signal_enable(void *data, Evas_Object *obj, const char *emission, const char *source);
229 static void _e_init_cb_signal_done_ok(void *data, Evas_Object *obj, const char *emission, const char *source);
230 static Eina_Bool _e_init_cb_window_configure(void *data, int ev_type, void *ev);
231 static Eina_Bool _e_init_cb_timeout(void *data);
232 static Ecore_Evas *_e_init_evas_new(Ecore_X_Window root, int w, int h, Ecore_X_Window *winret);
233
234 /* local subsystem globals */
235 static Ecore_X_Window _e_init_root_win = 0;
236 static Ecore_X_Window _e_init_win = 0;
237 static Ecore_Evas *_e_init_ecore_evas = NULL;
238 static Evas *_e_init_evas = NULL;
239 static Evas_Object *_e_init_object = NULL;
240 static Ecore_Event_Handler *_e_init_configure_handler = NULL;
241 static Ecore_Timer *_e_init_timeout_timer = NULL;
242
243 /* externally accessible functions */
244 EINTERN int
245 e_init_init(void)
246 {
247    Ecore_X_Window root, *roots;
248    Evas_Object *o;
249    Eina_List *l, *screens;
250    int i, num, w, h;
251    const char *s;
252
253    e_xinerama_init();
254
255    _e_init_configure_handler =
256      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE,
257                              _e_init_cb_window_configure, NULL);
258
259    num = 0;
260    roots = ecore_x_window_root_list(&num);
261    if ((!roots) || (num <= 0)) return 0;
262    root = roots[0];
263    _e_init_root_win = root;
264
265    s = theme;
266    initwins = malloc(num * 2 * sizeof(Ecore_X_Window));
267    initwins_num = num * 2;
268
269    /* extra root windows/screens */
270    for (i = 1; i < num; i++)
271      {
272         ecore_x_window_size_get(roots[i], &w, &h);
273         _e_init_ecore_evas = _e_init_evas_new(roots[i], w, h, &_e_init_win);
274         _e_init_evas = ecore_evas_get(_e_init_ecore_evas);
275         initwins[(i * 2) + 0] = roots[i];
276         initwins[(i * 2) + 1] = _e_init_win;
277
278         o = edje_object_add(_e_init_evas);
279         edje_object_file_set(o, s, "e/init/extra_screen");
280         evas_object_move(o, 0, 0);
281         evas_object_resize(o, w, h);
282         evas_object_show(o);
283      }
284
285    /* primary screen/root */
286    ecore_x_window_size_get(root, &w, &h);
287    _e_init_ecore_evas = _e_init_evas_new(root, w, h, &_e_init_win);
288    _e_init_evas = ecore_evas_get(_e_init_ecore_evas);
289    initwins[0] = root;
290    initwins[1] = _e_init_win;
291
292    /* look at xinerama asto how to slice this up */
293    screens = (Eina_List *)e_xinerama_screens_get();
294    if (screens)
295      {
296         E_Screen *scr;
297
298         EINA_LIST_FOREACH(screens, l, scr)
299           {
300              o = edje_object_add(_e_init_evas);
301              if (l == screens)
302                {
303                   edje_object_file_set(o, s, "e/init/splash");
304                   _e_init_object = o;
305                }
306              else
307                edje_object_file_set(o, s, "e/init/extra_screen");
308              evas_object_move(o, scr->x, scr->y);
309              evas_object_resize(o, scr->w, scr->h);
310              evas_object_show(o);
311           }
312      }
313    else
314      {
315         o = edje_object_add(_e_init_evas);
316         edje_object_file_set(o, s, "e/init/splash");
317         _e_init_object = o;
318         evas_object_move(o, 0, 0);
319         evas_object_resize(o, w, h);
320         evas_object_show(o);
321      }
322
323    edje_object_part_text_set(_e_init_object, "e.text.disable_text",
324                              "Disable splash screen");
325    edje_object_signal_callback_add(_e_init_object, "e,action,init,disable", "e",
326                                    _e_init_cb_signal_disable, NULL);
327    edje_object_signal_callback_add(_e_init_object, "e,action,init,enable", "e",
328                                    _e_init_cb_signal_enable, NULL);
329    edje_object_signal_callback_add(_e_init_object, "e,state,done_ok", "e",
330                                    _e_init_cb_signal_done_ok, NULL);
331    free(roots);
332
333    _e_init_timeout_timer = ecore_timer_add(240.0, _e_init_cb_timeout, NULL);
334    return 1;
335 }
336
337 EINTERN int
338 e_init_shutdown(void)
339 {
340    if (_e_init_configure_handler)
341      ecore_event_handler_del(_e_init_configure_handler);
342    _e_init_configure_handler = NULL;
343    e_init_hide();
344    return 1;
345 }
346
347 EAPI void
348 e_init_show(void)
349 {
350    if (!_e_init_ecore_evas) return;
351    ecore_evas_raise(_e_init_ecore_evas);
352    ecore_evas_show(_e_init_ecore_evas);
353 }
354
355 EAPI void
356 e_init_hide(void)
357 {
358    if (!_e_init_ecore_evas) return;
359    ecore_evas_hide(_e_init_ecore_evas);
360    evas_object_del(_e_init_object);
361    ecore_evas_free(_e_init_ecore_evas);
362    _e_init_ecore_evas = NULL;
363    _e_init_evas = NULL;
364    _e_init_win = 0;
365    _e_init_object = NULL;
366 }
367
368 EAPI void
369 e_init_title_set(const char *str)
370 {
371    if (!_e_init_object) return;
372    edje_object_part_text_set(_e_init_object, "e.text.title", str);
373 }
374
375 EAPI void
376 e_init_version_set(const char *str)
377 {
378    if (!_e_init_object) return;
379    edje_object_part_text_set(_e_init_object, "e.text.version", str);
380 }
381
382 EAPI void
383 e_init_status_set(const char *str)
384 {
385    if (!_e_init_object) return;
386    edje_object_part_text_set(_e_init_object, "e.text.status", str);
387 }
388
389 EAPI void
390 e_init_done(void)
391 {
392    if (!_e_init_object) return;
393    edje_object_signal_emit(_e_init_object, "e,state,done", "e");
394    if (_e_init_timeout_timer) ecore_timer_del(_e_init_timeout_timer);
395    _e_init_timeout_timer = ecore_timer_add(60.0, _e_init_cb_timeout, NULL);
396 }
397
398
399 static void
400 _e_init_cb_signal_disable(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
401 {
402    if (!server) return;
403    ecore_ipc_server_send(server,
404                          7/*E_IPC_DOMAIN_INIT*/,
405                          2/*set splash*/,
406                          0, 0, 0,
407                          NULL, 0);
408    ecore_ipc_server_flush(server);
409 }
410
411 static void
412 _e_init_cb_signal_enable(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
413 {
414    if (!server) return;
415    ecore_ipc_server_send(server,
416                          7/*E_IPC_DOMAIN_INIT*/,
417                          2/*set splash*/,
418                          1, 0, 0,
419                          NULL, 0);
420    ecore_ipc_server_flush(server);
421 }
422
423 static void
424 _e_init_cb_signal_done_ok(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
425 {
426    e_init_hide();
427    if (_e_init_timeout_timer)
428      {
429         ecore_timer_del(_e_init_timeout_timer);
430         _e_init_timeout_timer = NULL;
431      }
432    ecore_main_loop_quit();
433 }
434
435 static Eina_Bool
436 _e_init_cb_window_configure(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
437 {
438    Ecore_X_Event_Window_Configure *e;
439
440    e = ev;
441    /* really simple - don't handle xinerama - because this event will only
442     * happen in single head */
443    if (e->win != _e_init_root_win) return ECORE_CALLBACK_PASS_ON;
444    ecore_evas_resize(_e_init_ecore_evas, e->w, e->h);
445    evas_object_resize(_e_init_object, e->w, e->h);
446    return ECORE_CALLBACK_PASS_ON;
447 }
448
449 static Eina_Bool
450 _e_init_cb_timeout(void *data __UNUSED__)
451 {
452    e_init_hide();
453    _e_init_timeout_timer = NULL;
454    ecore_main_loop_quit();
455    return ECORE_CALLBACK_CANCEL;
456 }
457
458 static Ecore_Evas *
459 _e_init_evas_new(Ecore_X_Window root, int w, int h, Ecore_X_Window *winret)
460 {
461    Ecore_Evas *ee = NULL;
462    Evas *e;
463    Eina_List *l;
464    const char *path;
465
466    ee = ecore_evas_software_x11_new(NULL, root, 0, 0, w, h);
467    ecore_evas_override_set(ee, 1);
468    ecore_evas_software_x11_direct_resize_set(ee, 1);
469    *winret = ecore_evas_software_x11_window_get(ee);
470
471    e = ecore_evas_get(ee);
472
473    evas_image_cache_set(e, 4096 * 1024);
474    evas_font_cache_set(e, 512 * 1024);
475
476    EINA_LIST_FOREACH(fpath, l, path)
477      evas_font_path_append(e, path);
478
479    if (font_hinting == 0)
480      {
481         if (evas_font_hinting_can_hint(e, EVAS_FONT_HINTING_BYTECODE))
482           evas_font_hinting_set(e, EVAS_FONT_HINTING_BYTECODE);
483         else if (evas_font_hinting_can_hint(e, EVAS_FONT_HINTING_AUTO))
484           evas_font_hinting_set(e, EVAS_FONT_HINTING_AUTO);
485         else
486           evas_font_hinting_set(e, EVAS_FONT_HINTING_NONE);
487      }
488    else if (font_hinting == 1)
489      {
490         if (evas_font_hinting_can_hint(e, EVAS_FONT_HINTING_AUTO))
491           evas_font_hinting_set(e, EVAS_FONT_HINTING_AUTO);
492         else
493           evas_font_hinting_set(e, EVAS_FONT_HINTING_NONE);
494      }
495    else if (font_hinting == 2)
496      evas_font_hinting_set(e, EVAS_FONT_HINTING_NONE);
497
498    ecore_evas_name_class_set(ee, "E", "Init_Window");
499    ecore_evas_title_set(ee, "Enlightenment Init");
500
501    ecore_evas_raise(ee);
502    ecore_evas_show(ee);
503
504    return ee;
505 }