aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/e_exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/e_exec.c')
-rw-r--r--src/bin/e_exec.c145
1 files changed, 134 insertions, 11 deletions
diff --git a/src/bin/e_exec.c b/src/bin/e_exec.c
index c48fbbe47..cedcdeefb 100644
--- a/src/bin/e_exec.c
+++ b/src/bin/e_exec.c
@@ -11,6 +11,7 @@
typedef struct _E_Exec_Launch E_Exec_Launch;
typedef struct _E_Exec_Search E_Exec_Search;
+typedef struct _E_Exec_Watch E_Exec_Watch;
struct _E_Exec_Launch
{
@@ -21,10 +22,18 @@ struct _E_Exec_Launch
struct _E_Exec_Search
{
E_Exec_Instance *inst;
+ Efreet_Desktop *desktop;
int startup_id;
pid_t pid;
};
+struct _E_Exec_Watch
+{
+ void (*func) (void *data, E_Exec_Instance *inst, E_Exec_Watch_Type type);
+ const void *data;
+ Eina_Bool delete_me : 1;
+};
+
struct _E_Config_Dialog_Data
{
Efreet_Desktop *desktop;
@@ -99,18 +108,36 @@ e_exec(E_Zone *zone, Efreet_Desktop *desktop, const char *exec,
{
E_Exec_Launch *launch;
E_Exec_Instance *inst = NULL;
- const char *single = NULL;
if ((!desktop) && (!exec)) return NULL;
if (desktop)
{
+ const char *single;
+
single = eina_hash_find(desktop->x, "X-Enlightenment-Single-Instance");
- if (single)
+ if ((single) ||
+ (e_config->exe_always_single_instance))
{
- if ((!strcasecmp(single, "true")) ||
- (!strcasecmp(single, "yes"))||
- (!strcasecmp(single, "1")))
+ Eina_Bool dosingle = EINA_FALSE;
+
+ // first take system config for always single instance if set
+ if (e_config->exe_always_single_instance) dosingle = EINA_TRUE;
+
+ // and now let desktop file override it
+ if (single)
+ {
+ if ((!strcasecmp(single, "true")) ||
+ (!strcasecmp(single, "yes"))||
+ (!strcasecmp(single, "1")))
+ dosingle = EINA_TRUE;
+ else if ((!strcasecmp(single, "false")) ||
+ (!strcasecmp(single, "no"))||
+ (!strcasecmp(single, "0")))
+ dosingle = EINA_FALSE;
+ }
+
+ if (dosingle)
{
Eina_List *l;
E_Border *bd;
@@ -121,7 +148,8 @@ e_exec(E_Zone *zone, Efreet_Desktop *desktop, const char *exec,
{
if (bd)
{
- if (!bd->focused) e_border_activate(bd, EINA_TRUE);
+ if (!bd->focused)
+ e_border_activate(bd, EINA_TRUE);
else e_border_raise(bd);
return NULL;
}
@@ -166,6 +194,7 @@ e_exec_startup_id_pid_instance_find(int id, pid_t pid)
E_Exec_Search search;
search.inst = NULL;
+ search.desktop = NULL;
search.startup_id = id;
search.pid = pid;
eina_hash_foreach(e_exec_instances, _e_exec_startup_id_pid_find, &search);
@@ -182,6 +211,87 @@ e_exec_startup_id_pid_find(int id, pid_t pid)
return inst->desktop;
}
+EAPI E_Exec_Instance *
+e_exec_startup_desktop_instance_find(Efreet_Desktop *desktop)
+{
+ E_Exec_Search search;
+
+ search.inst = NULL;
+ search.desktop = desktop;
+ search.startup_id = 0;
+ search.pid = 0;
+ eina_hash_foreach(e_exec_instances, _e_exec_startup_id_pid_find, &search);
+ return search.inst;
+}
+
+static void
+_e_exe_instance_watchers_call(E_Exec_Instance *inst, E_Exec_Watch_Type type)
+{
+ E_Exec_Watch *iw;
+ Eina_List *l, *ln;
+
+ inst->walking++;
+ EINA_LIST_FOREACH(inst->watchers, l, iw)
+ {
+ if (iw->func) iw->func((void *)(iw->data), inst, type);
+ }
+ inst->walking--;
+ if (inst->walking == 0)
+ {
+ EINA_LIST_FOREACH_SAFE(inst->watchers, l, ln, iw)
+ {
+ if (iw->delete_me)
+ {
+ inst->watchers = eina_list_remove_list(inst->watchers, l);
+ free(iw);
+ }
+ }
+ }
+}
+
+EAPI void
+e_exec_instance_found(E_Exec_Instance *inst)
+{
+ _e_exe_instance_watchers_call(inst, E_EXEC_WATCH_STARTED);
+}
+
+EAPI void
+e_exec_instance_watcher_add(E_Exec_Instance *inst, void (*func) (void *data, E_Exec_Instance *inst, E_Exec_Watch_Type type), const void *data)
+{
+ E_Exec_Watch *iw;
+
+ iw = E_NEW(E_Exec_Watch, 1);
+ if (!iw) return;
+ iw->func = func;
+ iw->data = data;
+ inst->watchers = eina_list_append(inst->watchers, iw);
+}
+
+EAPI void
+e_exec_instance_watcher_del(E_Exec_Instance *inst, void (*func) (void *data, E_Exec_Instance *inst, E_Exec_Watch_Type type), const void *data)
+{
+ E_Exec_Watch *iw;
+ Eina_List *l, *ln;
+
+ EINA_LIST_FOREACH_SAFE(inst->watchers, l, ln, iw)
+ {
+ if ((iw->func == func) && (iw->data == data))
+ {
+ if (inst->walking == 0)
+ {
+ inst->watchers = eina_list_remove_list(inst->watchers, l);
+ free(iw);
+ return;
+ }
+ else
+ {
+ iw->delete_me = EINA_TRUE;
+ return;
+ }
+ }
+ }
+}
+
/* local subsystem functions */
static E_Exec_Instance *
_e_exec_cb_exec(void *data, Efreet_Desktop *desktop, char *exec, int remaining)
@@ -407,6 +517,7 @@ _e_exec_cb_expire_timer(void *data)
e_exec_start_pending = eina_list_remove(e_exec_start_pending,
inst->desktop);
inst->expire_timer = NULL;
+ _e_exe_instance_watchers_call(inst, E_EXEC_WATCH_TIMEOUT);
return ECORE_CALLBACK_CANCEL;
}
@@ -414,7 +525,11 @@ static void
_e_exec_instance_free(E_Exec_Instance *inst)
{
Eina_List *instances;
-
+ E_Exec_Watch *iw;
+
+ _e_exe_instance_watchers_call(inst, E_EXEC_WATCH_STOPPED);
+ EINA_LIST_FREE(inst->watchers, iw) free(iw);
+
if (inst->key)
{
instances = eina_hash_find(e_exec_instances, inst->key);
@@ -435,13 +550,14 @@ _e_exec_instance_free(E_Exec_Instance *inst)
if (inst->desktop) efreet_desktop_free(inst->desktop);
free(inst);
}
-
+/*
static Eina_Bool
_e_exec_cb_instance_finish(void *data)
{
_e_exec_instance_free(data);
return ECORE_CALLBACK_CANCEL;
}
+*/
static Eina_Bool
_e_exec_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
@@ -509,14 +625,17 @@ _e_exec_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
}
}
- /* maybe better 1 minute? it might be openoffice */
- if (ecore_time_get() - inst->launch_time < 2.0)
+/* scripts that fork off children with & break child tracking... but this hack
+ * also breaks apps that handle single-instance themselves */
+/*
+ if ((ecore_time_get() - inst->launch_time) < 2.0)
{
inst->exe = NULL;
if (inst->expire_timer) ecore_timer_del(inst->expire_timer);
inst->expire_timer = ecore_timer_add(e_config->exec.expire_timeout, _e_exec_cb_instance_finish, inst);
}
else
+ */
_e_exec_instance_free(inst);
return ECORE_CALLBACK_PASS_ON;
@@ -532,8 +651,12 @@ _e_exec_startup_id_pid_find(const Eina_Hash *hash __UNUSED__, const void *key __
search = data;
EINA_LIST_FOREACH(value, l, inst)
{
- if (((search->startup_id > 0) &&
+ if (((search->desktop) &&
+ (search->desktop == inst->desktop)) ||
+
+ ((search->startup_id > 0) &&
(search->startup_id == inst->startup_id)) ||
+
((inst->exe) && (search->pid > 1) &&
(search->pid == ecore_exe_pid_get(inst->exe))))
{