discomfitor pushed a commit to branch enlightenment-0.22.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=e4cf048112c3006cf279fc20d213fb9784ea810a

commit e4cf048112c3006cf279fc20d213fb9784ea810a
Author: Mike Blumenkrantz <[email protected]>
Date:   Fri Nov 3 13:23:26 2017 -0400

    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
---
 src/bin/e_comp_wl.c       | 24 ++++++++++++---
 src/bin/e_comp_wl.h       |  9 ++++++
 src/bin/e_comp_wl_input.c | 74 +++++++++++++++++++++++++----------------------
 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 141132c77..320830451 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 199923a45..84212850d 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 b1d50e959..e9f1bd385 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 8884deec3..e726aa0c1 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);

-- 


Reply via email to