diff options
author | Mike Blumenkrantz <zmike@osg.samsung.com> | 2017-11-03 13:23:26 -0400 |
---|---|---|
committer | Mike Blumenkrantz <zmike@osg.samsung.com> | 2017-11-03 13:21:57 -0400 |
commit | b8f8c42aec9391d23a4fb78ec205843b213eaa93 (patch) | |
tree | acaf40576617dbf191c6baa5c26a782edc33e5ba | |
parent | 58e686caec495a5224a89ab1f28b6a0f102001b3 (diff) | |
download | enlightenment-b8f8c42aec9391d23a4fb78ec205843b213eaa93.tar.gz |
make wl_pointer cursor handling state-based to correctly handle cursor visuals
this fixes a lot of corner cases such as apps which set their cursor before
receiving pointer.enter events
-rw-r--r-- | src/bin/e_comp_wl.c | 24 | ||||
-rw-r--r-- | src/bin/e_comp_wl.h | 9 | ||||
-rw-r--r-- | src/bin/e_comp_wl_input.c | 74 | ||||
-rw-r--r-- | src/bin/e_comp_wl_input.h | 2 |
4 files changed, 71 insertions, 38 deletions
diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index 141132c772..3208304512 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -211,11 +211,15 @@ _e_comp_wl_mouse_in(E_Client *ec, Evas_Event_Mouse_In *ev) serial = wl_display_next_serial(e_comp_wl->wl.disp); EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res) { + E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(res); + if (!e_comp_wl_input_pointer_check(res)) continue; if (wl_resource_get_client(res) != wc) continue; + ptr->entered = 1; wl_pointer_send_enter(res, serial, ec->comp_data->surface, wl_fixed_from_int(ev->canvas.x - ec->client.x), wl_fixed_from_int(ev->canvas.y - ec->client.y)); + e_comp_wl_input_pointer_cursor_update(ptr); } } @@ -267,8 +271,10 @@ _e_comp_wl_mouse_out(E_Client *ec) serial = wl_display_next_serial(e_comp_wl->wl.disp); EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res) { + E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(res); if (!e_comp_wl_input_pointer_check(res)) continue; if (wl_resource_get_client(res) != wc) continue; + ptr->entered = 0; wl_pointer_send_leave(res, serial, ec->comp_data->surface); } } @@ -2591,11 +2597,21 @@ _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec) _e_comp_wl_mouse_out(ec); else if (ec->comp_data->cursor) { - Evas_Object *o; + Eina_List *l; + struct wl_resource *res; + + EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res) + { + E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(res); - ecore_evas_cursor_get(e_comp->ee, &o, NULL, NULL, NULL); - if (o == ec->frame) - e_pointer_object_set(e_comp->pointer, NULL, 0, 0); + if (ptr->cursor_set && (ptr->cursor == ec)) + { + ptr->cursor = NULL; + ptr->cursor_set = 0; + if (ptr->entered) + e_comp_wl_input_pointer_cursor_update(ptr); + } + } } if (ec->comp_data->aux_hint.hints) diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h index 199923a45e..84212850d4 100644 --- a/src/bin/e_comp_wl.h +++ b/src/bin/e_comp_wl.h @@ -5,6 +5,7 @@ typedef struct _E_Comp_Wl_Subsurf_Data E_Comp_Wl_Subsurf_Data; typedef struct _E_Comp_Wl_Surface_State E_Comp_Wl_Surface_State; typedef struct _E_Comp_Wl_Client_Data E_Comp_Wl_Client_Data; typedef struct _E_Comp_Wl_Output E_Comp_Wl_Output; +typedef struct _E_Comp_Wl_Pointer E_Comp_Wl_Pointer; typedef struct E_Shell_Data E_Shell_Data; typedef struct Tizen_Extensions Tizen_Extensions; typedef void (*E_Comp_Wl_Grab_End_Cb)(E_Client*); @@ -394,6 +395,14 @@ struct _E_Comp_Wl_Output void *data; }; +struct _E_Comp_Wl_Pointer +{ + E_Client *cursor; + Evas_Point offset; + Eina_Bool entered : 1; + Eina_Bool cursor_set : 1; +}; + E_API Eina_Bool e_comp_wl_init(void); EINTERN void e_comp_wl_shutdown(void); diff --git a/src/bin/e_comp_wl_input.c b/src/bin/e_comp_wl_input.c index b1d50e959b..e9f1bd385c 100644 --- a/src/bin/e_comp_wl_input.c +++ b/src/bin/e_comp_wl_input.c @@ -43,39 +43,18 @@ _e_comp_wl_input_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struc } static void -_e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, uint32_t serial EINA_UNUSED, struct wl_resource *surface_resource, int32_t x, int32_t y) +_e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial EINA_UNUSED, struct wl_resource *surface_resource, int32_t x, int32_t y) { E_Client *ec; - Eina_Bool got_mouse = EINA_FALSE; - - E_CLIENT_FOREACH(ec) - { - if (e_object_is_del(E_OBJECT(ec))) continue; - if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) continue; - if (!ec->comp_data->surface) continue; - if (client != wl_resource_get_client(ec->comp_data->surface)) continue; - if (ec->mouse.in) - { - if (e_client_has_xwindow(ec)) - got_mouse = E_INSIDE(ec->mouse.current.mx, ec->mouse.current.my, - ec->client.x, ec->client.y, ec->client.w, ec->client.h); - else - got_mouse = EINA_TRUE; - break; - } - } - if (!got_mouse) - { - if (ec && ec->mouse.in && (!surface_resource)) - e_pointer_object_set(e_comp->pointer, NULL, 0, 0); - return; - } + E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(resource); + if (!surface_resource) { - if (e_comp_object_frame_exists(ec->frame) && - ec->mouse.in && (!ec->comp_data->ssd_mouse_in)) - e_pointer_object_set(e_comp->pointer, NULL, 0, 0); - else + ptr->cursor_set = 1; + ptr->cursor = NULL; + ptr->offset.x = x; + ptr->offset.y = y; + if (ptr->entered) { ecore_evas_cursor_unset(e_comp->ee); evas_object_hide(e_comp->pointer->o_ptr); @@ -89,6 +68,10 @@ _e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client, struct wl_resou * are being processed... let's BAIL. */ if (!ec) return; + ptr->cursor_set = 1; + ptr->cursor = ec; + ptr->offset.x = x; + ptr->offset.y = y; if (ec->comp_data->pending.input) eina_tiler_clear(ec->comp_data->pending.input); else @@ -113,9 +96,8 @@ _e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client, struct wl_resou EC_CHANGED(ec); } - /* ignore cursor changes during resize/move I guess */ - if (e_client_action_get()) return; - e_pointer_object_set(e_comp->pointer, ec->frame, x, y); + if (ptr->entered) + e_comp_wl_input_pointer_cursor_update(ptr); } static const struct wl_pointer_interface _e_pointer_interface = @@ -137,14 +119,20 @@ static const struct wl_touch_interface _e_touch_interface = static void _e_comp_wl_input_cb_pointer_unbind(struct wl_resource *resource) { + E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(resource); + + if (ptr->cursor_set && ptr->entered) + e_pointer_object_set(e_comp->pointer, NULL, 0, 0); e_comp_wl->ptr.resources = eina_list_remove(e_comp_wl->ptr.resources, resource); + free(ptr); } static void _e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct wl_resource *res; + E_Comp_Wl_Pointer *ptr; /* try to create pointer resource */ res = wl_resource_create(client, &wl_pointer_interface, @@ -156,12 +144,12 @@ _e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *re wl_client_post_no_memory(client); return; } + ptr = E_NEW(E_Comp_Wl_Pointer, 1); e_comp_wl->ptr.resources = eina_list_append(e_comp_wl->ptr.resources, res); - wl_resource_set_user_data(res, resource); wl_resource_set_implementation(res, &_e_pointer_interface, - e_comp->wl_comp_data, + ptr, _e_comp_wl_input_cb_pointer_unbind); } @@ -547,6 +535,24 @@ e_comp_wl_input_shutdown(void) e_comp_wl->seat.global = NULL; } +EINTERN void +e_comp_wl_input_pointer_cursor_update(E_Comp_Wl_Pointer *ptr) +{ + EINA_SAFETY_ON_TRUE_RETURN(!ptr->entered); + if (ptr->cursor_set && (!e_comp_util_mouse_grabbed())) + { + if (ptr->cursor) + e_pointer_object_set(e_comp->pointer, ptr->cursor->frame, ptr->offset.x, ptr->offset.y); + else + { + ecore_evas_cursor_unset(e_comp->ee); + evas_object_hide(e_comp->pointer->o_ptr); + } + } + else + e_pointer_object_set(e_comp->pointer, NULL, 0, 0); +} + EINTERN Eina_Bool e_comp_wl_input_pointer_check(struct wl_resource *res) { diff --git a/src/bin/e_comp_wl_input.h b/src/bin/e_comp_wl_input.h index 8884deec30..e726aa0c1a 100644 --- a/src/bin/e_comp_wl_input.h +++ b/src/bin/e_comp_wl_input.h @@ -18,6 +18,8 @@ EINTERN Eina_Bool e_comp_wl_input_pointer_check(struct wl_resource *res); EINTERN Eina_Bool e_comp_wl_input_keyboard_check(struct wl_resource *res); EINTERN Eina_Bool e_comp_wl_input_touch_check(struct wl_resource *res); +EINTERN void e_comp_wl_input_pointer_cursor_update(E_Comp_Wl_Pointer *ptr); + EINTERN Eina_Bool e_comp_wl_input_keyboard_modifiers_serialize(void); EINTERN void e_comp_wl_input_keyboard_modifiers_update(void); EINTERN void e_comp_wl_input_keyboard_state_update(uint32_t keycode, Eina_Bool pressed); |