enlightenment/src/bin/e_init_main.c

499 lines
13 KiB
C

#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <Ecore.h>
#include <Ecore_X.h>
#include <Ecore_Evas.h>
#include <Ecore_Ipc.h>
#include <Evas.h>
#include <Edje.h>
#define E_TYPEDEFS 1
#include "e_xinerama.h"
#undef E_TYPEDEFS
#include "e_xinerama.h"
EAPI int e_init_init(void);
EAPI int e_init_shutdown(void);
EAPI void e_init_show(void);
EAPI void e_init_hide(void);
EAPI void e_init_title_set(const char *str);
EAPI void e_init_version_set(const char *str);
EAPI void e_init_status_set(const char *str);
EAPI void e_init_done(void);
/* local subsystem functions */
static int _e_ipc_init(void);
static Eina_Bool _e_ipc_cb_server_add(void *data, int type, void *event);
static Eina_Bool _e_ipc_cb_server_del(void *data, int type, void *event);
static Eina_Bool _e_ipc_cb_server_data(void *data, int type, void *event);
/* local subsystem globals */
static Ecore_Ipc_Server *_e_ipc_server = NULL;
static const char *theme = NULL;
static int font_hinting = -1;
static int engine = -1;
static const char *title = NULL;
static const char *verstr = NULL;
static Eina_List *fpath = NULL;
static Ecore_X_Window *initwins = NULL;
static int initwins_num = 0;
static Ecore_Ipc_Server *server = NULL;
static Eina_Bool
delayed_ok(void *data)
{
kill(getppid(), SIGUSR2);
return ECORE_CALLBACK_CANCEL;
}
int
main(int argc, char **argv)
{
int i;
char *s;
double scale;
for (i = 1; i < argc; i++)
{
if ((i == 1) &&
((!strcmp(argv[i], "-h")) ||
(!strcmp(argv[i], "-help")) ||
(!strcmp(argv[i], "--help"))))
{
printf(
"This is an internal tool for Enlightenment.\n"
"do not use it.\n"
);
exit(0);
}
else if (!theme) theme = argv[i];
else if (engine < 0) engine = atoi(argv[i]);
else if (font_hinting < 0) font_hinting = atoi(argv[i]);
else if (!title) title = argv[i];
else if (!verstr) verstr = argv[i];
else fpath = eina_list_append(fpath, argv[i]);
}
ecore_init();
ecore_x_init(NULL);
ecore_app_args_set(argc, (const char **)argv);
evas_init();
ecore_evas_init();
edje_init();
edje_frametime_set(1.0 / 30.0);
s = getenv("E_SCALE");
scale = 1.0;
if (s) scale = atof(s);
edje_scale_set(scale);
ecore_ipc_init();
if (_e_ipc_init())
{
e_init_init();
e_init_show();
e_init_title_set(title);
e_init_version_set(verstr);
e_init_status_set("");
ecore_timer_add(0.2, delayed_ok, NULL);
ecore_main_loop_begin();
}
if (_e_ipc_server)
{
ecore_ipc_server_del(_e_ipc_server);
_e_ipc_server = NULL;
}
ecore_ipc_shutdown();
ecore_evas_shutdown();
edje_shutdown();
evas_shutdown();
ecore_x_shutdown();
ecore_shutdown();
return 0;
}
/* local subsystem functions */
static int
_e_ipc_init(void)
{
char *sdir;
sdir = getenv("E_IPC_SOCKET");
if (!sdir)
{
printf("The E_IPC_SOCKET environment variable is not set. This is\n"
"exported by Enlightenment to all processes it launches.\n"
"This environment variable must be set and must point to\n"
"Enlightenment's IPC socket file (minus port number).\n");
return 0;
}
_e_ipc_server = ecore_ipc_server_connect(ECORE_IPC_LOCAL_SYSTEM, sdir, 0, NULL);
if (!_e_ipc_server) return 0;
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _e_ipc_cb_server_add, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _e_ipc_cb_server_del, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _e_ipc_cb_server_data, NULL);
return 1;
}
static Eina_Bool
_e_ipc_cb_server_add(__UNUSED__ void *data, __UNUSED__ int type, void *event)
{
Ecore_Ipc_Event_Server_Add *e;
e = event;
server = e->server;
ecore_ipc_server_send(server,
7/*E_IPC_DOMAIN_INIT*/,
1/*hello*/,
0, 0, 0,
initwins, initwins_num * sizeof(Ecore_X_Window));
ecore_ipc_server_flush(server);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_ipc_cb_server_del(__UNUSED__ void *data, __UNUSED__ int type, __UNUSED__ void *event)
{
/* quit now */
ecore_main_loop_quit();
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_ipc_cb_server_data(__UNUSED__ void *data, __UNUSED__ int type, void *event)
{
Ecore_Ipc_Event_Server_Data *e;
e = event;
if (e->major != 7/*E_IPC_DOMAIN_INIT*/) return ECORE_CALLBACK_PASS_ON;
switch (e->minor)
{
case 1:
if (e->data) e_init_status_set(e->data);
break;
case 2:
/* quit now */
e_init_done();
break;
default:
break;
}
return ECORE_CALLBACK_PASS_ON;
}
static void _e_init_cb_signal_disable(void *data, Evas_Object *obj, const char *emission, const char *source);
static void _e_init_cb_signal_enable(void *data, Evas_Object *obj, const char *emission, const char *source);
static void _e_init_cb_signal_done_ok(void *data, Evas_Object *obj, const char *emission, const char *source);
static Eina_Bool _e_init_cb_window_configure(void *data, int ev_type, void *ev);
static Eina_Bool _e_init_cb_timeout(void *data);
static Ecore_Evas *_e_init_evas_new(Ecore_X_Window root, int w, int h, Ecore_X_Window *winret);
/* local subsystem globals */
static Ecore_X_Window _e_init_root_win = 0;
static Ecore_X_Window _e_init_win = 0;
static Ecore_Evas *_e_init_ecore_evas = NULL;
static Evas *_e_init_evas = NULL;
static Evas_Object *_e_init_object = NULL;
static Ecore_Event_Handler *_e_init_configure_handler = NULL;
static Ecore_Timer *_e_init_timeout_timer = NULL;
/* externally accessible functions */
EAPI int
e_init_init(void)
{
Ecore_X_Window root, *roots;
Evas_Object *o;
Eina_List *l, *screens;
int i, num, w, h;
const char *s;
e_xinerama_init();
_e_init_configure_handler =
ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE,
_e_init_cb_window_configure, NULL);
num = 0;
roots = ecore_x_window_root_list(&num);
if ((!roots) || (num <= 0)) return 0;
root = roots[0];
_e_init_root_win = root;
s = theme;
initwins = malloc(num * 2 * sizeof(Ecore_X_Window));
initwins_num = num * 2;
/* extra root windows/screens */
for (i = 1; i < num; i++)
{
ecore_x_window_size_get(roots[i], &w, &h);
_e_init_ecore_evas = _e_init_evas_new(roots[i], w, h, &_e_init_win);
_e_init_evas = ecore_evas_get(_e_init_ecore_evas);
initwins[(i * 2) + 0] = roots[i];
initwins[(i * 2) + 1] = _e_init_win;
o = edje_object_add(_e_init_evas);
edje_object_file_set(o, s, "e/init/extra_screen");
evas_object_move(o, 0, 0);
evas_object_resize(o, w, h);
evas_object_show(o);
}
/* primary screen/root */
ecore_x_window_size_get(root, &w, &h);
_e_init_ecore_evas = _e_init_evas_new(root, w, h, &_e_init_win);
_e_init_evas = ecore_evas_get(_e_init_ecore_evas);
initwins[0] = root;
initwins[1] = _e_init_win;
/* look at xinerama asto how to slice this up */
screens = (Eina_List *)e_xinerama_screens_get();
if (screens)
{
E_Screen *scr;
EINA_LIST_FOREACH(screens, l, scr)
{
o = edje_object_add(_e_init_evas);
if (l == screens)
{
edje_object_file_set(o, s, "e/init/splash");
_e_init_object = o;
}
else
edje_object_file_set(o, s, "e/init/extra_screen");
evas_object_move(o, scr->x, scr->y);
evas_object_resize(o, scr->w, scr->h);
evas_object_show(o);
}
}
else
{
o = edje_object_add(_e_init_evas);
edje_object_file_set(o, s, "e/init/splash");
_e_init_object = o;
evas_object_move(o, 0, 0);
evas_object_resize(o, w, h);
evas_object_show(o);
}
edje_object_part_text_set(_e_init_object, "e.text.disable_text",
"Disable splash screen");
edje_object_signal_callback_add(_e_init_object, "e,action,init,disable", "e",
_e_init_cb_signal_disable, NULL);
edje_object_signal_callback_add(_e_init_object, "e,action,init,enable", "e",
_e_init_cb_signal_enable, NULL);
edje_object_signal_callback_add(_e_init_object, "e,state,done_ok", "e",
_e_init_cb_signal_done_ok, NULL);
free(roots);
_e_init_timeout_timer = ecore_timer_add(240.0, _e_init_cb_timeout, NULL);
return 1;
}
EAPI int
e_init_shutdown(void)
{
if (_e_init_configure_handler)
ecore_event_handler_del(_e_init_configure_handler);
_e_init_configure_handler = NULL;
e_init_hide();
return 1;
}
EAPI void
e_init_show(void)
{
if (!_e_init_ecore_evas) return;
ecore_evas_raise(_e_init_ecore_evas);
ecore_evas_show(_e_init_ecore_evas);
}
EAPI void
e_init_hide(void)
{
if (!_e_init_ecore_evas) return;
ecore_evas_hide(_e_init_ecore_evas);
evas_object_del(_e_init_object);
ecore_evas_free(_e_init_ecore_evas);
_e_init_ecore_evas = NULL;
_e_init_evas = NULL;
_e_init_win = 0;
_e_init_object = NULL;
}
EAPI void
e_init_title_set(const char *str)
{
if (!_e_init_object) return;
edje_object_part_text_set(_e_init_object, "e.text.title", str);
}
EAPI void
e_init_version_set(const char *str)
{
if (!_e_init_object) return;
edje_object_part_text_set(_e_init_object, "e.text.version", str);
}
EAPI void
e_init_status_set(const char *str)
{
if (!_e_init_object) return;
edje_object_part_text_set(_e_init_object, "e.text.status", str);
}
EAPI void
e_init_done(void)
{
if (!_e_init_object) return;
edje_object_signal_emit(_e_init_object, "e,state,done", "e");
if (_e_init_timeout_timer) ecore_timer_del(_e_init_timeout_timer);
_e_init_timeout_timer = ecore_timer_add(60.0, _e_init_cb_timeout, NULL);
}
static void
_e_init_cb_signal_disable(void *data, Evas_Object *obj, const char *emission, const char *source)
{
if (!server) return;
ecore_ipc_server_send(server,
7/*E_IPC_DOMAIN_INIT*/,
2/*set splash*/,
0, 0, 0,
NULL, 0);
ecore_ipc_server_flush(server);
}
static void
_e_init_cb_signal_enable(void *data, Evas_Object *obj, const char *emission, const char *source)
{
if (!server) return;
ecore_ipc_server_send(server,
7/*E_IPC_DOMAIN_INIT*/,
2/*set splash*/,
1, 0, 0,
NULL, 0);
ecore_ipc_server_flush(server);
}
static void
_e_init_cb_signal_done_ok(void *data, Evas_Object *obj, const char *emission, const char *source)
{
e_init_hide();
if (_e_init_timeout_timer)
{
ecore_timer_del(_e_init_timeout_timer);
_e_init_timeout_timer = NULL;
}
ecore_main_loop_quit();
}
static Eina_Bool
_e_init_cb_window_configure(__UNUSED__ void *data, __UNUSED__ int ev_type, void *ev)
{
Ecore_X_Event_Window_Configure *e;
e = ev;
/* really simple - don't handle xinerama - because this event will only
* happen in single head */
if (e->win != _e_init_root_win) return ECORE_CALLBACK_PASS_ON;
ecore_evas_resize(_e_init_ecore_evas, e->w, e->h);
evas_object_resize(_e_init_object, e->w, e->h);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_init_cb_timeout(void *data)
{
e_init_hide();
_e_init_timeout_timer = NULL;
ecore_main_loop_quit();
return ECORE_CALLBACK_CANCEL;
}
static Ecore_Evas *
_e_init_evas_new(Ecore_X_Window root, int w, int h, Ecore_X_Window *winret)
{
Ecore_Evas *ee = NULL;
Evas *e;
Eina_List *l;
const char *path;
if ((engine == 0) || (engine == 1))
{
ee = ecore_evas_software_x11_new(NULL, root, 0, 0, w, h);
ecore_evas_override_set(ee, 1);
ecore_evas_software_x11_direct_resize_set(ee, 1);
*winret = ecore_evas_software_x11_window_get(ee);
}
else if (engine == 2)
{
ee = ecore_evas_gl_x11_new(NULL, root, 0, 0, w, h);
ecore_evas_override_set(ee, 1);
ecore_evas_gl_x11_direct_resize_set(ee, 1);
*winret = ecore_evas_gl_x11_window_get(ee);
}
else if (engine == 3)
{
ee = ecore_evas_xrender_x11_new(NULL, root, 0, 0, w, h);
ecore_evas_override_set(ee, 1);
ecore_evas_xrender_x11_direct_resize_set(ee, 1);
*winret = ecore_evas_xrender_x11_window_get(ee);
}
else if (engine == 4)
{
ee = ecore_evas_software_x11_16_new(NULL, root, 0, 0, w, h);
ecore_evas_override_set(ee, 1);
ecore_evas_software_x11_16_direct_resize_set(ee, 1);
*winret = ecore_evas_software_x11_16_window_get(ee);
}
else
{
printf("The select engine is unknown or incorrectly set. Please specify a correct one.\n");
exit(0);
}
e = ecore_evas_get(ee);
evas_image_cache_set(e, 4096 * 1024);
evas_font_cache_set(e, 512 * 1024);
EINA_LIST_FOREACH(fpath, l, path)
evas_font_path_append(e, path);
if (font_hinting == 0)
{
if (evas_font_hinting_can_hint(e, EVAS_FONT_HINTING_BYTECODE))
evas_font_hinting_set(e, EVAS_FONT_HINTING_BYTECODE);
else if (evas_font_hinting_can_hint(e, EVAS_FONT_HINTING_AUTO))
evas_font_hinting_set(e, EVAS_FONT_HINTING_AUTO);
else
evas_font_hinting_set(e, EVAS_FONT_HINTING_NONE);
}
else if (font_hinting == 1)
{
if (evas_font_hinting_can_hint(e, EVAS_FONT_HINTING_AUTO))
evas_font_hinting_set(e, EVAS_FONT_HINTING_AUTO);
else
evas_font_hinting_set(e, EVAS_FONT_HINTING_NONE);
}
else if (font_hinting == 2)
evas_font_hinting_set(e, EVAS_FONT_HINTING_NONE);
ecore_evas_name_class_set(ee, "E", "Init_Window");
ecore_evas_title_set(ee, "Enlightenment Init");
ecore_evas_raise(ee);
ecore_evas_show(ee);
return ee;
}