From: Sungjin Park Date: Tue, 25 Apr 2023 11:18:24 +0000 (+0900) Subject: e_comp_wl & e_comp_wl_input: added implementation for zwp_pointer_constraints_v1_inte... X-Git-Tag: accepted/tizen/7.0/unified/20230502.051241~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F08%2F292008%2F1;p=platform%2Fupstream%2Fenlightenment.git e_comp_wl & e_comp_wl_input: added implementation for zwp_pointer_constraints_v1_interface Change-Id: Ib8393b03d78761e97cd92cd2b179d0d877ff1c25 Signed-off-by: Sungjin Park --- diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index cf51e1d011..72a342e950 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -3429,6 +3429,7 @@ _e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_reso ec->client.w = ec->client.h = 1; ec->comp_data->surface = res; ec->icccm.accepts_focus = 1; + wl_list_init(&ec->comp_data->pointer_constraints); } /* set reference to pixmap so we can fetch it later */ @@ -5617,11 +5618,7 @@ e_comp_wl_mouse_relative_motion_send(E_Client *ec, E_Client *focused = e_client_focused_get(); if ((focused) && (ec != focused)) return EINA_FALSE; - e_comp_wl->relative_ptr.ec = ec; - e_comp_wl->relative_ptr.activated = EINA_TRUE; - wc = wl_resource_get_client(ec->comp_data->surface); - EINA_LIST_FOREACH(e_comp_wl->relative_ptr.resources, l, res) { if (!e_comp_wl_input_relative_pointer_check(res)) continue; diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h index e16ff040e6..c002261c30 100644 --- a/src/bin/e_comp_wl.h +++ b/src/bin/e_comp_wl.h @@ -15,6 +15,7 @@ typedef struct _E_Comp_Wl_Pid_Hook E_Comp_Wl_Pid_Hook; # include # include +# include # ifdef __linux__ # include @@ -47,6 +48,7 @@ typedef struct _E_Comp_Wl_Output E_Comp_Wl_Output; typedef struct _E_Comp_Wl_Intercept_Hook E_Comp_Wl_Intercept_Hook; typedef struct _E_Comp_Wl_Evas_Gl E_Comp_Wl_Evas_Gl; typedef struct _E_Comp_Wl_Seat E_Comp_Wl_Seat; +typedef struct _E_Comp_Wl_Pointer_Constraint E_Comp_Wl_Pointer_Constraint; typedef enum _E_Comp_Wl_Buffer_Type { @@ -247,6 +249,18 @@ struct _E_Comp_Wl_Data struct wl_global *global; } relative_ptr; + struct + { + Eina_List *resources; + E_Client *ec; + Eina_Bool activated : 1; + struct wl_signal pointer_destroy_signal; + struct wl_signal surface_unmap_signal; + struct wl_signal surface_commit_signal; + struct wl_signal surface_focus_signal; + struct wl_global *global; + } ptr_constraints; + struct { Eina_List *resources; @@ -504,6 +518,8 @@ struct _E_Comp_Wl_Client_Data } sh_v6; const char *role_name; + + struct wl_list pointer_constraints; }; struct _E_Comp_Wl_Output diff --git a/src/bin/e_comp_wl_input.c b/src/bin/e_comp_wl_input.c index fdfff74111..8c2f9bf119 100644 --- a/src/bin/e_comp_wl_input.c +++ b/src/bin/e_comp_wl_input.c @@ -1,6 +1,47 @@ #define EXECUTIVE_MODE_ENABLED #include "e.h" #include +#include + +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; @@ -497,6 +538,564 @@ _e_comp_wl_input_cb_bind_relative_pointer_manager(struct wl_client *client, NULL, _e_comp_wl_input_cb_unbind_relative_pointer_manager); } +static void +_e_comp_wl_input_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_input_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 + ERR("unknown pointer constraint type (%d) !", type); +} + +static void +_e_comp_wl_input_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->relative_ptr.activated = EINA_FALSE; + e_comp_wl->relative_ptr.ec = NULL; + _e_comp_wl_input_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_input_pointer_constraint_destroy(E_Comp_Wl_Pointer_Constraint *constraint) +{ + if (constraint->active) + _e_comp_wl_input_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_input_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_input_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 + ERR("unknown pointer constraint type (%d) !", type); +} + +static void +_e_comp_wl_input_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->relative_ptr.activated = EINA_TRUE; + e_comp_wl->relative_ptr.ec = ec; + _e_comp_wl_input_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_input_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_input_is_position_inside_constraint_region(constraint, + e_comp_wl->ptr.x, + e_comp_wl->ptr.y)) + return; + + _e_comp_wl_input_pointer_constraint_enable(constraint); +} + +static void +_e_comp_wl_input_pointer_constraint_disable(E_Comp_Wl_Pointer_Constraint *constraint) +{ + int lifetime = constraint->lifetime; + + if (lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT) + _e_comp_wl_input_pointer_constraint_destroy(constraint); + else if (lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT) + _e_comp_wl_input_pointer_constraint_deactivate(constraint); + else + ERR("unknown pointer constraint lifetime (%d) !", lifetime); +} + +static void +_e_comp_wl_input_cb_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); + + if (pointer_resource == constraint->pointer) + _e_comp_wl_input_pointer_constraint_destroy(constraint); +} + +static void +_e_comp_wl_input_cb_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; + } + } + + if (found && !constraint->active) + _e_comp_wl_input_pointer_constraints_check_enable(constraint); + else if (!found && constraint->active) + _e_comp_wl_input_pointer_constraint_disable(constraint); +} + +static void +_e_comp_wl_input_cb_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); + } + + //CHECKME: check if the updated region can take effect on the given constraint +} + +static void +_e_comp_wl_input_cb_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); + + if (ec == constraint->ec) + _e_comp_wl_input_pointer_constraint_disable(constraint); +} + +static E_Comp_Wl_Pointer_Constraint * +_e_comp_wl_input_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_input_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_input_cb_pointer_constraints_pointer_destroyed; + constraint->surface_commit_listener.notify = + _e_comp_wl_input_cb_pointer_constraints_surface_committed; + constraint->surface_focus_listener.notify = + _e_comp_wl_input_cb_pointer_constraints_surface_focused; + constraint->surface_unmap_listener.notify = + _e_comp_wl_input_cb_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_input_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_input_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_input_pointer_constraint_destroy(constraint); +} + +static void +_e_comp_wl_input_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_input_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_input_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_input_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_input_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_input_cb_locked_pointer_destroy, + _e_comp_wl_input_cb_locked_pointer_set_cursor_position_hint, + _e_comp_wl_input_cb_locked_pointer_set_region, +}; + +static void +_e_comp_wl_input_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_input_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_input_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_input_cb_unbind_locked_pointer); + + _e_comp_wl_input_pointer_constraints_check_enable(constraint); +} + +static void +_e_comp_wl_input_cb_pointer_constraints_confine_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) +{ + (void) client; + (void) resource; + (void) id; + (void) surface; + (void) pointer; + (void) region; + (void) lifetime; + + /* TODO: pointer constraints confine */ +} + +static void +_e_comp_wl_input_cb_pointer_constraints_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct zwp_pointer_constraints_v1_interface _e_pointer_constraints_interface = { + _e_comp_wl_input_cb_pointer_constraints_destroy, + _e_comp_wl_input_cb_pointer_constraints_lock_pointer, + _e_comp_wl_input_cb_pointer_constraints_confine_pointer, +}; + +static void +_e_comp_wl_input_cb_unbind_pointer_constraints(struct wl_resource *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; + } + + 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_input_cb_unbind_pointer_constraints); +} + static void _e_comp_wl_input_keymap_cache_create(const char *keymap_path, char *keymap_data) { @@ -731,6 +1330,25 @@ e_comp_wl_input_init(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); + wl_array_init(&e_comp_wl->kbd.keys); wl_array_init(&e_comp_wl->kbd.routed_keys); @@ -770,6 +1388,10 @@ e_comp_wl_input_shutdown(void) 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_resource_destroy(res); @@ -805,6 +1427,11 @@ e_comp_wl_input_shutdown(void) 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);