diff --git a/action_route.xml b/action_route.xml new file mode 100644 index 0000000..b8eac15 --- /dev/null +++ b/action_route.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/loader/loader.c b/loader/loader.c new file mode 100644 index 0000000..fe30bcf --- /dev/null +++ b/loader/loader.c @@ -0,0 +1,288 @@ +#include "config.h" +#define EFL_BETA_API_SUPPORT +#include +#include +#include +#include "e-gadget-client-protocol.h" +#include "action_route-client-protocol.h" +#include + +static Ecore_Event_Handler *handler; + +static Eina_Hash *wins; +static Eina_Hash *gadget_globals; +static Eina_Hash *ar_globals; +static Eina_Hash *display_actions; + +typedef struct Gadget_Action +{ + Ecore_Wl2_Display *d; + Eina_Stringshare *action; + char handle[37]; + Eina_List *requestors; + struct action_route_bind *ar_bind; +} Gadget_Action; + +static inline Ecore_Wl2_Display * +win_display_get(Evas_Object *win) +{ + Ecore_Wl2_Window *ww; + ww = elm_win_wl_window_get(win); + return ecore_wl2_window_display_get(ww); +} + +static void +wins_emit(Ecore_Wl2_Display *d, const char *sig, uint32_t val) +{ + Eina_List *l, *ll; + Evas_Object *win; + + l = eina_hash_find(wins, &d); + EINA_LIST_FOREACH(l, ll, win) + evas_object_smart_callback_call(win, sig, (uintptr_t*)(uintptr_t)val); +} + +static void +_gadget_anchor(void *data, struct e_gadget *e_gadget EINA_UNUSED, uint32_t anchor) +{ + wins_emit(data, "gadget_site_anchor", anchor); +} + +static void +_gadget_orient(void *data, struct e_gadget *e_gadget EINA_UNUSED, uint32_t orient) +{ + wins_emit(data, "gadget_site_orient", orient); +} + +static void +_gadget_gravity(void *data, struct e_gadget *e_gadget EINA_UNUSED, uint32_t gravity) +{ + wins_emit(data, "gadget_site_gravity", gravity); +} + +static const struct e_gadget_listener _gadget_listener = +{ + _gadget_anchor, + _gadget_orient, + _gadget_gravity, +}; + +static void +_gadget_global_bind(Ecore_Wl2_Display *d, uint32_t id) +{ + struct e_gadget *gadget_global = wl_registry_bind(ecore_wl2_display_registry_get(d), id, &e_gadget_interface, 1); + e_gadget_add_listener(gadget_global, &_gadget_listener, d); + eina_hash_add(gadget_globals, &d, gadget_global); +} + +static void +_ar_global_bind(Ecore_Wl2_Display *d, uint32_t id) +{ + struct action_route *ar_global = wl_registry_bind(ecore_wl2_display_registry_get(d), id, &action_route_interface, 1); + eina_hash_add(ar_globals, &d, ar_global); +} + +static Eina_Bool +_global_added(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Wl2_Event_Global *ev) +{ + if (eina_streq(ev->interface, "e_gadget")) + _gadget_global_bind(ev->display, ev->id); + else if (eina_streq(ev->interface, "action_route")) + _ar_global_bind(ev->display, ev->id); + return ECORE_CALLBACK_RENEW; +} + +static void +_gadget_init(Ecore_Wl2_Display *d) +{ + Eina_Iterator *it; + Ecore_Wl2_Global *g; + + if (wins) + { + if (eina_hash_find(gadget_globals, &d)) return; + } + else + { + gadget_globals = eina_hash_pointer_new(NULL); + ar_globals = eina_hash_pointer_new(NULL); + } + it = ecore_wl2_display_globals_get(d); + EINA_ITERATOR_FOREACH(it, g) + { + if (eina_streq(g->interface, "e_gadget")) + _gadget_global_bind(d, g->id); + else if (eina_streq(g->interface, "action_route")) + _ar_global_bind(d, g->id); + } + eina_iterator_free(it); + if (!handler) + handler = ecore_event_handler_add(ECORE_WL2_EVENT_GLOBAL_ADDED, (Ecore_Event_Handler_Cb)_global_added, NULL); +} + +static void +_ar_bind_activate(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + const char *params = event_info; + Gadget_Action *ga = data; + + if (params && (!params[0])) params = NULL; + action_route_bind_activate(ga->ar_bind, params); +} + +static void +_ar_bind_del(Gadget_Action *ga) +{ + Evas_Object *r; + eina_stringshare_del(ga->action); + EINA_LIST_FREE(ga->requestors, r) + evas_object_smart_callback_del_full(r, ga->handle, _ar_bind_activate, ga); + free(ga); +} + +static void +_ar_bind_end(void *data, struct action_route_bind *action_route_bind EINA_UNUSED) +{ + Gadget_Action *ga = data; + Eina_List *l; + Evas_Object *r; + + EINA_LIST_FOREACH(ga->requestors, l, r) + evas_object_smart_callback_call(r, "gadget_action_end", ga->handle); +} + +static void +_ar_bind_status(void *data, struct action_route_bind *action_route_bind, uint32_t state) +{ + uuid_t u; + Gadget_Action *ga = data; + Evas_Object *r; + + if (state == ACTION_ROUTE_BIND_STATE_REJECTED) + { + Eina_Hash *h; + Eina_List *l; + h = eina_hash_find(display_actions, &ga->d); + EINA_LIST_FOREACH(ga->requestors, l, r) + { + if (ga->handle[0]) + evas_object_smart_callback_call(r, "gadget_action_deleted", ga->handle); + else + evas_object_smart_callback_call(r, "gadget_action", NULL); + } + eina_hash_del_by_key(h, ga->action); + return; + } + uuid_generate(u); + uuid_unparse_lower(u, ga->handle); + ga->ar_bind = action_route_bind; + r = eina_list_data_get(ga->requestors); + evas_object_smart_callback_add(r, ga->handle, _ar_bind_activate, ga); + evas_object_smart_callback_call(r, "gadget_action", ga->handle); +} + +static const struct action_route_bind_listener _ar_bind_interface = +{ + _ar_bind_status, + _ar_bind_end +}; + +static void +action_request(void *data, Evas_Object *obj, void *event_info) +{ + Gadget_Action *ga; + const char *action = event_info; + Ecore_Wl2_Display *d = data; + void *ar_global; + struct action_route_bind *ar_bind; + Eina_Hash *h; + + if ((!action) || (!action[0])) + { + evas_object_smart_callback_call(obj, "gadget_action", NULL); + return; + } + if (display_actions) + { + h = eina_hash_find(display_actions, &d); + if (h) + { + ga = eina_hash_find(h, action); + if (ga && (!eina_list_data_find(ga->requestors, obj))) + { + ga->requestors = eina_list_append(ga->requestors, obj); + evas_object_smart_callback_add(obj, ga->handle, _ar_bind_activate, ga); + } + evas_object_smart_callback_call(obj, "gadget_action", ga ? ga->handle : NULL); + return; + } + } + ar_global = eina_hash_find(ar_globals, &d); + if (!ar_global) + { + evas_object_smart_callback_call(obj, "gadget_action", NULL); + return; + } + ga = calloc(1, sizeof(Gadget_Action)); + ga->d = d; + ga->requestors = eina_list_append(ga->requestors, obj); + ga->action = eina_stringshare_add(action); + if (!display_actions) + display_actions = eina_hash_string_superfast_new(NULL); + h = eina_hash_find(display_actions, &d); + if (!h) + { + h = eina_hash_pointer_new((Eina_Free_Cb)_ar_bind_del); + eina_hash_add(display_actions, &d, h); + } + + ar_bind = action_route_bind_action(ar_global, action); + action_route_bind_add_listener(ar_bind, &_ar_bind_interface, ga); + wl_display_roundtrip(ecore_wl2_display_get(d)); +} + +static void +win_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Ecore_Wl2_Display *d = win_display_get(obj); + eina_hash_list_remove(wins, &d, obj); +} + +static Evas_Object * +win_add(Evas_Object *win) +{ + Ecore_Wl2_Display *d; + if (!win) return NULL; + d = win_display_get(win); + _gadget_init(d); + if (!wins) + wins = eina_hash_pointer_new(NULL); + eina_hash_list_append(wins, &d, win); + evas_object_smart_callback_add(win, "gadget_action_request", action_request, d); + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, win_del, NULL); + return win; +} + +Evas_Object * +elm_win_util_dialog_add(Evas_Object *parent, const char *name, const char *title) +{ + Evas_Object *(*_elm_win_util_dialog_add)(Evas_Object *, const char *, const char *) = dlsym(RTLD_NEXT, __func__); + + return win_add(_elm_win_util_dialog_add(parent, name, title)); +} + +Evas_Object * +elm_win_util_standard_add(const char *name, const char *title) +{ + Evas_Object *(*_elm_win_util_standard_add)(const char *, const char *) = dlsym(RTLD_NEXT, __func__); + + return win_add(_elm_win_util_standard_add(name, title)); +} + +Evas_Object * +elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type) +{ + Evas_Object *(*_elm_win_add)(Evas_Object *,const char*, Elm_Win_Type) = dlsym(RTLD_NEXT, __func__); + + return win_add(_elm_win_add(parent, name, type)); +} diff --git a/loader/start.c b/loader/start.c new file mode 100644 index 0000000..7db270b --- /dev/null +++ b/loader/start.c @@ -0,0 +1,182 @@ +#include +#include + +static E_Gadget_Site_Orient gorient; +static E_Gadget_Site_Anchor ganchor; +static char *menu_action; + +static void +do_orient(Evas_Object *ly, E_Gadget_Site_Orient orient, E_Gadget_Site_Anchor anchor) +{ + char buf[4096]; + const char *s = "float"; + + if (anchor & E_GADGET_SITE_ANCHOR_LEFT) + { + if (anchor & E_GADGET_SITE_ANCHOR_TOP) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "top_left"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "left_top"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "left_top"; + break; + } + } + else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "bottom_left"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "left_bottom"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "left_bottom"; + break; + } + } + else + s = "left"; + } + else if (anchor & E_GADGET_SITE_ANCHOR_RIGHT) + { + if (anchor & E_GADGET_SITE_ANCHOR_TOP) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "top_right"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "right_top"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "right_top"; + break; + } + } + else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM) + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "bottom_right"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "right_bottom"; + break; + case E_GADGET_SITE_ORIENT_NONE: + s = "right_bottom"; + break; + } + } + else + s = "right"; + } + else if (anchor & E_GADGET_SITE_ANCHOR_TOP) + s = "top"; + else if (anchor & E_GADGET_SITE_ANCHOR_BOTTOM) + s = "bottom"; + else + { + switch (orient) + { + case E_GADGET_SITE_ORIENT_HORIZONTAL: + s = "horizontal"; + break; + case E_GADGET_SITE_ORIENT_VERTICAL: + s = "vertical"; + break; + default: break; + } + } + snprintf(buf, sizeof(buf), "e,state,orientation,%s", s); + elm_layout_signal_emit(ly, buf, "e"); +} + +static void +_menu_cb_post(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + if (eina_streq(event_info, menu_action)) + elm_layout_signal_emit(data, "e,state,unfocused", "e"); +} + +static void +_button_cb_mouse_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Evas_Event_Mouse_Down *ev = event_info; + + if (ev->button != 1) return; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; + if (!menu_action) return; + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + evas_object_smart_callback_call(elm_win_get(obj), menu_action, "main"); + elm_layout_signal_emit(obj, "e,state,focused", "e"); +} + +static void +anchor_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + ganchor = (uintptr_t)event_info; + do_orient(data, gorient, ganchor); +} + +static void +orient_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + gorient = (uintptr_t)event_info; + do_orient(data, gorient, ganchor); +} + +static void +action_deleted(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + if (eina_streq(menu_action, event_info)) + { + free(menu_action); + menu_action = NULL; + } +} + +static void +action_return(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + fprintf(stderr, "AR RETURN: %s\n", (char*)event_info); + menu_action = eina_strdup(event_info); +} + +int +main(int argc, char *argv[]) +{ + Evas_Object *win, *ly; + + elm_init(argc, (char**)argv); + win = elm_win_add(NULL, "start", ELM_WIN_BASIC); + elm_win_autodel_set(win, 1); + elm_win_alpha_set(win, 1); + ly = elm_layout_add(win); + evas_object_size_hint_min_set(win, 100, 100); + evas_object_size_hint_aspect_set(ly, EVAS_ASPECT_CONTROL_BOTH, 1, 1); + elm_layout_file_set(ly, + elm_theme_group_path_find(NULL, "e/gadget/start/main"), "e/gadget/start/main"); + elm_win_resize_object_add(win, ly); + evas_object_show(ly); + evas_object_smart_callback_add(win, "gadget_site_anchor", anchor_change, ly); + evas_object_smart_callback_add(win, "gadget_site_orient", orient_change, ly); + evas_object_smart_callback_add(win, "gadget_action", action_return, NULL); + evas_object_smart_callback_add(win, "gadget_action_end", _menu_cb_post, ly); + evas_object_smart_callback_add(win, "gadget_action_deleted", action_deleted, NULL); + evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_DOWN, _button_cb_mouse_down, NULL); + evas_object_smart_callback_call(win, "gadget_action_request", "menu_show"); + evas_object_show(win); + ecore_main_loop_begin(); + return 0; +} diff --git a/meson.build b/meson.build index 5c18b67..ff130de 100644 --- a/meson.build +++ b/meson.build @@ -135,18 +135,45 @@ if dep_efl_wl.found() == true config_h.set('HAVE_RUNNER', '1') wayland_scanner = find_program('wayland-scanner') - gen_scanner_client = generator(wayland_scanner, - output: '@BASENAME@-client-protocol.h', - arguments: ['client-header', '@INPUT@', '@OUTPUT@']) + gen_scanner_client = generator(wayland_scanner, + output: '@BASENAME@-client-protocol.h', + arguments: ['client-header', '@INPUT@', '@OUTPUT@']) + gen_scanner_server = generator(wayland_scanner, + output: '@BASENAME@-server-protocol.h', + arguments: ['server-header', '@INPUT@', '@OUTPUT@']) gen_scanner_impl = generator(wayland_scanner, - output: '@BASENAME@-protocol.c', - arguments: ['code', '@INPUT@', '@OUTPUT@']) - protos = [ 'e-gadget.xml'] + output: '@BASENAME@-protocol.c', + arguments: ['code', '@INPUT@', '@OUTPUT@']) + protos = [ + 'e-gadget.xml', + 'action_route.xml', + ] + loader_src = ['loader/loader.c'] foreach proto: protos - build_files += gen_scanner_client.process(proto) + loader_src += gen_scanner_client.process(proto) + loader_src += gen_scanner_impl.process(proto) + endforeach + foreach proto: protos + build_files += gen_scanner_server.process(proto) build_files += gen_scanner_impl.process(proto) endforeach + + shared_library('loader', loader_src, + name_prefix: '', + dependencies: [ + dependency('elementary'), + dependency('ecore-wl2'), + dependency('wayland-client'), + cc.find_library('uuid')], + install_dir: join_paths([dir_module_e, module_arch]), + install: true) + + executable('e_gadget_start', + 'loader/start.c', + dependencies: [dependency('elementary'), dependency('enlightenment')], + install_dir: dir_bin, + install: true) endif @@ -167,4 +194,5 @@ shared_module('desksanity', build_files, install_dir: join_paths([dir_module_e, module_arch]), install: true) + meson.add_install_script('meson_modules.sh', join_paths([dir_module_e, module_arch, 'desksanity.so'])) diff --git a/src/runner.c b/src/runner.c index 5a94229..77de9ce 100644 --- a/src/runner.c +++ b/src/runner.c @@ -1,5 +1,8 @@ +#define HAVE_WAYLAND #include "e_mod_main.h" #include +#include "e-gadget-server-protocol.h" +#include "action_route-server-protocol.h" typedef enum { @@ -22,6 +25,8 @@ typedef struct Instance Evas_Object *obj; Ecore_Exe *exe; Config_Item *ci; + Eina_Hash *allowed_pids; + void *gadget_resource; } Instance; typedef struct RConfig @@ -35,16 +40,44 @@ static E_Config_DD *conf_item_edd = NULL; static RConfig *rconfig; static Eina_List *instances; +static Eina_List *wizards; static Ecore_Event_Handler *exit_handler; typedef struct Wizard_Item { + Evas_Object *site; + Evas_Object *popup; E_Gadget_Wizard_End_Cb cb; void *data; int id; } Wizard_Item; +static void +runner_run(Instance *inst) +{ + char *preload = eina_strdup(getenv("LD_PRELOAD")); + char buf[PATH_MAX]; + char *file = ecore_file_dir_get(mod->module->file); + int pid; + + snprintf(buf, sizeof(buf), "%s/loader.so", file); + e_util_env_set("LD_PRELOAD", buf); + + snprintf(buf, sizeof(buf), "%d", inst->ci->id); + e_util_env_set("E_GADGET_ID", buf); + + inst->exe = efl_wl_run(inst->obj, inst->ci->cmd); + + e_util_env_set("E_GADGET_ID", NULL); + e_util_env_set("LD_PRELOAD", preload); + free(file); + free(preload); + eina_hash_free_buckets(inst->allowed_pids); + pid = ecore_exe_pid_get(inst->exe); + eina_hash_add(inst->allowed_pids, &pid, (void*)1); +} + static void _config_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { @@ -66,7 +99,7 @@ _config_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_inf if (!ci->cmd_changed) return; ci->cmd_changed = 0; if (inst->exe) ecore_exe_quit(inst->exe); - inst->exe = efl_wl_run(inst->obj, inst->ci->cmd); + runner_run(inst); } static void @@ -114,7 +147,7 @@ _config_cmd_activate(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) e_config_save_queue(); if (!inst) return; if (inst->exe) ecore_exe_quit(inst->exe); - inst->exe = efl_wl_run(inst->obj, inst->ci->cmd); + runner_run(inst); } EINTERN Evas_Object * @@ -228,7 +261,16 @@ _conf_item_get(int *id) } static void -_wizard_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +wizard_site_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Wizard_Item *wi = data; + wi->site = NULL; + evas_object_hide(wi->popup); + evas_object_del(wi->popup); +} + +static void +_wizard_config_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Wizard_Item *wi = data; Eina_List *l; @@ -246,27 +288,33 @@ _wizard_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void } } - wi->cb(wi->data, wi->id); + if (wi->site) + wi->cb(wi->data, wi->id); + wizards = eina_list_remove(wizards, wi); + if (wi->site) + evas_object_event_callback_del_full(wi->site, EVAS_CALLBACK_DEL, wizard_site_del, wi); free(wi); } static Evas_Object * -runner_wizard(E_Gadget_Wizard_End_Cb cb, void *data) +runner_wizard(E_Gadget_Wizard_End_Cb cb, void *data, Evas_Object *site) { int id = 0; Config_Item *ci; Wizard_Item *wi; - Evas_Object *obj; wi = E_NEW(Wizard_Item, 1); wi->cb = cb; wi->data = data; + wi->site = site; + evas_object_event_callback_add(wi->site, EVAS_CALLBACK_DEL, wizard_site_del, wi); + wizards = eina_list_append(wizards, wi); ci = _conf_item_get(&id); wi->id = ci->id; - obj = config_runner(ci, NULL); - evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _wizard_end, wi); - return obj; + wi->popup = config_runner(ci, NULL); + evas_object_event_callback_add(wi->popup, EVAS_CALLBACK_DEL, _wizard_config_end, wi); + return wi->popup; } ///////////////////////////////////////// @@ -288,15 +336,34 @@ runner_removed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) E_FREE(inst->ci); } +static void +runner_site_gravity(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + if (inst->gadget_resource) + e_gadget_send_gadget_gravity(inst->gadget_resource, e_gadget_site_gravity_get(obj)); +} + +static void +runner_site_anchor(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + if (inst->gadget_resource) + e_gadget_send_gadget_anchor(inst->gadget_resource, e_gadget_site_anchor_get(obj)); +} + static void runner_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { Instance *inst = data; evas_object_smart_callback_del_full(e_gadget_site_get(obj), "gadget_removed", runner_removed, inst); + evas_object_smart_callback_del_full(e_gadget_site_get(obj), "gadget_site_anchor", runner_site_anchor, inst); + evas_object_smart_callback_del_full(e_gadget_site_get(obj), "gadget_site_gravity", runner_site_gravity, inst); E_FREE_FUNC(inst->exe, ecore_exe_quit); if (inst->ci) inst->ci->inst = NULL; instances = eina_list_remove(instances, inst); + eina_hash_free(inst->allowed_pids); free(inst); } @@ -316,12 +383,71 @@ runner_created(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) evas_object_smart_callback_del_full(obj, "gadget_created", runner_created, data); } + +static void +gadget_unbind(struct wl_resource *resource) +{ + Instance *inst = wl_resource_get_user_data(resource); + inst->gadget_resource = NULL; +} + +static void +gadget_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + struct wl_resource *res; + Instance *inst = data; + pid_t pid; + Evas_Object *site; + + wl_client_get_credentials(client, &pid, NULL, NULL); + if (pid != ecore_exe_pid_get(inst->exe)) + { + wl_client_post_no_memory(client); + return; + } + + res = wl_resource_create(client, &e_gadget_interface, version, id); + wl_resource_set_implementation(res, NULL, data, gadget_unbind); + inst->gadget_resource = res; + site = e_gadget_site_get(inst->obj); + e_gadget_send_gadget_orient(res, e_gadget_site_orient_get(site)); + e_gadget_send_gadget_gravity(res, e_gadget_site_gravity_get(site)); + e_gadget_send_gadget_anchor(res, e_gadget_site_anchor_get(site)); +} + +static void +ar_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + struct wl_resource *res; + Instance *inst = data; + int v; + const void *ar_interface; + pid_t pid; + + wl_client_get_credentials(client, &pid, NULL, NULL); + if (pid != ecore_exe_pid_get(inst->exe)) + { + wl_client_post_no_memory(client); + return; + } + ar_interface = e_comp_wl_extension_action_route_interface_get(&v); + + if (!(res = wl_resource_create(client, &action_route_interface, MIN(v, version), id))) + { + wl_client_post_no_memory(client); + return; + } + + wl_resource_set_implementation(res, ar_interface, inst->allowed_pids, NULL); +} + static Evas_Object * runner_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient) { Evas_Object *obj; Instance *inst; Config_Item *ci = NULL; + int ar_version; if (orient) return NULL; if (*id > 0) ci = _conf_item_get(id); @@ -338,15 +464,21 @@ runner_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient) if (!inst->ci) inst->ci = _conf_item_get(id); inst->ci->inst = inst; + inst->allowed_pids = eina_hash_int32_new(NULL); inst->obj = efl_wl_add(e_comp->evas); efl_wl_aspect_set(inst->obj, 1); efl_wl_minmax_set(inst->obj, 1); + efl_wl_global_add(inst->obj, &e_gadget_interface, 1, inst, gadget_bind); + e_comp_wl_extension_action_route_interface_get(&ar_version); + efl_wl_global_add(inst->obj, &action_route_interface, ar_version, inst, ar_bind); evas_object_data_set(inst->obj, "runner", inst); evas_object_event_callback_add(inst->obj, EVAS_CALLBACK_MOUSE_DOWN, mouse_down, inst); evas_object_smart_callback_add(parent, "gadget_created", runner_created, inst); evas_object_smart_callback_add(parent, "gadget_removed", runner_removed, inst); + evas_object_smart_callback_add(parent, "gadget_site_anchor", runner_site_anchor, inst); + evas_object_smart_callback_add(parent, "gadget_site_gravity", runner_site_gravity, inst); evas_object_pass_events_set(inst->obj, !inst->ci->allow_events); - inst->exe = efl_wl_run(inst->obj, inst->ci->cmd); + runner_run(inst); ecore_exe_data_set(inst->exe, inst); evas_object_event_callback_add(inst->obj, EVAS_CALLBACK_DEL, runner_del, inst); return inst->obj; @@ -361,7 +493,7 @@ runner_exe_del(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Exe_Event_Del *ev) switch (inst->ci->exit_mode) { case EXIT_MODE_RESTART: - inst->exe = efl_wl_run(inst->obj, inst->ci->cmd); + runner_run(inst); ecore_exe_data_set(inst->exe, inst); break; case EXIT_MODE_DELETE: