support fully sandboxed sub-gadgets in runner gadget

also add demo "start" gadget
This commit is contained in:
Mike Blumenkrantz 2017-08-04 16:24:58 -04:00
parent f1fd2a827a
commit 26c589e745
5 changed files with 725 additions and 18 deletions

77
action_route.xml Normal file
View File

@ -0,0 +1,77 @@
<protocol name="zwp_action_route">
<interface name="action_route" version="1">
<enum name="mode">
<description summary="types of state on the surface">
</description>
<entry name="focus_shared" value="1" summary="Activatable by any surface if its wl_client has focus">
</entry>
<entry name="focus_topmost" value="2" summary="Activatable by topmost surface with focus">
<description summary="Restricts activation to only the top-most client"/>
</entry>
<entry name="exclusive" value="3" summary="Activatable by one surface at any time">
<description summary="Allows activation for exactly one client at all times"/>
</entry>
</enum>
<enum name="modifiers">
<entry name="shift" value="1"></entry>
<entry name="control" value="2"></entry>
<entry name="alt" value="4"></entry>
<entry name="win" value="8"></entry>
<entry name="altgr" value="16"></entry>
</enum>
<request name="bind_action">
<description summary="Request a new grab for a key press">
</description>
<arg name="id" type="new_id" interface="action_route_bind"/>
<arg name="action" type="string"/>
</request>
<request name="grab_key">
<description summary="Request a new grab for a key press">
</description>
<arg name="id" type="new_id" interface="action_route_key_grab"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="key" type="string"/>
<arg name="mode" type="uint"/>
<arg name="modifiers" type="uint"/>
<arg name="action" type="string"/>
<arg name="params" type="string" allow-null="true"/>
</request>
</interface>
<interface name="action_route_bind" version="1">
<enum name="state">
<entry name="Rejected" value="0"></entry>
<entry name="Active" value="1"></entry>
<entry name="Queued" value="2"></entry>
</enum>
<event name="status">
<description summary="Status update on a bind request"></description>
<arg name="state" type="uint"/>
</event>
<request name="activate">
<description summary="Activate a bind"/>
<arg name="params" type="string" allow-null="true"/>
</request>
<request name="destroy" type="destructor">
<description summary="Destroy a requested bind">
</description>
</request>
<event name="end">
<description summary="The bind has completed execution"/>
</event>
</interface>
<interface name="action_route_key_grab" version="1">
<enum name="state">
<entry name="Rejected" value="0"></entry>
<entry name="Active" value="1"></entry>
<entry name="Queued" value="2"></entry>
</enum>
<event name="status">
<description summary="Status update on a grab request"></description>
<arg name="state" type="uint"/>
</event>
<request name="destroy" type="destructor">
<description summary="Destroy a requested grab">
</description>
</request>
</interface>
</protocol>

288
loader/loader.c Normal file
View File

@ -0,0 +1,288 @@
#include "config.h"
#define EFL_BETA_API_SUPPORT
#include <Ecore_Wl2.h>
#include <Elementary.h>
#include <dlfcn.h>
#include "e-gadget-client-protocol.h"
#include "action_route-client-protocol.h"
#include <uuid.h>
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));
}

182
loader/start.c Normal file
View File

@ -0,0 +1,182 @@
#include <Elementary.h>
#include <e_gadget_types.h>
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;
}

View File

@ -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']))

View File

@ -1,5 +1,8 @@
#define HAVE_WAYLAND
#include "e_mod_main.h"
#include <Efl_Wl.h>
#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: