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 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+