add quicklauncher infra! elementary_testql uses this infra.

SVN revision: 39199
This commit is contained in:
Carsten Haitzler 2009-02-25 11:00:07 +00:00
parent 017cc96515
commit f7a18a3db9
7 changed files with 609 additions and 71 deletions

View File

@ -18,6 +18,7 @@ AC_PROG_CC
AM_PROG_CC_STDC
AC_HEADER_STDC
AC_C_CONST
AC_FUNC_ALLOCA
AC_LIBTOOL_WIN32_DLL
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl

View File

@ -18,8 +18,33 @@ if ELEMENTARY_WINDOWS_BUILD
AM_CPPFLAGS += -DELEMENTARY_BUILD
endif
bin_PROGRAMS = elementary_test
bin_PROGRAMS = elementary_test elementary_quicklaunch elementary_run \
elementary_testql
elementary_test_SOURCES = test.c
elementary_test_LDADD = $(top_builddir)/src/lib/libelementary.la
elementary_test_LDFLAGS =
elementary_test_LDFLAGS =
elementary_quicklaunch_SOURCES = quicklaunch.c
elementary_quicklaunch_LDADD = $(top_builddir)/src/lib/libelementary.la
elementary_quicklaunch_LDFLAGS =
elementary_run_SOURCES = run.c
elementary_run_LDADD =
elementary_run_LDFLAGS =
## This is how to build a quicklanch capable app
# build the shared lib version - libtool produces a .a and .la file as well
# as a .so - these get put in libdir ($PREIFX/lib) as elementary_testql.so
# etc. - this is where elementary will expect to find the .so's for
# quicklaunch apps.
elementary_testqldir = $(libdir)
elementary_testql_LTLIBRARIES = elementary_testql.la
elementary_testql_la_SOURCES = test.c
elementary_testql_la_LIBADD = $(top_builddir)/src/lib/libelementary.la
elementary_testql_la_CFLAGS =
elementary_testql_la_LDFLAGS = -module -avoid-version -no-undefined
elementary_testql_SOURCES = test.c
elementary_testql_LDADD = $(top_builddir)/src/lib/libelementary.la
elementary_testql_CFLAGS = -DELM_LIB_QUICKLAUNCH=1
elementary_testql_LDFLAGS =

View File

@ -0,0 +1,130 @@
#include <Elementary.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
static void
handle_run(int fd, unsigned long bytes)
{
unsigned char *buf = NULL;
int i, num;
char **argv = NULL;
char *cwd;
int argc;
buf = alloca(bytes);
if ((num = read(fd, buf, bytes)) < 0)
{
close(fd);
return;
}
close(fd);
argc = ((unsigned long *)(buf))[0];
argv = (char **)(&(((unsigned long *)(buf))[1]));
for (i = 0; i < argc; i++) argv[i] = buf + (unsigned long)argv[i];
cwd = argv[argc - 1] + strlen(argv[argc - 1]) + 1;
elm_quicklaunch_prepare(argc, argv);
elm_quicklaunch_fork(argc, argv, cwd);
elm_quicklaunch_cleanup();
}
static void
child_handler(int n)
{
int status;
wait(&status);
}
int
main(int argc, char **argv)
{
int sock, socket_unix_len;
struct stat st;
struct sockaddr_un socket_unix;
struct linger lin;
char buf[PATH_MAX];
struct sigaction sa;
if (!getenv("DISPLAY"))
{
fprintf(stderr, "elementary_quicklaunch: DISPLAY env var not set\n");
exit(-1);
}
snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i", getuid());
if (stat(buf, &st) < 0) mkdir(buf, S_IRUSR | S_IWUSR | S_IXUSR);
snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i/%s", getuid(), getenv("DISPLAY"));
unlink(buf);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
{
perror("elementary_quicklaunch: socket(AF_UNIX, SOCK_STREAM, 0)");
exit(-1);
}
if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0)
{
perror("elementary_quicklaunch: fcntl(sock, F_SETFD, FD_CLOEXEC)");
exit(-1);
}
lin.l_onoff = 1;
lin.l_linger = 0;
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
{
perror("elementary_quicklaunch: setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) ");
exit(-1);
}
socket_unix.sun_family = AF_UNIX;
strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
if (bind(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
{
perror("elementary_quicklaunch: bind(sock, (struct sockaddr *)&socket_unix, socket_unix_len)");
printf("elementary_quicklaunch: cannot bind socket for '%s'\n", buf);
exit(-1);
}
if (listen(sock, 4096) < 0)
{
perror("elementary_quicklaunch: listen(sock, 4096)");
exit(-1);
}
elm_quicklaunch_init(argc, argv);
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGALRM, SIG_DFL);
signal(SIGUSR1, SIG_DFL);
signal(SIGUSR2, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGCHLD, child_handler);
for (;;)
{
int fd;
struct sockaddr_un client;
socklen_t len;
elm_quicklaunch_sub_init(argc, argv);
elm_quicklaunch_seed();
len = sizeof(struct sockaddr_un);
fd = accept(sock, (struct sockaddr *)&client, &len);
if (fd >= 0)
{
int bytes;
char line[4096];
read(fd, &bytes, sizeof(unsigned long));
handle_run(fd, bytes);
}
elm_quicklaunch_sub_shutdown();
}
elm_quicklaunch_shutdown();
return 0;
}

View File

@ -0,0 +1,159 @@
#include "elementary_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
int
main(int argc, char **argv)
{
int sock, socket_unix_len, i;
struct sockaddr_un socket_unix;
char buf[PATH_MAX];
struct stat st;
char *exe;
int we_are_elementary_run = 0;
char *disp;
char *cwd;
int sargc, slen;
unsigned char *sbuf = NULL, *pos;
char **sargv = NULL;
if (!getcwd(buf, sizeof(buf) - 1))
{
fprintf(stderr, "elementary_quicklaunch: currect working dir too big.\n");
exit(-1);
}
cwd = strdup(buf);
if (!(disp = getenv("DISPLAY")))
{
fprintf(stderr, "elementary_quicklaunch: DISPLAY env var not set\n");
exit(-1);
}
snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i/%s", getuid(), disp);
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
perror("elementary_quicklaunch: socket(AF_UNIX, SOCK_STREAM, 0)");
exit(-1);
}
socket_unix.sun_family = AF_UNIX;
strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
if (connect(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
{
perror("elementary_quicklaunch: connect(sock, (struct sockaddr *)&socket_unix, socket_unix_len)");
printf("elementary_quicklaunch: cannot connect to socket '%s'\n", buf);
exit(1);
}
exe = argv[0];
if (!(((exe[0] == '/')) ||
((exe[0] == '.') && (exe[1] == '/')) ||
((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/'))))
{
char *path = getenv("PATH");
int exelen = strlen(argv[0]);
if (path)
{
const char *p, *pp, *s;
int exelen;
p = path;
pp = p;
exe = NULL;
for (;;)
{
if ((*p == ':') || (*p == 0))
{
int len;
len = p - pp;
if (len < (sizeof(buf) - exelen - 3))
{
strncpy(buf, pp, len);
strcpy(buf + len, "/");
strcpy(buf + len + 1, argv[0]);
if (access(buf, R_OK | X_OK) == 0)
{
exe = buf;
break;
}
if (*p == 0) break;
p++;
pp = p;
}
}
else
{
if (*p == 0) break;
p++;
}
}
}
}
if (exe)
{
if (lstat(exe, &st) == 0)
{
if (S_ISLNK(st.st_mode))
{
char buf2[PATH_MAX];
ssize_t len = readlink(exe, buf2, sizeof(buf2) - 1);
if (len >= 0)
{
char *p;
buf2[len] = 0;
p = strrchr(buf2, '/');
if (p) p++;
else p = buf2;
if (!strncasecmp(p, "elementary_run", 14))
we_are_elementary_run = 1;
}
}
}
}
if (we_are_elementary_run)
{
sargc = argc;
sargv = argv;
}
else
{
sargc = argc - 1;
sargv = &(argv[1]);
}
slen = sizeof(unsigned long) + sizeof(unsigned long);
for (i = 0; i < sargc; i++)
{
slen += sizeof(unsigned long);
slen += strlen(sargv[i]) + 1;
}
slen += strlen(cwd) + 1;
sbuf = alloca(slen);
((unsigned long *)(sbuf))[0] = slen - sizeof(unsigned long);
((unsigned long *)(sbuf))[1] = sargc;
pos = (unsigned char *)(&((((unsigned long *)(sbuf))[2 + sargc])));
for (i = 0; i < sargc; i++)
{
((unsigned long *)(sbuf))[2 + i] =
(unsigned long)pos - ((unsigned long)sbuf + sizeof(unsigned long));
strcpy(pos, sargv[i]);
pos += strlen(sargv[i]) + 1;
}
strcpy(pos, cwd);
write(sock, sbuf, slen);
close(sock);
return 0;
}

View File

@ -1,5 +1,5 @@
#include <Elementary.h>
#ifndef ELM_LIB_QUICKLAUNCH
static void my_win_del(void *data, Evas_Object *obj, void *event_info);
static void my_bt_1(void *data, Evas_Object *obj, void *event_info);
static void my_win_main(void);
@ -2879,5 +2879,6 @@ elm_main(int argc, char **argv)
/* exit code */
return 0;
}
#endif
/* all emeentary apps should use this. but it right after elm_main() */
ELM_MAIN()

View File

@ -136,7 +136,11 @@ extern "C" {
ELM_WIN_KEYBOARD_PASSWORD
} Elm_Win_Keyboard_Mode;
#ifndef ELM_LIB_QUICKLAUNCH
#define ELM_MAIN() int main(int argc, char **argv) {elm_init(argc, argv); return elm_main(argc, argv);}
#else
#define ELM_MAIN() int main(int argc, char **argv) {return elm_quicklaunch_fallback(argc, argv);}
#endif
/**************************************************************************/
/* General calls */
@ -145,6 +149,17 @@ extern "C" {
EAPI void elm_run(void);
EAPI void elm_exit(void);
EAPI void elm_quicklaunch_init(int argc, char **argv);
EAPI void elm_quicklaunch_sub_init(int argc, char **argv);
EAPI void elm_quicklaunch_sub_shutdown(void);
EAPI void elm_quicklaunch_shutdown(void);
EAPI void elm_quicklaunch_seed(void);
EAPI Evas_Bool elm_quicklaunch_prepare(int argc, char **argv);
EAPI Evas_Bool elm_quicklaunch_fork(int argc, char **argv, char *cwd);
EAPI void elm_quicklaunch_cleanup(void);
EAPI int elm_quicklaunch_fallback(int argc, char **argv);
EAPI char *elm_quicklaunch_exe_path_get(const char *exe);
EAPI void elm_object_scale_set(Evas_Object *obj, double scale);
EAPI double elm_object_scale_get(Evas_Object *obj);
EAPI void elm_object_focus(Evas_Object *obj);
@ -626,6 +641,13 @@ extern "C" {
// * test for all bubble styles
// * test for all frame styles
// * test for all genlist item styles
// * test for all button styles
// * test for all hoversel styles
// * test for all inwin styles
// * test for all anchorblock styles
// * test for all anchorview styles
// * test more layout in layout
// * test normal evas (and edje) objects used as children in elm widgets
// * need a way to attach a "dnd detector" to any object
// * need a dnd handler (able to hook to dnd detector)
// * need another sample theme

View File

@ -26,6 +26,7 @@ char *_elm_appname = NULL;
Elm_Config *_elm_config = NULL;
const char *_elm_data_dir = NULL;
static Ecore_Event_Handler *_elm_exit_handler = NULL;
static Ecore_Event_Handler *_elm_event_property_change = NULL;
#ifdef HAVE_ELEMENTARY_X
static Ecore_X_Atom _elm_atom_enlightenment_scale = 0;
@ -75,22 +76,37 @@ _elm_rescale(void)
EAPI void
elm_init(int argc, char **argv)
{
elm_quicklaunch_init(argc, argv);
elm_quicklaunch_sub_init(argc, argv);
}
EAPI void
elm_shutdown(void)
{
elm_quicklaunch_sub_shutdown();
elm_quicklaunch_shutdown();
}
static const char *elm_engine, *elm_scale, *elm_theme, *elm_prefix, *elm_data_dir;
static const char *elm_font_hinting, *elm_font_path, *elm_image_cache;
static const char *elm_font_cache, *elm_finger_size;
EAPI void
elm_quicklaunch_init(int argc, char **argv)
{
int i;
const char *elm_engine, *elm_scale, *elm_theme, *elm_prefix, *elm_data_dir;
const char *elm_font_hinting, *elm_font_path, *elm_image_cache;
const char *elm_font_cache, *elm_finger_size;
char buf[PATH_MAX];
eet_init();
ecore_init();
ecore_init();
ecore_app_args_set(argc, (const char **)argv);
ecore_file_init();
evas_init();
edje_init();
ecore_evas_init(); // FIXME: check errors
ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, _elm_signal_exit, NULL);
_elm_exit_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, _elm_signal_exit, NULL);
_elm_appname = strdup(ecore_file_file_get(argv[0]));
@ -154,6 +170,19 @@ elm_init(int argc, char **argv)
// FIXME: actually load config
_elm_config = ELM_NEW(Elm_Config);
_elm_config->engine = ELM_SOFTWARE_X11;
_elm_config->thumbscroll_enable = 1;
_elm_config->thumbscroll_threshhold = 24;
_elm_config->thumbscroll_momentum_threshhold = 100.0;
_elm_config->thumbscroll_friction = 1.0;
_elm_config->scale = 1.0;
_elm_config->font_hinting = 2;
_elm_config->font_dirs = NULL;
_elm_config->image_cache = 4096;
_elm_config->font_cache = 512;
_elm_config->finger_size = 40;
_elm_config->bgpixmap = 0;
_elm_config->compositing = 1;
if (elm_engine)
{
if ((!strcasecmp(elm_engine, "x11")) ||
@ -190,55 +219,6 @@ elm_init(int argc, char **argv)
_elm_config->engine = ELM_SOFTWARE_16_WINCE;
}
_elm_config->thumbscroll_enable = 1;
_elm_config->thumbscroll_threshhold = 24;
_elm_config->thumbscroll_momentum_threshhold = 100.0;
_elm_config->thumbscroll_friction = 1.0;
_elm_config->scale = 1.0;
_elm_config->font_hinting = 2;
_elm_config->font_dirs = NULL;
_elm_config->image_cache = 4096;
_elm_config->font_cache = 512;
_elm_config->finger_size = 40;
_elm_config->bgpixmap = 0;
_elm_config->compositing = 1;
if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
(_elm_config->engine == ELM_SOFTWARE_16_X11) ||
(_elm_config->engine == ELM_XRENDER_X11) ||
(_elm_config->engine == ELM_OPENGL_X11) ||
(_elm_config->engine == ELM_SOFTWARE_WIN32) ||
(_elm_config->engine == ELM_SOFTWARE_16_WINCE))
{
#ifdef HAVE_ELEMENTARY_X
int val = 1000;
if (!ecore_x_init(NULL))
{
EINA_ERROR_PERR("elementary: ERROR. Cannot connect to X11 display. check $DISPLAY variable\n");
exit(1);
}
if (!ecore_x_screen_is_composited(0))
_elm_config->compositing = 0;
_elm_atom_enlightenment_scale = ecore_x_atom_get("ENLIGHTENMENT_SCALE");
ecore_x_event_mask_set(ecore_x_window_root_first_get(),
ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
_elm_event_property_change = ecore_event_handler_add
(ECORE_X_EVENT_WINDOW_PROPERTY, _elm_window_property_change, NULL);
/* FIXME if quickstart this happens in child */
if (ecore_x_window_prop_card32_get(ecore_x_window_root_first_get(),
_elm_atom_enlightenment_scale,
&val, 1) > 0)
{
if (val > 0) _elm_config->scale = (double)val / 1000.0;
}
#endif
}
if (elm_scale)
_elm_config->scale = atof(elm_scale);
if (elm_theme)
_elm_theme_parse(elm_theme);
else
@ -272,7 +252,7 @@ elm_init(int argc, char **argv)
len = p - pp;
strncpy(buf, pp, len);
buf[len] = 0;
_elm_config->font_dirs = eina_list_append(_elm_config->font_dirs, buf);
_elm_config->font_dirs = eina_list_append(_elm_config->font_dirs, eina_stringshare_add(buf));
if (*p == 0) break;
p++;
pp = p;
@ -291,11 +271,6 @@ elm_init(int argc, char **argv)
if (elm_font_cache)
_elm_config->font_cache = atoi(elm_font_cache);
_elm_config->finger_size =
(double)_elm_config->finger_size * _elm_config->scale;
if (elm_finger_size)
_elm_config->finger_size = atoi(elm_finger_size);
/* FIXME: implement quickstart below */
/* if !quickstart return
* else
@ -320,24 +295,70 @@ elm_init(int argc, char **argv)
}
EAPI void
elm_shutdown(void)
elm_quicklaunch_sub_init(int argc, char **argv)
{
ecore_app_args_set(argc, (const char **)argv);
if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
(_elm_config->engine == ELM_SOFTWARE_16_X11) ||
(_elm_config->engine == ELM_XRENDER_X11) ||
(_elm_config->engine == ELM_OPENGL_X11))
{
#ifdef HAVE_ELEMENTARY_X
int val = 1000;
if (!ecore_x_init(NULL))
{
EINA_ERROR_PERR("elementary: ERROR. Cannot connect to X11 display. check $DISPLAY variable\n");
exit(1);
}
if (!ecore_x_screen_is_composited(0))
_elm_config->compositing = 0;
_elm_atom_enlightenment_scale = ecore_x_atom_get("ENLIGHTENMENT_SCALE");
ecore_x_event_mask_set(ecore_x_window_root_first_get(),
ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
_elm_event_property_change = ecore_event_handler_add
(ECORE_X_EVENT_WINDOW_PROPERTY, _elm_window_property_change, NULL);
/* FIXME if quickstart this happens in child */
if (ecore_x_window_prop_card32_get(ecore_x_window_root_first_get(),
_elm_atom_enlightenment_scale,
&val, 1) > 0)
{
if (val > 0) _elm_config->scale = (double)val / 1000.0;
}
#endif
}
if (elm_scale)
_elm_config->scale = atof(elm_scale);
_elm_config->finger_size =
(double)_elm_config->finger_size * _elm_config->scale;
if (elm_finger_size)
_elm_config->finger_size = atoi(elm_finger_size);
}
EAPI void
elm_quicklaunch_sub_shutdown(void)
{
_elm_win_shutdown();
if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
(_elm_config->engine == ELM_SOFTWARE_16_X11) ||
(_elm_config->engine == ELM_XRENDER_X11) ||
(_elm_config->engine == ELM_OPENGL_X11) ||
(_elm_config->engine == ELM_SOFTWARE_WIN32) ||
(_elm_config->engine == ELM_SOFTWARE_16_WINCE))
(_elm_config->engine == ELM_SOFTWARE_16_X11) ||
(_elm_config->engine == ELM_XRENDER_X11) ||
(_elm_config->engine == ELM_OPENGL_X11) ||
(_elm_config->engine == ELM_SOFTWARE_WIN32) ||
(_elm_config->engine == ELM_SOFTWARE_16_WINCE))
{
#ifdef HAVE_ELEMENTARY_X
ecore_event_handler_del(_elm_event_property_change);
_elm_event_property_change = NULL;
ecore_x_shutdown();
ecore_x_disconnect();
#endif
}
}
EAPI void
elm_quicklaunch_shutdown(void)
{
eina_stringshare_del(_elm_data_dir);
_elm_data_dir = NULL;
@ -347,6 +368,9 @@ elm_shutdown(void)
_elm_config->font_dirs = eina_list_remove_list(_elm_config->font_dirs, _elm_config->font_dirs);
}
ecore_event_handler_del(_elm_exit_handler);
_elm_exit_handler = NULL;
free(_elm_config);
free(_elm_appname);
ecore_evas_shutdown();
@ -357,6 +381,182 @@ elm_shutdown(void)
eet_shutdown();
}
EAPI void
elm_quicklaunch_seed(void)
{
Evas_Object *win, *bg, *bt;
win = elm_win_add(NULL, "seed", ELM_WIN_BASIC);
bg = elm_bg_add(win);
elm_win_resize_object_add(win, bg);
evas_object_show(bg);
bt = elm_button_add(win);
elm_button_label_set(bt, " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~-_=+\\|]}[{;:'\",<.>/?");
elm_win_resize_object_add(win, bt);
ecore_main_loop_iterate();
evas_object_del(win);
ecore_main_loop_iterate();
if ((_elm_config->engine == ELM_SOFTWARE_X11) ||
(_elm_config->engine == ELM_SOFTWARE_16_X11) ||
(_elm_config->engine == ELM_XRENDER_X11) ||
(_elm_config->engine == ELM_OPENGL_X11))
{
#ifdef HAVE_ELEMENTARY_X
ecore_x_sync();
#endif
}
ecore_main_loop_iterate();
}
static void *qr_handle = NULL;
static int (*qr_main) (int argc, char **argv) = NULL;
EAPI Evas_Bool
elm_quicklaunch_prepare(int argc, char **argv)
{
char *exe = elm_quicklaunch_exe_path_get(argv[0]);
if (!exe)
{
printf("ERROR: %s does not exist\n", argv[0]);
return;
}
else
{
char *exe2, *p;
char *exename;
exe2 = malloc(strlen(exe) + 1 + 10);
strcpy(exe2, exe);
p = strrchr(exe2, '/');
if (p) p++;
else p = exe2;
exename = alloca(strlen(p) + 1);
strcpy(exename, p);
*p = 0;
strcat(p, "../lib/");
strcat(p, exename);
strcat(p, ".so");
if (access(exe2, R_OK | X_OK) == 0)
{
free(exe);
exe = exe2;
}
else
free(exe2);
}
qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL);
free(exe);
if (!qr_handle) return 0;
qr_main = dlsym(qr_handle, "elm_main");
if (!qr_main)
{
dlclose(qr_handle);
qr_handle = NULL;
return 0;
}
return 1;
}
EAPI Evas_Bool
elm_quicklaunch_fork(int argc, char **argv, char *cwd)
{
pid_t child;
int ret;
int real_argc;
char **real_argv;
// FIXME:
// need to accept current environment from elementary_run
if (!qr_main)
{
int i;
char **args;
child = fork();
if (child) return 1;
chdir(cwd);
args = alloca((argc + 1) * sizeof(char *));
for (i = 0; i < argc; i++) args[i] = argv[i];
args[argc] = NULL;
printf("WARNING: %s not quicklaunch capable\n", argv[0]);
exit(execvp(argv[0], args));
}
child = fork();
if (child) return 1;
chdir(cwd);
ret = qr_main(argc, argv);
exit(ret);
}
EAPI void
elm_quicklaunch_cleanup(void)
{
if (qr_handle)
{
dlclose(qr_handle);
qr_handle = NULL;
qr_main = NULL;
}
}
EAPI int
elm_quicklaunch_fallback(int argc, char **argv)
{
int ret;
elm_quicklaunch_init(argc, argv);
elm_quicklaunch_sub_init(argc, argv);
elm_quicklaunch_prepare(argc, argv);
ret = qr_main(argc, argv);
exit(ret);
}
EAPI char *
elm_quicklaunch_exe_path_get(const char *exe)
{
static char *path = NULL;
static Eina_List *pathlist = NULL;
Eina_List *l;
char buf[PATH_MAX];
if (exe[0] == '/') return strdup(exe);
if ((exe[0] == '.') && (exe[1] == '/')) return strdup(exe);
if ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/')) return strdup(exe);
if (!path)
{
const char *p, *pp, *s;
char *buf;
path = getenv("PATH");
buf = alloca(strlen(path) + 1);
p = path;
pp = p;
for (;;)
{
if ((*p == ':') || (*p == 0))
{
int len;
len = p - pp;
strncpy(buf, pp, len);
buf[len] = 0;
pathlist = eina_list_append(pathlist, eina_stringshare_add(buf));
if (*p == 0) break;
p++;
pp = p;
}
else
{
if (*p == 0) break;
p++;
}
}
}
for (l = pathlist; l; l = l->next)
{
snprintf(buf, sizeof(buf), "%s/%s", l->data, exe);
if (access(buf, R_OK | X_OK) == 0) return strdup(buf);
}
return NULL;
}
EAPI void
elm_run(void)
{