diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h index 464dc9755..10071aafd 100644 --- a/src/bin/e_comp_wl.h +++ b/src/bin/e_comp_wl.h @@ -425,6 +425,9 @@ E_API void e_comp_wl_extension_relative_motion_event(uint64_t time_usec, double E_API void e_comp_wl_extension_pointer_constraints_commit(E_Client *ec); E_API Eina_Bool e_comp_wl_extension_pointer_constraints_update(E_Client *ec, int x, int y); E_API void e_comp_wl_extension_pointer_unconstrain(E_Client *ec); +E_API void e_comp_wl_extension_action_route_pid_allowed_set(uint32_t pid, Eina_Bool allow); + + E_API void e_policy_wl_aux_message_send(E_Client *ec, diff --git a/src/bin/e_comp_wl_extensions.c b/src/bin/e_comp_wl_extensions.c index 74133ce3e..8fa3cb53e 100644 --- a/src/bin/e_comp_wl_extensions.c +++ b/src/bin/e_comp_wl_extensions.c @@ -574,9 +574,9 @@ _e_comp_wl_zwp_pointer_constraints_v1_confine_pointer(struct wl_client *client, extern E_Action *(*e_binding_key_list_cb)(E_Binding_Context, Ecore_Event_Key*, E_Binding_Modifier, E_Binding_Key **); static Eina_Hash *key_bindings; -typedef struct Action_Route +typedef struct Action_Route_Key { - union + struct { E_Binding_Key key; } binding; @@ -584,13 +584,23 @@ typedef struct Action_Route uint32_t state; struct wl_resource *res; struct wl_resource *surface; -} Action_Route; +} Action_Route_Key; + +typedef struct Action_Route_Bind +{ + E_Action *action; + uint32_t state; + struct wl_resource *res; + Evas_Object *end_obj; +} Action_Route_Bind; + +static Eina_Hash *allowed_pids; static E_Action * _action_route_key_list_cb(E_Binding_Context ctxt, Ecore_Event_Key *ev, E_Binding_Modifier mod, E_Binding_Key **bind_ret) { Eina_List *l, *ll; - Action_Route *ar; + Action_Route_Key *ar; E_Binding_Key *binding; if (bind_ret) *bind_ret = NULL; @@ -651,9 +661,9 @@ _action_route_key_list_cb(E_Binding_Context ctxt, Ecore_Event_Key *ev, E_Binding } static Eina_Bool -_action_route_is_allowed(const char *action, const char *params) +_action_route_key_is_allowed(const char *action EINA_UNUSED, const char *params EINA_UNUSED) { - /* FIXME: allow 1-2 bindings maybe */ + /* FIXME: no users of this yet... */ return EINA_FALSE; } @@ -669,10 +679,10 @@ _action_route_can_override(const E_Binding_Key *binding) } static void -_e_comp_wl_action_route_grab_del(struct wl_resource *resource) +_e_comp_wl_action_route_key_grab_del(struct wl_resource *resource) { Eina_List *l, *ll; - Action_Route *ar; + Action_Route_Key *ar; Eina_Bool update; /* FIXME: delete active actions? */ @@ -697,14 +707,14 @@ _e_comp_wl_action_route_grab_del(struct wl_resource *resource) } static void -_e_comp_wl_action_route_grab_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource) +_e_comp_wl_action_route_key_grab_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource) { - _e_comp_wl_action_route_grab_del(resource); + wl_resource_destroy(resource); } -static const struct action_route_key_grab_interface _e_action_route_grab_interface = +static const struct action_route_key_grab_interface _e_action_route_key_grab_interface = { - _e_comp_wl_action_route_grab_destroy, + _e_comp_wl_action_route_key_grab_destroy, }; static void @@ -720,7 +730,7 @@ _e_comp_wl_action_route_grab_key(struct wl_client *client, struct wl_resource *r struct wl_resource *rt; E_Binding_Key *binding; Eina_List *l, *ll; - Action_Route *ar, *lar; + Action_Route_Key *ar, *lar; E_Binding_Context ctxt = E_BINDING_CONTEXT_WINDOW; rt = wl_resource_create(client, &action_route_key_grab_interface, 1, id); @@ -730,16 +740,16 @@ _e_comp_wl_action_route_grab_key(struct wl_client *client, struct wl_resource *r wl_client_post_no_memory(client); return; } - wl_resource_set_implementation(rt, &_e_action_route_grab_interface, NULL, - _e_comp_wl_action_route_grab_del); + wl_resource_set_implementation(rt, &_e_action_route_key_grab_interface, NULL, + _e_comp_wl_action_route_key_grab_del); binding = e_bindings_key_find(key, modifiers, 0); - if ((!_action_route_is_allowed(action, params)) || (!_action_route_can_override(binding))) + if ((!_action_route_key_is_allowed(action, params)) || (!_action_route_can_override(binding))) { action_route_key_grab_send_status(rt, ACTION_ROUTE_KEY_GRAB_STATE_REJECTED); wl_resource_destroy(rt); return; } - ar = E_NEW(Action_Route, 1); + ar = E_NEW(Action_Route_Key, 1); ar->mode = mode; ar->res = rt; ar->surface = surface; @@ -782,6 +792,126 @@ _e_comp_wl_action_route_grab_key(struct wl_client *client, struct wl_resource *r action_route_key_grab_send_status(ar->res, ar->state); } +static void +_e_comp_wl_action_route_bind_menu_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Action_Route_Bind *ar = data; + evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, + _e_comp_wl_action_route_bind_menu_end, ar); + action_route_bind_send_end(ar->res); +} + +static void +_e_comp_wl_action_route_bind_action_del(struct wl_resource *resource) +{ + Action_Route_Bind *ar = wl_resource_get_user_data(resource); + + if (strstr(ar->action->name, "menu")) + { + E_Menu *m = e_menu_active_get(); + if (!m) return; + evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_HIDE, + _e_comp_wl_action_route_bind_menu_end, ar); + } + + e_object_unref(E_OBJECT(ar->action)); + free(ar); +} + +static void +_e_comp_wl_action_route_bind_action_activate(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *params) +{ + Action_Route_Bind *ar = wl_resource_get_user_data(resource); + if (!ar) return; + ar->action->func.go(NULL, params); + if (strstr(ar->action->name, "menu")) + { + E_Menu *m = e_menu_active_get(); + if (!m) return; + evas_object_event_callback_add(m->comp_object, EVAS_CALLBACK_HIDE, + _e_comp_wl_action_route_bind_menu_end, ar); + } +} + +static void +_e_comp_wl_action_route_bind_action_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct action_route_bind_interface _e_action_route_bind_action_interface = +{ + _e_comp_wl_action_route_bind_action_activate, + _e_comp_wl_action_route_bind_action_destroy, +}; + +static E_Action * +_action_route_bind_is_allowed(int32_t pid, const char *action) +{ + const char **b, *blacklist[] = + { + "exit_now", + "halt_now", + "suspend_now", + "hibernate_now", + NULL, + }; + if (!allowed_pids) return NULL; + if (!eina_hash_find(allowed_pids, &pid)) return NULL; + if ((!action[0])) return NULL; + if (!strncmp(action, "module_", sizeof("module_") - 1)) return NULL; + for (b = blacklist; *b; b++) + if (eina_streq(*b, action)) return NULL; + return e_action_find(action); +} + +static void +_e_comp_wl_action_route_bind_action(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, + uint32_t id, + const char *action) +{ + struct wl_resource *rt; + Action_Route_Bind *ar; + E_Action *act; + int32_t pid; + + rt = wl_resource_create(client, &action_route_bind_interface, 1, id); + if (!rt) + { + ERR("Could not create action route"); + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(rt, &_e_action_route_bind_action_interface, NULL, + _e_comp_wl_action_route_bind_action_del); + wl_client_get_credentials(client, &pid, NULL, NULL); + act = _action_route_bind_is_allowed(pid, action); + if (!act) + { + action_route_bind_send_status(rt, ACTION_ROUTE_BIND_STATE_REJECTED); + wl_resource_destroy(rt); + return; + } + ar = E_NEW(Action_Route_Bind, 1); + ar->res = rt; + ar->action = act; + e_object_ref(E_OBJECT(act)); + ar->state = ACTION_ROUTE_BIND_STATE_ACTIVE; + wl_resource_set_user_data(rt, ar); + action_route_bind_send_status(ar->res, ar->state); +} + +E_API void +e_comp_wl_extension_action_route_pid_allowed_set(uint32_t pid, Eina_Bool allow) +{ + if (!allowed_pids) + allowed_pids = eina_hash_int32_new(NULL); + if (allow) + eina_hash_add(allowed_pids, &pid, (void*)1); + else + eina_hash_del_by_key(allowed_pids, &pid); +} + ///////////////////////////////////////////////////////// static const struct zwp_e_session_recovery_interface _e_session_recovery_interface = @@ -823,6 +953,7 @@ static const struct zwp_pointer_constraints_v1_interface _e_zwp_pointer_constrai static const struct action_route_interface _e_action_route_interface = { + _e_comp_wl_action_route_bind_action, _e_comp_wl_action_route_grab_key, }; diff --git a/src/protocol/action_route.xml b/src/protocol/action_route.xml index 904f983a9..b8eac15bb 100644 --- a/src/protocol/action_route.xml +++ b/src/protocol/action_route.xml @@ -19,6 +19,12 @@ + + + + + + @@ -28,9 +34,31 @@ - + + + + + + + + + + + + + + + + + + + + + + +