summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2017-11-03 11:41:14 -0400
committerMike Blumenkrantz <zmike@osg.samsung.com>2017-11-03 11:41:14 -0400
commitaafb9954ba1850a7173e841eef8fc0d1c4b5c3e9 (patch)
tree2a341eb1381d44a3cdf7ca21f4ea06d8786aac48
parent054b72912ba51abd9bdce347a1b6e2eddee4cbc4 (diff)
remove sandbox base infra
-rw-r--r--loader/loader.c310
-rw-r--r--loader/test.c2
-rw-r--r--meson.build44
-rw-r--r--src/Makefile.mk4
-rw-r--r--src/e_mod_main.c9
-rw-r--r--src/e_mod_main.h5
-rw-r--r--src/runner.c930
7 files changed, 6 insertions, 1298 deletions
diff --git a/loader/loader.c b/loader/loader.c
deleted file mode 100644
index 1b32304..0000000
--- a/loader/loader.c
+++ /dev/null
@@ -1,310 +0,0 @@
1#include "config.h"
2#define EFL_BETA_API_SUPPORT
3#include <Ecore_Wl2.h>
4#include <Elementary.h>
5#include <dlfcn.h>
6#include "e-gadget-client-protocol.h"
7#include "action_route-client-protocol.h"
8#include <uuid.h>
9
10static Ecore_Event_Handler *handler;
11
12static Eina_Hash *wins;
13static Eina_Hash *gadget_globals;
14static Eina_Hash *ar_globals;
15static Eina_Hash *display_actions;
16
17typedef struct Gadget_Action
18{
19 Ecore_Wl2_Display *d;
20 Eina_Stringshare *action;
21 char handle[37];
22 Eina_List *requestors;
23 struct action_route_bind *ar_bind;
24} Gadget_Action;
25
26static inline Ecore_Wl2_Display *
27win_display_get(Evas_Object *win)
28{
29 Ecore_Wl2_Window *ww;
30 ww = elm_win_wl_window_get(win);
31 return ecore_wl2_window_display_get(ww);
32}
33
34static void
35wins_emit(Ecore_Wl2_Display *d, const char *sig, uint32_t val)
36{
37 Eina_List *l, *ll;
38 Evas_Object *win;
39
40 l = eina_hash_find(wins, &d);
41 EINA_LIST_FOREACH(l, ll, win)
42 evas_object_smart_callback_call(win, sig, (uintptr_t*)(uintptr_t)val);
43}
44
45static void
46_gadget_anchor(void *data, struct e_gadget *e_gadget EINA_UNUSED, uint32_t anchor)
47{
48 wins_emit(data, "gadget_site_anchor", anchor);
49}
50
51static void
52_gadget_orient(void *data, struct e_gadget *e_gadget EINA_UNUSED, uint32_t orient)
53{
54 wins_emit(data, "gadget_site_orient", orient);
55}
56
57static void
58_gadget_gravity(void *data, struct e_gadget *e_gadget EINA_UNUSED, uint32_t gravity)
59{
60 wins_emit(data, "gadget_site_gravity", gravity);
61}
62
63static const struct e_gadget_listener _gadget_listener =
64{
65 _gadget_anchor,
66 _gadget_orient,
67 _gadget_gravity,
68};
69
70static void
71_gadget_global_bind(Ecore_Wl2_Display *d, uint32_t id)
72{
73 struct e_gadget *gadget_global = wl_registry_bind(ecore_wl2_display_registry_get(d), id, &e_gadget_interface, 1);
74 e_gadget_add_listener(gadget_global, &_gadget_listener, d);
75 eina_hash_add(gadget_globals, &d, gadget_global);
76}
77
78static void
79_ar_global_bind(Ecore_Wl2_Display *d, uint32_t id)
80{
81 struct action_route *ar_global = wl_registry_bind(ecore_wl2_display_registry_get(d), id, &action_route_interface, 1);
82 eina_hash_add(ar_globals, &d, ar_global);
83}
84
85static Eina_Bool
86_global_added(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Wl2_Event_Global *ev)
87{
88 if (eina_streq(ev->interface, "e_gadget"))
89 _gadget_global_bind(ev->display, ev->id);
90 else if (eina_streq(ev->interface, "action_route"))
91 _ar_global_bind(ev->display, ev->id);
92 return ECORE_CALLBACK_RENEW;
93}
94
95static void
96_gadget_init(Ecore_Wl2_Display *d)
97{
98 Eina_Iterator *it;
99 Ecore_Wl2_Global *g;
100
101 if (wins)
102 {
103 if (eina_hash_find(gadget_globals, &d)) return;
104 }
105 else
106 {
107 gadget_globals = eina_hash_pointer_new(NULL);
108 ar_globals = eina_hash_pointer_new(NULL);
109 }
110 it = ecore_wl2_display_globals_get(d);
111 EINA_ITERATOR_FOREACH(it, g)
112 {
113 if (eina_streq(g->interface, "e_gadget"))
114 _gadget_global_bind(d, g->id);
115 else if (eina_streq(g->interface, "action_route"))
116 _ar_global_bind(d, g->id);
117 }
118 eina_iterator_free(it);
119 if (!handler)
120 handler = ecore_event_handler_add(ECORE_WL2_EVENT_GLOBAL_ADDED, (Ecore_Event_Handler_Cb)_global_added, NULL);
121}
122
123static void
124_ar_bind_activate(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
125{
126 const char *params = event_info;
127 Gadget_Action *ga = data;
128
129 if (params && (!params[0])) params = NULL;
130 action_route_bind_activate(ga->ar_bind, params);
131}
132
133static void
134_ar_bind_del(Gadget_Action *ga)
135{
136 Evas_Object *r;
137 eina_stringshare_del(ga->action);
138 EINA_LIST_FREE(ga->requestors, r)
139 evas_object_smart_callback_del_full(r, ga->handle, _ar_bind_activate, ga);
140 free(ga);
141}
142
143static void
144_ar_bind_end(void *data, struct action_route_bind *action_route_bind EINA_UNUSED)
145{
146 Gadget_Action *ga = data;
147 Eina_List *l;
148 Evas_Object *r;
149
150 EINA_LIST_FOREACH(ga->requestors, l, r)
151 evas_object_smart_callback_call(r, "gadget_action_end", ga->handle);
152}
153
154static void
155_ar_bind_status(void *data, struct action_route_bind *action_route_bind, uint32_t state)
156{
157 uuid_t u;
158 Gadget_Action *ga = data;
159 Evas_Object *r;
160
161 if (state == ACTION_ROUTE_BIND_STATE_REJECTED)
162 {
163 Eina_Hash *h;
164 Eina_List *l;
165 h = eina_hash_find(display_actions, &ga->d);
166 EINA_LIST_FOREACH(ga->requestors, l, r)
167 {
168 if (ga->handle[0])
169 evas_object_smart_callback_call(r, "gadget_action_deleted", ga->handle);
170 else
171 evas_object_smart_callback_call(r, "gadget_action", NULL);
172 }
173 eina_hash_del_by_key(h, ga->action);
174 return;
175 }
176 uuid_generate(u);
177 uuid_unparse_lower(u, ga->handle);
178 ga->ar_bind = action_route_bind;
179 r = eina_list_data_get(ga->requestors);
180 evas_object_smart_callback_add(r, ga->handle, _ar_bind_activate, ga);
181 evas_object_smart_callback_call(r, "gadget_action", ga->handle);
182}
183
184static const struct action_route_bind_listener _ar_bind_interface =
185{
186 _ar_bind_status,
187 _ar_bind_end
188};
189
190static void
191uriopen_request(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
192{
193 Ecore_Wl2_Display *d = data;
194 const char *uri = event_info;
195 struct e_gadget *gadget_global = eina_hash_find(gadget_globals, &d);
196
197 e_gadget_open_uri(gadget_global, uri);
198}
199
200static void
201action_request(void *data, Evas_Object *obj, void *event_info)
202{
203 Gadget_Action *ga;
204 const char *action = event_info;
205 Ecore_Wl2_Display *d = data;
206 void *ar_global;
207 struct action_route_bind *ar_bind;
208 Eina_Hash *h;
209
210 if ((!action) || (!action[0]))
211 {
212 evas_object_smart_callback_call(obj, "gadget_action", NULL);
213 return;
214 }
215 if (display_actions)
216 {
217 h = eina_hash_find(display_actions, &d);
218 if (h)
219 {
220 ga = eina_hash_find(h, action);
221 if (ga && (!eina_list_data_find(ga->requestors, obj)))
222 {
223 ga->requestors = eina_list_append(ga->requestors, obj);
224 evas_object_smart_callback_add(obj, ga->handle, _ar_bind_activate, ga);
225 }
226 evas_object_smart_callback_call(obj, "gadget_action", ga ? ga->handle : NULL);
227 return;
228 }
229 }
230 ar_global = eina_hash_find(ar_globals, &d);
231 if (!ar_global)
232 {
233 evas_object_smart_callback_call(obj, "gadget_action", NULL);
234 return;
235 }
236 ga = calloc(1, sizeof(Gadget_Action));
237 ga->d = d;
238 ga->requestors = eina_list_append(ga->requestors, obj);
239 ga->action = eina_stringshare_add(action);
240 if (!display_actions)
241 display_actions = eina_hash_string_superfast_new(NULL);
242 h = eina_hash_find(display_actions, &d);
243 if (!h)
244 {
245 h = eina_hash_pointer_new((Eina_Free_Cb)_ar_bind_del);
246 eina_hash_add(display_actions, &d, h);
247 }
248
249 ar_bind = action_route_bind_action(ar_global, action);
250 action_route_bind_add_listener(ar_bind, &_ar_bind_interface, ga);
251 wl_display_roundtrip(ecore_wl2_display_get(d));
252}
253
254static void
255win_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
256{
257 Ecore_Wl2_Display *d = win_display_get(obj);
258 eina_hash_list_remove(wins, &d, obj);
259}
260
261static Evas_Object *
262win_add(Evas_Object *win)
263{
264 Ecore_Wl2_Display *d;
265 if (!win) return NULL;
266 d = win_display_get(win);
267 _gadget_init(d);
268 if (!wins)
269 wins = eina_hash_pointer_new(NULL);
270 eina_hash_list_append(wins, &d, win);
271 evas_object_smart_callback_add(win, "gadget_action_request", action_request, d);
272 evas_object_smart_callback_add(win, "gadget_open_uri", uriopen_request, d);
273 evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, win_del, NULL);
274 elm_win_borderless_set(win, 1);
275 return win;
276}
277
278int
279eina_init(void)
280{
281 int (*_eina_init)(void) = dlsym(RTLD_NEXT, __func__);
282
283 if (wins) return _eina_init();
284 if (getenv("RUNNER_DEBUG")) raise(SIGSTOP);
285 return _eina_init();
286}
287
288Evas_Object *
289elm_win_util_dialog_add(Evas_Object *parent, const char *name, const char *title)
290{
291 Evas_Object *(*_elm_win_util_dialog_add)(Evas_Object *, const char *, const char *) = dlsym(RTLD_NEXT, __func__);
292
293 return win_add(_elm_win_util_dialog_add(parent, name, title));
294}
295
296Evas_Object *
297elm_win_util_standard_add(const char *name, const char *title)
298{
299 Evas_Object *(*_elm_win_util_standard_add)(const char *, const char *) = dlsym(RTLD_NEXT, __func__);
300
301 return win_add(_elm_win_util_standard_add(name, title));
302}
303
304Evas_Object *
305elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type)
306{
307 Evas_Object *(*_elm_win_add)(Evas_Object *,const char*, Elm_Win_Type) = dlsym(RTLD_NEXT, __func__);
308
309 return win_add(_elm_win_add(parent, name, type));
310}
diff --git a/loader/test.c b/loader/test.c
index 82c81f4..d44c278 100644
--- a/loader/test.c
+++ b/loader/test.c
@@ -97,6 +97,8 @@ main(int argc, char *argv[])
97 elm_win_alpha_set(win, EINA_TRUE); 97 elm_win_alpha_set(win, EINA_TRUE);
98 98
99 ic = elm_icon_add(win); 99 ic = elm_icon_add(win);
100 elm_object_tooltip_text_set(ic, "this is some test text which is probably going to be a lot longer than the overall icon size haHAA");
101 elm_object_tooltip_window_mode_set(ic, 1);
100 snprintf(buf, sizeof(buf), "%s/images/logo.png", elm_app_data_dir_get()); 102 snprintf(buf, sizeof(buf), "%s/images/logo.png", elm_app_data_dir_get());
101 elm_image_file_set(ic, buf, NULL); 103 elm_image_file_set(ic, buf, NULL);
102 elm_image_object_size_get(ic, &w, &h); 104 elm_image_object_size_get(ic, &w, &h);
diff --git a/meson.build b/meson.build
index 12de729..ed346a8 100644
--- a/meson.build
+++ b/meson.build
@@ -40,7 +40,8 @@ endif
40endforeach 40endforeach
41add_global_arguments(dev_cflags, language: 'c') 41add_global_arguments(dev_cflags, language: 'c')
42 42
43release = 'ver-0.22' 43dep_e = dependency('enlightenment')
44release = dep_e.get_pkgconfig_variable('release')
44host_os = host_machine.system() 45host_os = host_machine.system()
45if host_os == 'linux' 46if host_os == 'linux'
46 if cc.has_header_symbol('features.h', '__UCLIBC__') 47 if cc.has_header_symbol('features.h', '__UCLIBC__')
@@ -109,8 +110,7 @@ add_global_arguments('-DPACKAGE_LIB_DIR="@0@"'.format(dir_lib), language: 'c')
109add_global_arguments('-DPACKAGE_DATA_DIR="@0@"'.format(join_paths(dir_data, meson.project_name())), language: 'c') 110add_global_arguments('-DPACKAGE_DATA_DIR="@0@"'.format(join_paths(dir_data, meson.project_name())), language: 'c')
110add_global_arguments('-DPACKAGE_SYSCONF_DIR="@0@"'.format(dir_sysconf), language: 'c') 111add_global_arguments('-DPACKAGE_SYSCONF_DIR="@0@"'.format(dir_sysconf), language: 'c')
111 112
112dep_efl_wl = dependency('efl-wl', version: '>= 1.20.99', required: false) 113dep_efl_wl = dependency('efl-wl', required: false)
113dep_e = dependency('enlightenment')
114 114
115dir_module_e = join_paths([dep_e.get_pkgconfig_variable('modules'), 'desksanity']) 115dir_module_e = join_paths([dep_e.get_pkgconfig_variable('modules'), 'desksanity'])
116edje_cc = find_program('edje_cc') 116edje_cc = find_program('edje_cc')
@@ -132,45 +132,9 @@ build_files = [
132] 132]
133 133
134if dep_efl_wl.found() == true and dep_e.get_pkgconfig_variable('wayland') == 'true' 134if dep_efl_wl.found() == true and dep_e.get_pkgconfig_variable('wayland') == 'true'
135 build_files += 'src/runner.c'
136 config_h.set('HAVE_RUNNER', '1') 135 config_h.set('HAVE_RUNNER', '1')
137 136
138 wayland_scanner = find_program('wayland-scanner') 137 dir_gadgets = join_paths([dir_lib, 'enlightenment/gadgets', module_arch])
139 gen_scanner_client = generator(wayland_scanner,
140 output: '@BASENAME@-client-protocol.h',
141 arguments: ['client-header', '@INPUT@', '@OUTPUT@'])
142 gen_scanner_server = generator(wayland_scanner,
143 output: '@BASENAME@-server-protocol.h',
144 arguments: ['server-header', '@INPUT@', '@OUTPUT@'])
145 gen_scanner_impl = generator(wayland_scanner,
146 output: '@BASENAME@-protocol.c',
147 arguments: ['code', '@INPUT@', '@OUTPUT@'])
148 protos = [
149 'e-gadget.xml',
150 'action_route.xml',
151 ]
152
153 loader_src = ['loader/loader.c']
154 foreach proto: protos
155 loader_src += gen_scanner_client.process(proto)
156 loader_src += gen_scanner_impl.process(proto)
157 endforeach
158 foreach proto: protos
159 build_files += gen_scanner_server.process(proto)
160 build_files += gen_scanner_impl.process(proto)
161 endforeach
162
163 shared_library('loader', loader_src,
164 name_prefix: '',
165 dependencies: [
166 dependency('elementary'),
167 dependency('ecore-wl2'),
168 dependency('wayland-client'),
169 cc.find_library('uuid')],
170 install_dir: join_paths([dir_module_e, module_arch]),
171 install: true)
172
173 dir_gadgets = join_paths([dir_lib, 'enlightenment/gadgets', dep_e.get_pkgconfig_variable('release')])
174 executable('e_gadget_start', 138 executable('e_gadget_start',
175 'loader/start.c', 139 'loader/start.c',
176 c_args: '-fPIE', 140 c_args: '-fPIE',
diff --git a/src/Makefile.mk b/src/Makefile.mk
index 6559e64..1649c6b 100644
--- a/src/Makefile.mk
+++ b/src/Makefile.mk
@@ -19,10 +19,6 @@ src/zoom.c \
19src/magnify.c \ 19src/magnify.c \
20src/desksanity.c 20src/desksanity.c
21 21
22if BUILD_RUNNER
23module_la_SOURCES += src/runner.c
24endif
25
26module_la_LIBADD = @E_LIBS@ 22module_la_LIBADD = @E_LIBS@
27module_la_LDFLAGS = -module -avoid-version 23module_la_LDFLAGS = -module -avoid-version
28module_la_DEPENDENCIES = $(top_builddir)/config.h 24module_la_DEPENDENCIES = $(top_builddir)/config.h
diff --git a/src/e_mod_main.c b/src/e_mod_main.c
index a77940a..1b3ce40 100644
--- a/src/e_mod_main.c
+++ b/src/e_mod_main.c
@@ -261,9 +261,6 @@ e_modapi_init(E_Module *m)
261 pip_init(); 261 pip_init();
262 zoom_init(); 262 zoom_init();
263 mag_init(); 263 mag_init();
264#ifdef HAVE_RUNNER
265 runner_init();
266#endif
267 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY, ds_client_urgent, NULL); 264 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY, ds_client_urgent, NULL);
268 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE, ds_client_remove, NULL); 265 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE, ds_client_remove, NULL);
269 E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_AFTER_SHOW, ds_desk_after_show, NULL); 266 E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_AFTER_SHOW, ds_desk_after_show, NULL);
@@ -278,9 +275,6 @@ e_modapi_init(E_Module *m)
278E_API int 275E_API int
279e_modapi_shutdown(E_Module *m EINA_UNUSED) 276e_modapi_shutdown(E_Module *m EINA_UNUSED)
280{ 277{
281#ifdef HAVE_RUNNER
282 runner_shutdown();
283#endif
284 mag_shutdown(); 278 mag_shutdown();
285 zoom_shutdown(); 279 zoom_shutdown();
286 pip_shutdown(); 280 pip_shutdown();
@@ -313,9 +307,6 @@ E_API int
313e_modapi_save(E_Module *m EINA_UNUSED) 307e_modapi_save(E_Module *m EINA_UNUSED)
314{ 308{
315 e_config_domain_save("module.desksanity", conf_edd, ds_config); 309 e_config_domain_save("module.desksanity", conf_edd, ds_config);
316#ifdef HAVE_RUNNER
317 runner_save();
318#endif
319 return 1; 310 return 1;
320} 311}
321 312
diff --git a/src/e_mod_main.h b/src/e_mod_main.h
index 0c2904d..22d094c 100644
--- a/src/e_mod_main.h
+++ b/src/e_mod_main.h
@@ -106,9 +106,4 @@ EINTERN void zoom_shutdown(void);
106EINTERN void mag_init(void); 106EINTERN void mag_init(void);
107EINTERN void mag_shutdown(void); 107EINTERN void mag_shutdown(void);
108 108
109#ifdef HAVE_RUNNER
110EINTERN void runner_init(void);
111EINTERN void runner_shutdown(void);
112EINTERN void runner_save(void);
113#endif
114#endif 109#endif
diff --git a/src/runner.c b/src/runner.c
deleted file mode 100644
index 434cdae..0000000
--- a/src/runner.c
+++ /dev/null
@@ -1,930 +0,0 @@
1#define HAVE_WAYLAND
2#include "e_mod_main.h"
3#include <Efl_Wl.h>
4#include "e-gadget-server-protocol.h"
5#include "action_route-server-protocol.h"
6#include <sched.h>
7
8#ifdef __GNUC__
9# pragma GCC diagnostic ignored "-Wformat-truncation"
10#endif
11
12typedef enum
13{
14 EXIT_MODE_RESTART,
15 EXIT_MODE_DELETE,
16} Exit_Mode;
17
18typedef struct Config_Item
19{
20 int id;
21 int exit_mode;
22 Eina_Stringshare *cmd;
23 void *inst;
24 Eina_Bool cmd_changed : 1;
25} Config_Item;
26
27typedef struct Instance
28{
29 Evas_Object *box;
30 Evas_Object *obj;
31 Ecore_Exe *exe;
32 Config_Item *ci;
33 Eina_Hash *allowed_pids;
34 void *gadget_resource;
35 Evas_Object *popup;
36 Evas_Object *ctxpopup;
37 Eina_List *extracted;
38} Instance;
39
40typedef struct RConfig
41{
42 Eina_List *items;
43 Evas_Object *config_dialog;
44} RConfig;
45
46static E_Config_DD *conf_edd = NULL;
47static E_Config_DD *conf_item_edd = NULL;
48
49static int ns_fd = -1;
50
51static RConfig *rconfig;
52static Eina_List *instances;
53static Eina_List *wizards;
54
55static Eina_Hash *sandbox_gadgets;
56
57static Eina_List *handlers;
58static Eio_Monitor *gadget_monitor;
59static Eio_File *gadget_lister;
60
61typedef struct Wizard_Item
62{
63 Evas_Object *site;
64 Evas_Object *popup;
65 E_Gadget_Wizard_End_Cb cb;
66 void *data;
67 int id;
68 Eina_Bool sandbox : 1;
69} Wizard_Item;
70
71static void
72runner_run(Instance *inst)
73{
74 char *preload = eina_strdup(getenv("LD_PRELOAD"));
75 char buf[PATH_MAX];
76 char *file = ecore_file_dir_get(mod->module->file);
77 int pid;
78
79 snprintf(buf, sizeof(buf), "%s/loader.so", file);
80 e_util_env_set("LD_PRELOAD", buf);
81
82 snprintf(buf, sizeof(buf), "%d", inst->ci->id);
83 e_util_env_set("E_GADGET_ID", buf);
84
85 unshare(CLONE_NEWPID);
86
87 inst->exe = efl_wl_run(inst->obj, inst->ci->cmd);
88
89 setns(ns_fd, CLONE_NEWPID);
90
91 e_util_env_set("E_GADGET_ID", NULL);
92 e_util_env_set("LD_PRELOAD", preload);
93 free(file);
94 free(preload);
95 eina_hash_free_buckets(inst->allowed_pids);
96 pid = ecore_exe_pid_get(inst->exe);
97 eina_hash_add(inst->allowed_pids, &pid, (void*)1);
98}
99
100static void
101_config_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
102{
103 Config_Item *ci = data;
104 Instance *inst = ci->inst;
105
106 e_comp_ungrab_input(1, 1);
107 rconfig->config_dialog = NULL;
108 if (ci->cmd_changed)
109 {
110 char *cmd;
111
112 cmd = elm_entry_markup_to_utf8(elm_entry_entry_get(evas_object_data_get(obj, "entry")));
113 eina_stringshare_replace(&ci->cmd, cmd);
114 free(cmd);
115 e_config_save_queue();
116 }
117 if (!inst) ci->cmd_changed = 0;
118 if (!ci->cmd_changed) return;
119 ci->cmd_changed = 0;
120 if (inst->exe) ecore_exe_quit(inst->exe);
121 runner_run(inst);
122}
123
124static void
125_config_label_add(Evas_Object *tb, const char *txt, int row)
126{
127 Evas_Object *o;
128
129 o = elm_label_add(tb);
130 E_ALIGN(o, 0, 0.5);
131 elm_object_text_set(o, txt);
132 evas_object_show(o);
133 elm_table_pack(tb, o, 0, row, 1, 1);
134}
135
136static void
137_config_cmd_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
138{
139 Config_Item *ci = data;
140
141 ci->cmd_changed = 1;
142}
143
144static void
145_config_cmd_activate(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
146{
147 Config_Item *ci = data;
148 Instance *inst = ci->inst;
149 char *cmd;
150
151 ci->cmd_changed = 0;
152 cmd = elm_entry_markup_to_utf8(elm_entry_entry_get(obj));
153 eina_stringshare_replace(&ci->cmd, cmd);
154 free(cmd);
155 e_config_save_queue();
156 if (!inst) return;
157 if (inst->exe) ecore_exe_quit(inst->exe);
158 runner_run(inst);
159}
160
161EINTERN Evas_Object *
162config_runner(Config_Item *ci, E_Zone *zone)
163{
164 Evas_Object *popup, *tb, *o, *ent, *rg;
165 int row = 0;
166
167 if (!zone) zone = e_zone_current_get();
168 popup = elm_popup_add(e_comp->elm);
169 E_EXPAND(popup);
170 evas_object_layer_set(popup, E_LAYER_POPUP);
171 elm_popup_allow_events_set(popup, 1);
172 elm_popup_scrollable_set(popup, 1);
173
174 tb = elm_table_add(popup);
175 elm_table_align_set(tb, 0, 0.5);
176 E_EXPAND(tb);
177 evas_object_show(tb);
178 elm_object_content_set(popup, tb);
179
180 o = evas_object_rectangle_add(e_comp->evas);
181 evas_object_size_hint_min_set(o, ELM_SCALE_SIZE(200), 1);
182 elm_table_pack(tb, o, 0, row++, 2, 1);
183
184 _config_label_add(tb, D_("Command:"), row);
185 ent = o = elm_entry_add(tb);
186 E_FILL(o);
187 evas_object_show(o);
188 elm_entry_single_line_set(o, 1);
189 elm_entry_entry_set(o, ci->cmd);
190 evas_object_smart_callback_add(o, "changed,user", _config_cmd_changed, ci);
191 evas_object_smart_callback_add(o, "activated", _config_cmd_activate, ci);
192 elm_table_pack(tb, o, 1, row++, 1, 1);
193
194 _config_label_add(tb, D_("On Exit:"), row);
195 o = rg = elm_radio_add(tb);
196 E_FILL(o);
197 evas_object_show(o);
198 elm_object_text_set(o, D_("Restart"));
199 elm_radio_state_value_set(o, EXIT_MODE_RESTART);
200 elm_radio_value_pointer_set(o, &ci->exit_mode);
201 elm_table_pack(tb, o, 1, row++, 1, 1);
202
203 o = elm_radio_add(tb);
204 E_FILL(o);
205 elm_radio_group_add(o, rg);
206 evas_object_show(o);
207 elm_object_text_set(o, D_("Delete"));
208 elm_radio_state_value_set(o, EXIT_MODE_DELETE);
209 elm_table_pack(tb, o, 1, row++, 1, 1);
210
211
212 popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE);
213 evas_object_layer_set(popup, E_LAYER_POPUP);
214 evas_object_move(popup, zone->x, zone->y);
215 evas_object_resize(popup, zone->w / 4, zone->h / 3);
216 e_comp_object_util_center(popup);
217 evas_object_show(popup);
218 e_comp_object_util_autoclose(popup, NULL, e_comp_object_util_autoclose_on_escape, NULL);
219 evas_object_event_callback_priority_add(popup, EVAS_CALLBACK_DEL, EVAS_CALLBACK_PRIORITY_BEFORE, _config_close, ci);
220 evas_object_data_set(popup, "entry", ent);
221 e_comp_grab_input(1, 1);
222
223 elm_object_focus_set(ent, 1);
224
225 return rconfig->config_dialog = popup;
226}
227
228static Config_Item *
229_conf_item_get(int *id)
230{
231 Config_Item *ci;
232 Eina_List *l;
233
234 if (*id > 0)
235 {
236 EINA_LIST_FOREACH(rconfig->items, l, ci)
237 if (*id == ci->id) return ci;
238 }
239
240 ci = E_NEW(Config_Item, 1);
241 if (!*id)
242 *id = ci->id = rconfig->items ? eina_list_count(rconfig->items) + 1 : 1;
243 else
244 ci->id = *id;
245
246 if (ci->id < 1) return ci;
247 rconfig->items = eina_list_append(rconfig->items, ci);
248 e_config_save_queue();
249
250 return ci;
251}
252
253static void
254wizard_site_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
255{
256 Wizard_Item *wi = data;
257 wi->site = NULL;
258 evas_object_hide(wi->popup);
259 evas_object_del(wi->popup);
260}
261
262static void
263_wizard_config_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
264{
265 Wizard_Item *wi = data;
266 Eina_List *l;
267 Config_Item *ci;
268
269 EINA_LIST_FOREACH(rconfig->items, l, ci)
270 {
271 if (ci->id == wi->id)
272 {
273 if (ci->cmd) break;
274 wi->id = 0;
275 free(ci);
276 rconfig->items = eina_list_remove_list(rconfig->items, l);
277 break;
278 }
279 }
280
281 if (wi->site)
282 wi->cb(wi->data, wi->id);
283 wizards = eina_list_remove(wizards, wi);
284 if (wi->site)
285 evas_object_event_callback_del_full(wi->site, EVAS_CALLBACK_DEL, wizard_site_del, wi);
286 free(wi);
287}
288
289static Evas_Object *
290runner_wizard(E_Gadget_Wizard_End_Cb cb, void *data, Evas_Object *site)
291{
292 int id = 0;
293 Config_Item *ci;
294 Wizard_Item *wi;
295
296 wi = E_NEW(Wizard_Item, 1);
297 wi->cb = cb;
298 wi->data = data;
299 wi->site = site;
300 evas_object_event_callback_add(wi->site, EVAS_CALLBACK_DEL, wizard_site_del, wi);
301 wizards = eina_list_append(wizards, wi);
302
303 ci = _conf_item_get(&id);
304 wi->id = ci->id;
305 wi->popup = config_runner(ci, NULL);
306 evas_object_event_callback_add(wi->popup, EVAS_CALLBACK_DEL, _wizard_config_end, wi);
307 return wi->popup;
308}
309
310/////////////////////////////////////////
311
312static void
313mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
314{
315 Instance *inst = data;
316 evas_object_focus_set(inst->obj, 1);
317}
318
319static void
320runner_removed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
321{
322 Instance *inst = data;
323 if (inst->box != event_info) return;
324 rconfig->items = eina_list_remove(rconfig->items, inst->ci);
325 eina_stringshare_del(inst->ci->cmd);
326 E_FREE(inst->ci);
327}
328
329static void
330runner_site_gravity(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
331{
332 Instance *inst = data;
333 if (inst->gadget_resource)
334 e_gadget_send_gadget_gravity(inst->gadget_resource, e_gadget_site_gravity_get(obj));
335}
336
337static void
338runner_site_anchor(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
339{
340 Instance *inst = data;
341 if (inst->gadget_resource)
342 e_gadget_send_gadget_anchor(inst->gadget_resource, e_gadget_site_anchor_get(obj));
343}
344
345static void
346runner_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
347{
348 Instance *inst = data;
349 Evas_Object *site = e_gadget_site_get(obj);
350
351 evas_object_smart_callback_del_full(site, "gadget_removed", runner_removed, inst);
352 evas_object_smart_callback_del_full(site, "gadget_site_anchor", runner_site_anchor, inst);
353 evas_object_smart_callback_del_full(site, "gadget_site_gravity", runner_site_gravity, inst);
354 if (inst->ci)
355 {
356 inst->ci->inst = NULL;
357 E_FREE_FUNC(inst->exe, ecore_exe_quit);
358 }
359 else
360 E_FREE_FUNC(inst->exe, ecore_exe_terminate);
361 instances = eina_list_remove(instances, inst);
362 eina_hash_free(inst->allowed_pids);
363 free(inst);
364}
365
366static Evas_Object *
367runner_gadget_configure(Evas_Object *g)
368{
369 Instance *inst = evas_object_data_get(g, "runner");
370 return config_runner(inst->ci, e_comp_object_util_zone_get(g));
371}
372
373static void
374runner_created(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
375{
376 Instance *inst = data;
377 if (inst->box != event_info) return;
378 e_gadget_configure_cb_set(inst->box, runner_gadget_configure);
379 evas_object_smart_callback_del_full(obj, "gadget_created", runner_created, data);
380}
381
382
383static void
384gadget_unbind(struct wl_resource *resource)
385{
386 Instance *inst = wl_resource_get_user_data(resource);
387 inst->gadget_resource = NULL;
388}
389
390static void
391gadget_open_uri(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *uri)
392{
393 Instance *inst = wl_resource_get_user_data(resource);
394
395 /* FIXME: rate limit? */
396 e_util_open(uri, NULL);
397}
398
399static const struct e_gadget_interface _gadget_interface =
400{
401 .open_uri = gadget_open_uri,
402};
403
404static void
405gadget_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
406{
407 struct wl_resource *res;
408 Instance *inst = data;
409 pid_t pid;
410 Evas_Object *site;
411
412 wl_client_get_credentials(client, &pid, NULL, NULL);
413 if (pid != ecore_exe_pid_get(inst->exe))
414 {
415 wl_client_post_no_memory(client);
416 return;
417 }
418
419 res = wl_resource_create(client, &e_gadget_interface, version, id);
420 wl_resource_set_implementation(res, &_gadget_interface, data, gadget_unbind);
421 inst->gadget_resource = res;
422 site = e_gadget_site_get(inst->box);
423 e_gadget_send_gadget_orient(res, e_gadget_site_orient_get(site));
424 e_gadget_send_gadget_gravity(res, e_gadget_site_gravity_get(site));
425 e_gadget_send_gadget_anchor(res, e_gadget_site_anchor_get(site));
426}
427
428static void
429ar_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
430{
431 struct wl_resource *res;
432 Instance *inst = data;
433 int v;
434 const void *ar_interface;
435 pid_t pid;
436
437 wl_client_get_credentials(client, &pid, NULL, NULL);
438 if (pid != ecore_exe_pid_get(inst->exe))
439 {
440 wl_client_post_no_memory(client);
441 return;
442 }
443 ar_interface = e_comp_wl_extension_action_route_interface_get(&v);
444
445 if (!(res = wl_resource_create(client, &action_route_interface, MIN(v, version), id)))
446 {
447 wl_client_post_no_memory(client);
448 return;
449 }
450
451 wl_resource_set_implementation(res, ar_interface, inst->allowed_pids, NULL);
452}
453
454static void
455child_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
456{
457 Instance *inst = data;
458 Evas_Object *ext;
459
460 inst->popup = NULL;
461 ext = evas_object_data_get(obj, "extracted");
462 elm_box_unpack_all(obj);
463 inst->extracted = eina_list_remove(inst->extracted, ext);
464 evas_object_hide(ext);
465}
466
467static void
468child_added(void *data, Evas_Object *obj, void *event_info)
469{
470 Evas_Object *popup, *bx;
471 E_Zone *zone = e_comp_object_util_zone_get(obj);
472 Instance *inst = data;
473
474 if (!efl_wl_surface_extract(event_info)) return;
475 inst->extracted = eina_list_append(inst->extracted, event_info);
476
477 popup = elm_popup_add(e_comp->elm);
478 e_comp_object_util_del_list_append(event_info, popup);
479 E_EXPAND(popup);
480 evas_object_layer_set(popup, E_LAYER_POPUP);
481 elm_popup_allow_events_set(popup, 1);
482 elm_popup_scrollable_set(popup, 1);
483
484 bx = elm_box_add(popup);
485 E_EXPAND(event_info);
486 E_FILL(event_info);
487 elm_box_homogeneous_set(bx, 1);
488 evas_object_show(bx);
489 elm_box_pack_end(bx, event_info);
490 elm_object_content_set(popup, bx);
491
492 inst->popup = popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE);
493 evas_object_layer_set(popup, E_LAYER_POPUP);
494 evas_object_move(popup, zone->x, zone->y);
495 evas_object_resize(popup, zone->w / 4, zone->h / 3);
496 e_comp_object_util_center(popup);
497 evas_object_show(popup);
498 e_comp_canvas_feed_mouse_up(0);
499 e_comp_object_util_autoclose(popup, NULL, e_comp_object_util_autoclose_on_escape, NULL);
500 evas_object_event_callback_add(bx, EVAS_CALLBACK_DEL, child_close, inst);
501 evas_object_data_set(bx, "extracted", event_info);
502 evas_object_focus_set(event_info, 1);
503}
504
505static void
506popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
507{
508 Instance *inst = data;
509 Evas_Object *ext;
510
511 inst->ctxpopup = NULL;
512 ext = evas_object_data_get(obj, "extracted");
513 elm_box_unpack_all(obj);
514 inst->extracted = eina_list_remove(inst->extracted, ext);
515 evas_object_hide(ext);
516}
517
518static void
519popup_dismissed(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
520{
521 evas_object_del(obj);
522}
523
524static void
525popup_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
526{
527 Instance *inst = data;
528 elm_ctxpopup_dismiss(inst->ctxpopup);
529 evas_object_del(elm_object_content_get(inst->ctxpopup));
530}
531
532static void
533popup_hints_update(Evas_Object *obj)
534{
535 double w, h;
536 E_Zone *zone = e_comp_object_util_zone_get(obj);
537
538 evas_object_size_hint_weight_get(obj, &w, &h);
539 w = E_CLAMP(w, 0, 0.5);
540 h = E_CLAMP(h, 0, 0.5);
541
542 if ((w > 0) && (h > 0))
543 {
544 evas_object_size_hint_min_set(obj, w * zone->w, h * zone->h);
545 evas_object_size_hint_max_set(obj, w * zone->w, h * zone->h);
546 }
547 if ((!EINA_DBL_NONZERO(w)) && (!EINA_DBL_NONZERO(h)))
548 {
549 int ww, hh;
550 evas_object_geometry_get(obj, NULL, NULL, &ww, &hh);
551 evas_object_size_hint_min_set(obj, ww, hh);
552 }
553 E_WEIGHT(obj, 0, 0);
554}
555
556static void
557popup_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
558{
559 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, popup_hints, data);
560 popup_hints_update(obj);
561 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, popup_hints, data);
562}
563
564static void
565popup_added(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
566{
567 Instance *inst = data;
568 Evas_Object *bx;
569
570 if (!efl_wl_surface_extract(event_info)) return;
571 inst->extracted = eina_list_append(inst->extracted, event_info);
572
573 inst->ctxpopup = elm_ctxpopup_add(inst->box);
574 elm_object_style_set(inst->ctxpopup, "noblock");
575 evas_object_smart_callback_add(inst->ctxpopup, "dismissed", popup_dismissed, inst);
576 evas_object_event_callback_add(event_info, EVAS_CALLBACK_DEL, popup_hide, inst);
577
578 bx = elm_box_add(inst->ctxpopup);
579 popup_hints_update(event_info);
580 E_FILL(event_info);
581 evas_object_event_callback_add(event_info, EVAS_CALLBACK_CHANGED_SIZE_HINTS, popup_hints, inst);
582 evas_object_show(bx);
583 elm_box_pack_end(bx, event_info);
584 elm_box_recalculate(bx);
585 evas_object_data_set(bx, "extracted", event_info);
586 evas_object_event_callback_add(bx, EVAS_CALLBACK_DEL, popup_del, inst);
587 elm_object_content_set(inst->ctxpopup, bx);
588
589 e_gadget_util_ctxpopup_place(inst->box, inst->ctxpopup, NULL);
590 evas_object_show(inst->ctxpopup);
591 evas_object_focus_set(event_info, 1);
592}
593
594static void
595runner_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
596{
597 Instance *inst = data;
598 int w, h;
599 Evas_Aspect_Control aspect;
600
601 evas_object_size_hint_min_get(obj, &w, &h);
602 evas_object_size_hint_min_set(inst->box, w, h);
603 evas_object_size_hint_max_get(obj, &w, &h);
604 evas_object_size_hint_max_set(inst->box, w, h);
605 evas_object_size_hint_aspect_get(obj, &aspect, &w, &h);
606 evas_object_size_hint_aspect_set(inst->box, aspect, w, h);
607}
608
609static Evas_Object *
610gadget_create(Evas_Object *parent, Config_Item *ci, int *id, E_Gadget_Site_Orient orient)
611{
612 Instance *inst;
613 int ar_version;
614
615 inst = E_NEW(Instance, 1);
616 instances = eina_list_append(instances, inst);
617 inst->ci = ci;
618 if (!inst->ci)
619 inst->ci = _conf_item_get(id);
620 inst->ci->inst = inst;
621 inst->allowed_pids = eina_hash_int32_new(NULL);
622 inst->obj = efl_wl_add(e_comp->evas);
623 E_EXPAND(inst->obj);
624 E_FILL(inst->obj);
625 evas_object_show(inst->obj);
626 efl_wl_aspect_set(inst->obj, 1);
627 efl_wl_minmax_set(inst->obj, 1);
628 efl_wl_global_add(inst->obj, &e_gadget_interface, 1, inst, gadget_bind);
629 evas_object_smart_callback_add(inst->obj, "child_added", child_added, inst);
630 evas_object_smart_callback_add(inst->obj, "popup_added", popup_added, inst);
631 e_comp_wl_extension_action_route_interface_get(&ar_version);
632 efl_wl_global_add(inst->obj, &action_route_interface, ar_version, inst, ar_bind);
633 evas_object_data_set(inst->obj, "runner", inst);
634 evas_object_event_callback_add(inst->obj, EVAS_CALLBACK_MOUSE_DOWN, mouse_down, inst);
635 evas_object_smart_callback_add(parent, "gadget_created", runner_created, inst);
636 evas_object_smart_callback_add(parent, "gadget_removed", runner_removed, inst);
637 evas_object_smart_callback_add(parent, "gadget_site_anchor", runner_site_anchor, inst);
638 evas_object_smart_callback_add(parent, "gadget_site_gravity", runner_site_gravity, inst);
639 runner_run(inst);
640 ecore_exe_data_set(inst->exe, inst);
641 inst->box = elm_box_add(e_comp->elm);
642 e_util_size_debug_set(inst->box, 1);
643 evas_object_event_callback_add(inst->box, EVAS_CALLBACK_DEL, runner_del, inst);
644 evas_object_event_callback_add(inst->obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, runner_hints, inst);
645 elm_box_homogeneous_set(inst->box, 1);
646 elm_box_pack_end(inst->box, inst->obj);
647 return inst->box;
648}
649
650static Evas_Object *
651runner_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
652{
653 Evas_Object *obj;
654 Config_Item *ci = NULL;
655
656 if (orient) return NULL;
657 if (*id > 0) ci = _conf_item_get(id);
658 if ((*id < 0) || ci->inst)
659 {
660 obj = elm_image_add(parent);
661 elm_image_file_set(obj, e_theme_edje_file_get(NULL, "e/icons/modules-launcher"), "e/icons/modules-launcher");
662 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
663 return obj;
664 }
665 return gadget_create(parent, ci, id, orient);
666}
667
668static Eina_Bool
669runner_exe_del(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Exe_Event_Del *ev)
670{
671 Instance *inst = ecore_exe_data_get(ev->exe);
672
673 if ((!inst) || (!instances) || (!eina_list_data_find(instances, inst))) return ECORE_CALLBACK_RENEW;
674 switch (inst->ci->exit_mode)
675 {
676 case EXIT_MODE_RESTART:
677 /* FIXME: probably notify? */
678 if (ev->exit_code == 255) //exec error
679 e_gadget_del(inst->box);
680 else
681 {
682 runner_run(inst);
683 ecore_exe_data_set(inst->exe, inst);
684 }
685 break;
686 case EXIT_MODE_DELETE:
687 e_gadget_del(inst->box);
688 break;
689 }
690 return ECORE_CALLBACK_RENEW;
691}
692
693///////////////////////////////
694
695static Evas_Object *
696sandbox_create(Evas_Object *parent, const char *type, int *id, E_Gadget_Site_Orient orient)
697{
698 Efreet_Desktop *ed = eina_hash_find(sandbox_gadgets, type);
699 Config_Item *ci = NULL;
700
701 if (*id > 0) ci = _conf_item_get(id);
702 if ((*id < 0) || (ci && ci->inst))
703 {
704 if (ed->x)
705 {
706 const char *orients = eina_hash_find(ed->x, "X-Gadget-Orientations");
707
708 if (orients)
709 {
710 const char *ostring[] =
711 {
712 "None",
713 "Horizontal",
714 "Vertical",
715 };
716 char *v, *val = strdup(orients);
717 Eina_Bool found = EINA_FALSE;
718
719 for (v = strtok(val, ";"); v; v = strtok(NULL, ";"))
720 if (!strcmp(v, ostring[orient]))
721 {
722 found = EINA_TRUE;
723 break;
724 }
725 free(val);
726 if (!found) return NULL;
727 }
728 }
729 if (ed->icon)
730 {
731 int w, h;
732 Eina_Bool fail = EINA_FALSE;
733 Evas_Object *obj;
734
735 obj = elm_image_add(parent);
736 if (ed->icon[0] == '/')
737 {
738 if (eina_str_has_extension(ed->icon, ".edj"))
739 fail = !elm_image_file_set(obj, ed->icon, "icon");
740 else
741 fail = !elm_image_file_set(obj, ed->icon, NULL);
742 }
743 else
744 {
745 if (!elm_image_file_set(obj, e_theme_edje_file_get(NULL, ed->icon), ed->icon))
746 fail = !elm_icon_standard_set(obj, ed->icon);
747 }
748 if (!fail)
749 {
750 elm_image_object_size_get(obj, &w, &h);
751 if (w && h)
752 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, w, h);
753 return obj;
754 }
755 evas_object_del(obj);
756 }
757 }
758 if (!ci)
759 {
760 ci = _conf_item_get(id);
761 ci->cmd = eina_stringshare_add(ed->exec);
762 ci->exit_mode = EXIT_MODE_RESTART;
763 }
764 return gadget_create(parent, ci, id, orient);
765}
766
767static char *
768sandbox_name(const char *filename)
769{
770 Efreet_Desktop *ed = eina_hash_find(sandbox_gadgets, filename);
771 const char *name = ed->name ?: ed->generic_name;
772 char buf[1024];
773
774 if (name) return strdup(name);
775 strncpy(buf, ed->orig_path, sizeof(buf) - 1);
776 buf[0] = toupper(buf[0]);
777 return strdup(buf);
778}
779
780///////////////////////////////
781
782static void
783gadget_dir_add(const char *filename)
784{
785 const char *file;
786 char buf[PATH_MAX];
787 Efreet_Desktop *ed;
788
789 file = ecore_file_file_get(filename);
790 snprintf(buf, sizeof(buf), "%s/%s.desktop", filename, file);
791 ed = efreet_desktop_new(buf);
792 EINA_SAFETY_ON_NULL_RETURN(ed);
793 eina_hash_add(sandbox_gadgets, filename, ed);
794 e_gadget_external_type_add("runner_sandbox", filename, sandbox_create, NULL);
795 e_gadget_external_type_name_cb_set("runner_sandbox", filename, sandbox_name);
796}
797
798static Eina_Bool
799monitor_dir_create(void *d EINA_UNUSED, int t EINA_UNUSED, Eio_Monitor_Event *ev)
800{
801 if (!eina_hash_find(sandbox_gadgets, ev->filename))
802 gadget_dir_add(ev->filename);
803 return ECORE_CALLBACK_RENEW;
804}
805
806static Eina_Bool
807monitor_dir_del(void *d EINA_UNUSED, int t EINA_UNUSED, Eio_Monitor_Event *ev)
808{
809 eina_hash_del_by_key(sandbox_gadgets, ev->filename);
810 e_gadget_external_type_del("runner_sandbox", ev->filename);
811 return ECORE_CALLBACK_RENEW;
812}
813
814static Eina_Bool
815monitor_error(void *d EINA_UNUSED, int t EINA_UNUSED, Eio_Monitor_Error *ev)
816{
817 /* panic? */
818 return ECORE_CALLBACK_RENEW;
819}
820
821
822static Eina_Bool
823list_filter_cb(void *d EINA_UNUSED, Eio_File *ls EINA_UNUSED, const Eina_File_Direct_Info *info)
824{
825 struct stat st;
826 char buf[PATH_MAX];
827
828 if (info->type != EINA_FILE_DIR) return EINA_FALSE;
829 if (info->path[info->name_start] == '.') return EINA_FALSE;
830 snprintf(buf, sizeof(buf), "%s/%s.desktop", info->path, info->path + info->name_start);
831 return !stat(info->path, &st);
832}
833
834static void
835list_main_cb(void *d EINA_UNUSED, Eio_File *ls EINA_UNUSED, const Eina_File_Direct_Info *info)
836{
837 gadget_dir_add(info->path);
838}
839
840static void
841list_done_cb(void *d EINA_UNUSED, Eio_File *ls EINA_UNUSED)
842{
843 gadget_lister = NULL;
844}
845
846static void
847list_error_cb(void *d EINA_UNUSED, Eio_File *ls EINA_UNUSED, int error EINA_UNUSED)
848{
849 gadget_lister = NULL;
850}
851
852EINTERN void
853runner_init(void)
854{
855 conf_item_edd = E_CONFIG_DD_NEW("Config_Item", Config_Item);
856#undef T
857#undef D
858#define T Config_Item
859#define D conf_item_edd
860 E_CONFIG_VAL(D, T, id, INT);
861 E_CONFIG_VAL(D, T, exit_mode, INT);
862 E_CONFIG_VAL(D, T, cmd, STR);
863
864 conf_edd = E_CONFIG_DD_NEW("RConfig", RConfig);
865#undef T
866#undef D
867#define T RConfig
868#define D conf_edd
869 E_CONFIG_LIST(D, T, items, conf_item_edd);
870
871 rconfig = e_config_domain_load("module.runner", conf_edd);
872 if (!rconfig) rconfig = E_NEW(RConfig, 1);
873
874 e_gadget_type_add("runner", runner_create, runner_wizard);
875 {
876 gadget_monitor = eio_monitor_add(GADGET_DIR);
877 gadget_lister = eio_file_direct_ls(GADGET_DIR, list_filter_cb, list_main_cb, list_done_cb, list_error_cb, NULL);
878 }
879 E_LIST_HANDLER_APPEND(handlers, ECORE_EXE_EVENT_DEL, runner_exe_del, NULL);
880 E_LIST_HANDLER_APPEND(handlers, EIO_MONITOR_DIRECTORY_CREATED, monitor_dir_create, NULL);
881 E_LIST_HANDLER_APPEND(handlers, EIO_MONITOR_DIRECTORY_DELETED, monitor_dir_del, NULL);
882 E_LIST_HANDLER_APPEND(handlers, EIO_MONITOR_ERROR, monitor_error, NULL);
883
884 sandbox_gadgets = eina_hash_string_superfast_new((Eina_Free_Cb)efreet_desktop_free);
885 {
886 char buf[PATH_MAX];
887
888 snprintf(buf, sizeof(buf), "/proc/%d/ns/pid", getpid());
889 ns_fd = open(buf, O_RDONLY);
890 }
891}
892
893EINTERN void
894runner_shutdown(void)
895{
896 e_gadget_type_del("runner");
897 e_gadget_external_type_del("runner_sandbox", NULL);
898
899 if (rconfig)
900 {
901 Config_Item *ci;
902
903 if (rconfig->config_dialog)
904 {
905 evas_object_hide(rconfig->config_dialog);
906 evas_object_del(rconfig->config_dialog);
907 }
908
909 EINA_LIST_FREE(rconfig->items, ci)
910 {
911 eina_stringshare_del(ci->cmd);
912 free(ci);
913 }
914
915 }
916 E_FREE(rconfig);
917 E_CONFIG_DD_FREE(conf_edd);
918 E_CONFIG_DD_FREE(conf_item_edd);
919 E_FREE_LIST(handlers, ecore_event_handler_del);
920 E_FREE_FUNC(sandbox_gadgets, eina_hash_free);
921 E_FREE_FUNC(gadget_lister, eio_file_cancel);
922 close(ns_fd);
923 ns_fd = -1;
924}
925
926EINTERN void
927runner_save(void)
928{
929 e_config_domain_save("module.runner", conf_edd, rconfig);
930}