You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
288 lines
7.9 KiB
288 lines
7.9 KiB
#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)); |
|
}
|
|
|