#define EXECUTIVE_MODE_ENABLED
#include "e.h"
#include <sys/mman.h>
+#include <pixman.h>
+
+typedef struct _E_Comp_Wl_Pointer_Constraint E_Comp_Wl_Pointer_Constraint;
+
+typedef enum _E_Comp_Wl_Pointer_Constraint_Type
+{
+ E_COMP_WL_POINTER_CONSTRAINT_TYPE_NONE = 0,
+ E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK = 1,
+ E_COMP_WL_POINTER_CONSTRAINT_TYPE_CONFINE = 2,
+} E_Comp_Wl_Pointer_Constraint_Type;
+
+struct _E_Comp_Wl_Pointer_Constraint
+{
+ struct wl_list link;
+
+ E_Client *ec;
+ struct wl_resource *surface;
+ struct wl_resource *resource;
+ struct wl_resource *pointer;
+ Eina_Bool active;
+
+ E_Comp_Wl_Pointer_Constraint_Type type;
+ int lifetime;
+
+ pixman_region32_t region;
+ pixman_region32_t region_pending;
+ Eina_Bool is_region_pending;
+ Eina_Bool has_region_set;
+
+ wl_fixed_t hint_x;
+ wl_fixed_t hint_y;
+ wl_fixed_t hint_x_pending;
+ wl_fixed_t hint_y_pending;
+ Eina_Bool is_hint_pending;
+ Eina_Bool has_hint_set;
+
+ struct wl_listener pointer_destroy_listener;
+ struct wl_listener surface_unmap_listener;
+ struct wl_listener surface_commit_listener;
+ struct wl_listener surface_focus_listener;
+};
E_API int E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE = -1;
static Eina_Bool dont_set_e_input_keymap = EINA_FALSE;
static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
static Eina_Bool use_cache_keymap = EINA_FALSE;
+static E_Comp_Wl_Hook *_surface_commit_hook = NULL;
+
/* default XKB values from enviroment variables */
static char *_env_e_default_xkb_rules = NULL;
static char *_env_e_default_xkb_model = NULL;
{
e_comp_wl->ptr.resources =
eina_list_remove(e_comp_wl->ptr.resources, resource);
+
+ wl_signal_emit(&e_comp_wl->ptr_constraints.pointer_destroy_signal, resource);
}
static void
/* FIXME: must consider destroying relative pointer together
when the wl_pointer is destroyed */
(void) pointer_resource;
- wl_resource_set_implementation(res, &_e_relative_pointer_interface, NULL, _e_comp_wl_cb_unbind_relative_pointer);
+ wl_resource_set_implementation(res, &_e_relative_pointer_interface,
+ NULL, _e_comp_wl_cb_unbind_relative_pointer);
}
static const struct zwp_relative_pointer_manager_v1_interface _e_relative_pointer_manager_interface = {
_e_comp_wl_cb_relative_pointer_manager_get_relative_pointer,
};
+static void
+_e_comp_wl_cb_unbind_relative_pointer_manager(struct wl_resource *resource)
+{
+ ERR("Unbind relative_pointer_manager: (resource: %u) (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
+
+ e_comp_wl->relative_ptr.manager_resources =
+ eina_list_remove(e_comp_wl->relative_ptr.manager_resources, resource);
+}
+
static void
_e_comp_wl_input_cb_bind_relative_pointer_manager(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
{
DBG("Bind relative pointer: (resource:%u) (client: %p)", wl_resource_get_id(resource), client);
- wl_resource_set_implementation(resource, &_e_relative_pointer_manager_interface, NULL, NULL);
- //FIXME: consider to add unbind fucntion
+ e_comp_wl->relative_ptr.manager_resources =
+ eina_list_append(e_comp_wl->relative_ptr.manager_resources, resource);
+ wl_resource_set_implementation(resource, &_e_relative_pointer_manager_interface,
+ NULL, _e_comp_wl_cb_unbind_relative_pointer_manager);
+}
+
+static void
+_e_comp_wl_convert_eina_tiler_to_pixman_region32(const Eina_Tiler *tiler,
+ pixman_region32_t *region)
+{
+ Eina_Iterator *itr;
+ Eina_Rectangle *rect;
+
+ itr = eina_tiler_iterator_new(tiler);
+ EINA_ITERATOR_FOREACH(itr, rect)
+ {
+ pixman_region32_union_rect(region, region, rect->x, rect->y, rect->w, rect->h);
+ }
+ eina_iterator_free(itr);
+}
+
+static void
+_e_comp_wl_pointer_constraint_notify_deactivated(E_Comp_Wl_Pointer_Constraint *constraint)
+{
+ struct wl_resource *resource = constraint->resource;
+ E_Comp_Wl_Pointer_Constraint_Type type = constraint->type;
+
+ if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK == type)
+ zwp_locked_pointer_v1_send_unlocked(resource);
+ else if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_CONFINE == type)
+ zwp_confined_pointer_v1_send_unconfined(resource);
+ else
+ abort();
+
+ ERR("pointer constraint deactivated (type=%d, ec=%p)", constraint->type, constraint->ec);
+}
+
+static void
+_e_comp_wl_pointer_constraint_deactivate(E_Comp_Wl_Pointer_Constraint *constraint)
+{
+ constraint->active = EINA_FALSE;
+ e_comp_wl->ptr_constraints.activated = EINA_FALSE;
+ e_comp_wl->ptr_constraints.ec = NULL;
+ _e_comp_wl_pointer_constraint_notify_deactivated(constraint);
+ wl_list_remove(&constraint->surface_unmap_listener.link);
+ wl_list_init(&constraint->surface_unmap_listener.link);
+}
+
+static void
+_e_comp_wl_pointer_constraint_destroy(E_Comp_Wl_Pointer_Constraint *constraint)
+{
+ if (constraint->active)
+ _e_comp_wl_pointer_constraint_deactivate(constraint);
+
+ wl_list_remove(&constraint->pointer_destroy_listener.link);
+ wl_list_remove(&constraint->surface_focus_listener.link);
+ wl_list_remove(&constraint->surface_unmap_listener.link);
+ wl_list_remove(&constraint->surface_commit_listener.link);
+
+ wl_resource_set_user_data(constraint->resource, NULL);
+ pixman_region32_fini(&constraint->region);
+ wl_list_remove(&constraint->link);
+
+ free(constraint);
+}
+
+static Eina_Bool
+_e_comp_wl_is_position_inside_constraint_region(E_Comp_Wl_Pointer_Constraint *constraint,
+ wl_fixed_t fx,
+ wl_fixed_t fy)
+{
+ //return EINA_TRUE here before using region provided from client
+ return EINA_TRUE;
+
+ pixman_region32_t *region = &constraint->region;
+ pixman_region32_t cregion;
+ pixman_region32_t input_region;
+
+ pixman_region32_init(&cregion);
+ pixman_region32_init(&input_region);
+
+ //FIXME: get input_region from ec's input region (Eina_Tiler *tiler)
+ E_Client *ec = constraint->ec;
+ pixman_region32_init_rect(&input_region, 0, 0, ec->w, ec->h);
+ pixman_region32_intersect(&cregion, &input_region, region);
+
+ Eina_Bool inside = pixman_region32_contains_point(&cregion,
+ wl_fixed_to_int(fx),
+ wl_fixed_to_int(fy),
+ NULL);
+
+ pixman_region32_fini(&cregion);
+ pixman_region32_fini(&input_region);
+ return inside;
+}
+
+static void
+_e_comp_wl_pointer_constraint_notify_activated(E_Comp_Wl_Pointer_Constraint *constraint)
+{
+ struct wl_resource *resource = constraint->resource;
+ E_Comp_Wl_Pointer_Constraint_Type type = constraint->type;
+
+ if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK == type)
+ zwp_locked_pointer_v1_send_locked(resource);
+ else if (E_COMP_WL_POINTER_CONSTRAINT_TYPE_CONFINE == type)
+ zwp_confined_pointer_v1_send_confined(resource);
+ else
+ abort();
+
+ ERR("pointer constraint activated (type=%d, ec=%p)", constraint->type, constraint->ec);
+}
+
+static void
+_e_comp_wl_pointer_constraint_enable(E_Comp_Wl_Pointer_Constraint *constraint)
+{
+ if (constraint->active)
+ {
+ ERR("ERROR! Pointer constraint has been activated already !");
+ return;
+ }
+
+ constraint->active = EINA_TRUE;
+ E_Client *ec = constraint->ec;
+ e_comp_wl->ptr_constraints.activated = EINA_TRUE;
+ e_comp_wl->ptr_constraints.ec = ec;
+ _e_comp_wl_pointer_constraint_notify_activated(constraint);
+ wl_signal_add(&e_comp_wl->ptr_constraints.surface_unmap_signal,
+ &constraint->surface_unmap_listener);
+}
+
+static void
+_e_comp_wl_pointer_constraints_check_enable(E_Comp_Wl_Pointer_Constraint *constraint)
+{
+ if (!constraint || !constraint->ec)
+ {
+ ERR("Invalid constraint or ec of it.");
+ return;
+ }
+
+ E_Client *ec = constraint->ec;
+
+ if ((!e_comp_wl->ptr.ec) || (e_comp_wl->ptr.ec != ec)
+ || (!ec->pointer_enter_sent))
+ return;
+
+ if (!_e_comp_wl_is_position_inside_constraint_region(constraint,
+ e_comp_wl->ptr.x,
+ e_comp_wl->ptr.y))
+ return;
+
+ _e_comp_wl_pointer_constraint_enable(constraint);
+}
+
+static void
+_e_comp_wl_pointer_constraint_disable(E_Comp_Wl_Pointer_Constraint *constraint)
+{
+ int lifetime = constraint->lifetime;
+
+ if (lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT)
+ _e_comp_wl_pointer_constraint_destroy(constraint);
+ else if (lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT)
+ _e_comp_wl_pointer_constraint_deactivate(constraint);
+ else
+ abort();
+}
+
+static void
+_e_comp_wl_pointer_constraints_pointer_destroyed(struct wl_listener *listener,
+ void *data)
+{
+ struct wl_resource *pointer_resource = (struct wl_resource *)data;
+ E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
+ E_Comp_Wl_Pointer_Constraint,
+ pointer_destroy_listener);
+
+ ERR("[pointer destroyed -> pointer constraints will be destroyed]");
+
+ if (pointer_resource == constraint->pointer)
+ _e_comp_wl_pointer_constraint_destroy(constraint);
+}
+
+static void
+_e_comp_wl_pointer_constraints_surface_focused(struct wl_listener *listener,
+ void *data)
+{
+ E_Client *ec = (E_Client *)data;
+ E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
+ E_Comp_Wl_Pointer_Constraint,
+ surface_focus_listener);
+
+ Eina_Bool found = EINA_FALSE;
+ E_Comp_Wl_Pointer_Constraint *tmp_constraint;
+ wl_list_for_each(tmp_constraint, &ec->comp_data->pointer_constraints, link)
+ {
+ if (tmp_constraint == constraint)
+ {
+ found = EINA_TRUE;
+ break;
+ }
+ }
+
+ ERR("[surface focused -> pointer constraints will be checked, enabled or disabled]");
+
+ if (found && !constraint->active)
+ _e_comp_wl_pointer_constraints_check_enable(constraint);
+ else if (!found && constraint->active)
+ _e_comp_wl_pointer_constraint_disable(constraint);
+}
+
+static void
+_e_comp_wl_pointer_constraints_surface_committed(struct wl_listener *listener,
+ void *data)
+{
+ E_Client *ec = (E_Client *)data;
+ E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
+ E_Comp_Wl_Pointer_Constraint,
+ surface_commit_listener);
+
+ if (ec != constraint->ec)
+ return;
+
+ if (constraint->is_hint_pending)
+ {
+ constraint->is_hint_pending = EINA_FALSE;
+ constraint->hint_x = constraint->hint_x_pending;
+ constraint->hint_y = constraint->hint_y_pending;
+ }
+
+ if (constraint->is_region_pending)
+ {
+ constraint->is_region_pending = EINA_FALSE;
+ pixman_region32_copy(&constraint->region,
+ &constraint->region_pending);
+ pixman_region32_fini(&constraint->region_pending);
+ pixman_region32_init(&constraint->region_pending);
+ }
+
+ ERR("[surface committed -> pointer constraints' region/hint will be updated if required]");
+
+ //CHECKME: check if the updated region can take effect on the given constraint
+}
+
+static void
+_e_comp_wl_pointer_constraints_surface_unmapped(struct wl_listener *listener,
+ void *data)
+{
+ E_Client *ec = (E_Client *)data;
+ E_Comp_Wl_Pointer_Constraint *constraint = container_of(listener,
+ E_Comp_Wl_Pointer_Constraint,
+ surface_unmap_listener);
+
+ ERR("[surface unmapped -> pointer constraints will be disabled if required]");
+
+ if (ec == constraint->ec)
+ _e_comp_wl_pointer_constraint_disable(constraint);
+}
+
+static E_Comp_Wl_Pointer_Constraint *
+_e_comp_wl_pointer_constraint_create(E_Client *ec,
+ struct wl_resource *resource,
+ struct wl_resource *pointer,
+ struct wl_resource *region,
+ enum zwp_pointer_constraints_v1_lifetime lifetime,
+ E_Comp_Wl_Pointer_Constraint_Type type)
+{
+ E_Comp_Wl_Pointer_Constraint *constraint;
+
+ constraint = E_NEW(E_Comp_Wl_Pointer_Constraint, 1);
+
+ if (!constraint)
+ {
+ ERR("Could not allocate memory for pointer constrant: %m");
+ return NULL;
+ }
+
+ constraint->active = EINA_FALSE;
+ constraint->ec = ec;
+ constraint->lifetime = lifetime;
+ constraint->type = type;
+ constraint->pointer = pointer;
+ constraint->resource = resource;
+ constraint->surface = ec->comp_data->surface;
+ wl_list_init(&constraint->link);
+ wl_list_insert(&ec->comp_data->pointer_constraints, &constraint->link);
+ pixman_region32_init(&constraint->region);
+ pixman_region32_init(&constraint->region_pending);
+
+ if (region)
+ {
+ Eina_Tiler *tiler = wl_resource_get_user_data(region);
+ pixman_region32_t given_region;
+
+ if (tiler)
+ {
+ pixman_region32_init(&given_region);
+ _e_comp_wl_convert_eina_tiler_to_pixman_region32(tiler, &given_region);
+ pixman_region32_copy(&constraint->region, &given_region);
+ pixman_region32_fini(&given_region);
+ }
+ else
+ {
+ //CHECKME: check whether this situation is a kind of bug
+ ERR("Invalid tiler from region (pointer constraint region!");
+ pixman_region32_fini(&constraint->region);
+ pixman_region32_init_rect(&constraint->region,
+ INT32_MIN, INT32_MIN,
+ UINT32_MAX, UINT32_MAX);
+ }
+ }
+ else
+ {
+ pixman_region32_fini(&constraint->region);
+ pixman_region32_init_rect(&constraint->region,
+ INT32_MIN, INT32_MIN,
+ UINT32_MAX, UINT32_MAX);
+ constraint->has_region_set = EINA_TRUE;
+ }
+
+ constraint->pointer_destroy_listener.notify =
+ _e_comp_wl_pointer_constraints_pointer_destroyed;
+ constraint->surface_commit_listener.notify =
+ _e_comp_wl_pointer_constraints_surface_committed;
+ constraint->surface_focus_listener.notify =
+ _e_comp_wl_pointer_constraints_surface_focused;
+ constraint->surface_unmap_listener.notify =
+ _e_comp_wl_pointer_constraints_surface_unmapped;
+
+ wl_signal_add(&e_comp_wl->ptr_constraints.pointer_destroy_signal,
+ &constraint->pointer_destroy_listener);
+ wl_signal_add(&e_comp_wl->ptr_constraints.surface_commit_signal,
+ &constraint->surface_commit_listener);
+ wl_signal_add(&e_comp_wl->ptr_constraints.surface_focus_signal,
+ &constraint->surface_focus_listener);
+
+ return constraint;
+}
+
+static Eina_Bool
+_e_comp_wl_has_pointer_constraints_for_pointer(E_Client *ec, struct wl_resource *pointer)
+{
+ E_Comp_Wl_Pointer_Constraint *constraint;
+
+ wl_list_for_each(constraint, &ec->comp_data->pointer_constraints, link)
+ {
+ if (constraint->pointer == pointer)
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+static void
+_e_comp_wl_cb_unbind_locked_pointer(struct wl_resource *resource)
+{
+ E_Comp_Wl_Pointer_Constraint *constraint;
+ constraint = wl_resource_get_user_data(resource);
+
+ if (!constraint)
+ return;
+
+ _e_comp_wl_pointer_constraint_destroy(constraint);
+}
+
+static void
+_e_comp_wl_cb_locked_pointer_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ E_Comp_Wl_Pointer_Constraint *constraint;
+ constraint = wl_resource_get_user_data(resource);
+
+ if (constraint &&
+ constraint->ec &&
+ constraint->has_hint_set &&
+ _e_comp_wl_is_position_inside_constraint_region(constraint,
+ constraint->hint_x,
+ constraint->hint_y))
+ {
+ E_Client *ec = constraint->ec;
+ int cx = ec->client.x + wl_fixed_to_int(constraint->hint_x);
+ int cy = ec->client.x + wl_fixed_to_int(constraint->hint_y);
+ e_input_device_pointer_warp(NULL, cx, cy);
+ }
+
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_comp_wl_cb_locked_pointer_set_cursor_position_hint(struct wl_client *client,
+ struct wl_resource *resource,
+ wl_fixed_t surface_x,
+ wl_fixed_t surface_y)
+{
+ E_Comp_Wl_Pointer_Constraint *constraint =
+ (E_Comp_Wl_Pointer_Constraint *)wl_resource_get_user_data(resource);
+
+ constraint->hint_x_pending = surface_x;
+ constraint->hint_y_pending = surface_y;
+ constraint->is_hint_pending = EINA_TRUE;
+ constraint->has_hint_set = EINA_TRUE;
+}
+
+static void
+_e_comp_wl_cb_locked_pointer_set_region(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *region)
+{
+ E_Comp_Wl_Pointer_Constraint *constraint =
+ (E_Comp_Wl_Pointer_Constraint *)wl_resource_get_user_data(resource);
+
+ if (region)
+ {
+ Eina_Tiler *tiler = wl_resource_get_user_data(region);
+
+ pixman_region32_t t_region;
+
+ if (tiler)
+ {
+ pixman_region32_init(&t_region);
+ _e_comp_wl_convert_eina_tiler_to_pixman_region32(tiler, &t_region);
+ pixman_region32_copy(&constraint->region, &t_region);
+ pixman_region32_fini(&t_region);
+ }
+ else
+ {
+ //CHECKME: check whether this situation is a kind of bug
+ ERR("Invalid tiler from region (pointer constraint region!");
+ pixman_region32_fini(&constraint->region);
+ pixman_region32_init_rect(&constraint->region,
+ INT32_MIN, INT32_MIN,
+ UINT32_MAX, UINT32_MAX);
+ }
+
+ constraint->has_region_set = EINA_TRUE;
+ }
+ else
+ {
+ pixman_region32_fini(&constraint->region);
+ pixman_region32_init_rect(&constraint->region,
+ INT32_MIN, INT32_MIN,
+ UINT32_MAX, UINT32_MAX);
+ }
+
+ constraint->is_region_pending = EINA_TRUE;
+}
+
+static const struct zwp_locked_pointer_v1_interface _e_comp_wl_locked_pointer_interface =
+{
+ _e_comp_wl_cb_locked_pointer_destroy,
+ _e_comp_wl_cb_locked_pointer_set_cursor_position_hint,
+ _e_comp_wl_cb_locked_pointer_set_region,
+};
+
+static void
+_e_comp_wl_cb_pointer_constraints_lock_pointer(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *surface,
+ struct wl_resource *pointer,
+ struct wl_resource *region,
+ uint32_t lifetime)
+{
+ if (!pointer || !surface)
+ {
+ ERR("Pointer resource or surface resource is invalid !");
+ return;
+ }
+
+ E_Client *ec = wl_resource_get_user_data(surface);
+
+ if (!ec)
+ {
+ ERR("Could not get ec from surface resource !");
+ return;
+ }
+
+ if (_e_comp_wl_has_pointer_constraints_for_pointer(ec, pointer))
+ {
+ ERR("Pointer constraints has been created already (ec: %p, pointer_resource: %u)",
+ ec, wl_resource_get_id(resource));
+ wl_resource_post_error(resource,
+ ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED,
+ "the pointer has a lock set already on this surface");
+ return;
+ }
+
+ struct wl_resource *res;
+ res = wl_resource_create(client, &zwp_locked_pointer_v1_interface, 1, id);
+
+ if (!res)
+ {
+ ERR("Could not create a resource for pointer constraints lock: %m");
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ E_Comp_Wl_Pointer_Constraint *constraint;
+ constraint = _e_comp_wl_pointer_constraint_create(ec, res, pointer, region, lifetime,
+ E_COMP_WL_POINTER_CONSTRAINT_TYPE_LOCK);
+
+ if (!constraint)
+ {
+ ERR("Could not create a pointer constraint.");
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(res, &_e_comp_wl_locked_pointer_interface,
+ constraint, _e_comp_wl_cb_unbind_locked_pointer);
+
+ _e_comp_wl_pointer_constraints_check_enable(constraint);
+}
+
+static void
+_e_comp_wl_cb_pointer_constraints_confine_pointer(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *surface_resource,
+ struct wl_resource *pointer_resource,
+ struct wl_resource *region_resource,
+ uint32_t lifetime)
+{
+ (void) client;
+ (void) resource;
+ (void) id;
+ (void) surface_resource;
+ (void) pointer_resource;
+ (void) region_resource;
+ (void) lifetime;
+
+ /*
+ todo: pointer constraints confine
+ */
+}
+
+static void
+_e_comp_wl_cb_pointer_constraints_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ ERR("Destroy pointer constraints: (resource:%u) (client: %p)", wl_resource_get_id(resource), client);
+ wl_resource_destroy(resource);
+}
+
+static const struct zwp_pointer_constraints_v1_interface _e_pointer_constraints_interface = {
+ _e_comp_wl_cb_pointer_constraints_destroy,
+ _e_comp_wl_cb_pointer_constraints_lock_pointer,
+ _e_comp_wl_cb_pointer_constraints_confine_pointer,
+};
+
+static void
+_e_comp_wl_cb_unbind_pointer_constraints(struct wl_resource *resource)
+{
+ ERR("Unbind pointer constraints : (resource: %u) (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
+
+ e_comp_wl->ptr_constraints.resources =
+ eina_list_remove(e_comp_wl->ptr_constraints.resources, resource);
+}
+
+static void
+_e_comp_wl_input_cb_bind_pointer_constraints(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
+{
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(client, &zwp_pointer_constraints_v1_interface, version, id);
+
+ if (!resource)
+ {
+ ERR("Could not create pointer constraints resource: %m");
+ return;
+ }
+
+ ERR("Bind pointer constraints: (resource: %u) (client: %p)", wl_resource_get_id(resource), client);
+
+ e_comp_wl->ptr_constraints.resources =
+ eina_list_append(e_comp_wl->ptr_constraints.resources, resource);
+ wl_resource_set_implementation(resource, &_e_pointer_constraints_interface,
+ NULL, _e_comp_wl_cb_unbind_pointer_constraints);
+}
+
+static void
+_e_comp_wl_surface_cb_commit(void *data EINA_UNUSED, E_Client *ec)
+{
+ wl_signal_emit(&e_comp_wl->ptr_constraints.surface_commit_signal, ec);
}
static void
return EINA_FALSE;
}
+ /* create the global resource for pointer-constraints */
+ e_comp_wl->ptr_constraints.global =
+ wl_global_create(e_comp_wl->wl.disp,
+ &zwp_pointer_constraints_v1_interface, 1,
+ e_comp->wl_comp_data,
+ _e_comp_wl_input_cb_bind_pointer_constraints);
+ if (!e_comp_wl->ptr_constraints.global)
+ {
+ ERR("Could not create global for pointer constraints: %m");
+ return EINA_FALSE;
+ }
+
+ e_comp_wl->ptr_constraints.ec = NULL;
+ e_comp_wl->ptr_constraints.activated = EINA_FALSE;
+ wl_signal_init(&e_comp_wl->ptr_constraints.pointer_destroy_signal);
+ wl_signal_init(&e_comp_wl->ptr_constraints.surface_unmap_signal);
+ wl_signal_init(&e_comp_wl->ptr_constraints.surface_commit_signal);
+ wl_signal_init(&e_comp_wl->ptr_constraints.surface_focus_signal);
+
+ _surface_commit_hook = e_comp_wl_hook_add(E_COMP_WL_HOOK_CLIENT_SURFACE_COMMIT,
+ _e_comp_wl_surface_cb_commit,
+ NULL);
+
+
wl_array_init(&e_comp_wl->kbd.keys);
wl_array_init(&e_comp_wl->kbd.routed_keys);
E_FREE(_env_e_default_xkb_variant);
E_FREE(_env_e_default_xkb_opts );
+ /* delete surface commit hook */
+ if (_surface_commit_hook)
+ {
+ e_comp_wl_hook_del(_surface_commit_hook);
+ _surface_commit_hook = NULL;
+ }
+
/* destroy pointer resources */
EINA_LIST_FREE(e_comp_wl->ptr.resources, res)
wl_resource_destroy(res);
/* destroy relative pointer resources */
EINA_LIST_FREE(e_comp_wl->relative_ptr.resources, res)
wl_resource_destroy(res);
- //FIXME: destroy relative_pointer_manager
+
+ /* destroy relative pointer manager resources */
+ EINA_LIST_FREE(e_comp_wl->relative_ptr.manager_resources, res)
+ wl_resource_destroy(res);
+
+ /* destroy pointer constraints resources */
+ EINA_LIST_FREE(e_comp_wl->ptr_constraints.resources, res)
+ wl_resource_destroy(res);
/* destroy keyboard resources */
EINA_LIST_FREE(e_comp_wl->kbd.resources, res)
wl_global_destroy(e_comp_wl->relative_ptr.global);
e_comp_wl->relative_ptr.global = NULL;
+ /* destroy the global pointer constraints resource */
+ if (e_comp_wl->ptr_constraints.global)
+ wl_global_destroy(e_comp_wl->ptr_constraints.global);
+ e_comp_wl->ptr_constraints.global = NULL;
+
/* destroy the global seat resource */
if (e_comp_wl->seat.global)
wl_global_destroy(e_comp_wl->seat.global);