input: send mouse in/out event in input thread 17/317417/1
authorJihoon Kim <jihoon48.kim@samsung.com>
Fri, 30 Aug 2024 07:30:50 +0000 (16:30 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Tue, 10 Sep 2024 04:21:17 +0000 (13:21 +0900)
Change-Id: I51159429223ed052d405e9872867c7c992006049
Signed-off-by: Jihoon Kim <jihoon48.kim@samsung.com>
src/bin/inputmgr/e_input_thread_client.c
src/bin/inputmgr/e_input_thread_client_intern.h
src/bin/server/e_comp_wl_input_thread.c

index a9c0185..ba7efe1 100644 (file)
@@ -15,6 +15,8 @@ struct _E_Input_Thread_Client
    Eina_Bool is_video;
    Eina_Bool deleted;
    Eina_Bool is_cursor;
+   Eina_Bool mouse_in;
+   Eina_Bool pointer_enter_sent;
    Eina_Stringshare *icccm_name;
    Eina_Stringshare *netwm_name;
    Eina_Stringshare *icccm_title;
@@ -642,3 +644,34 @@ e_input_thread_client_last_device_get(E_Input_Thread_Client *iec, Ecore_Device_C
      }
    return NULL;
 }
+
+EINTERN void
+e_input_thread_client_mouse_in_set(E_Input_Thread_Client *iec, Eina_Bool mouse_in)
+{
+   EINA_SAFETY_ON_NULL_RETURN(iec);
+
+   iec->mouse_in = mouse_in;
+}
+
+EINTERN Eina_Bool e_input_thread_client_mouse_in_get(E_Input_Thread_Client *iec)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(iec, EINA_FALSE);
+
+   return iec->mouse_in;
+}
+
+EINTERN void
+e_input_thread_client_pointer_enter_sent_set(E_Input_Thread_Client *iec, Eina_Bool sent)
+{
+   EINA_SAFETY_ON_NULL_RETURN(iec);
+
+   iec->pointer_enter_sent = sent;
+}
+
+EINTERN Eina_Bool
+e_input_thread_client_pointer_enter_sent_get(E_Input_Thread_Client *iec)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(iec, EINA_FALSE);
+
+   return iec->pointer_enter_sent;
+}
\ No newline at end of file
index bb7b0d6..8b761c9 100644 (file)
@@ -96,4 +96,10 @@ EINTERN Eina_Bool e_input_thread_check_client_cloning_needed();
 EINTERN void e_input_thread_client_last_device_set(E_Input_Thread_Client *iec, Ecore_Device_Class dev_class, E_Devicemgr_Input_Device *device);
 EINTERN E_Devicemgr_Input_Device *e_input_thread_client_last_device_get(E_Input_Thread_Client *iec, Ecore_Device_Class dev_class);
 
+EINTERN void e_input_thread_client_mouse_in_set(E_Input_Thread_Client *ec, Eina_Bool mouse_in);
+EINTERN Eina_Bool e_input_thread_client_mouse_in_get(E_Input_Thread_Client *ec);
+
+EINTERN void e_input_thread_client_pointer_enter_sent_set(E_Input_Thread_Client *iec, Eina_Bool sent);
+EINTERN Eina_Bool e_input_thread_client_pointer_enter_sent_get(E_Input_Thread_Client *iec);
+
 #endif
index c945255..772f805 100644 (file)
@@ -141,6 +141,93 @@ _e_comp_wl_device_input_thread_send_event_device(E_Input_Thread_Client *iec, E_D
    g_rec_mutex_unlock(&e_devicemgr->device_list_mutex);
 }
 
+static void
+_e_comp_wl_input_thread_send_mouse_in(E_Input_Thread_Client *iec, int x, int y, int client_x, int client_y, int timestamp)
+{
+   struct wl_resource *res;
+   struct wl_client *wc;
+   Eina_List *l;
+   uint32_t serial;
+
+   e_comp_wl->ptr.x = wl_fixed_from_int(x);
+   e_comp_wl->ptr.y = wl_fixed_from_int(y);
+
+   if (!iec) return;
+
+   struct wl_resource *surface = e_input_thread_client_wl_resource_get(iec);
+   if (!surface) return;
+
+   ELOGF("Mouse", "In  (time: %d, canvas(%d, %d) output(%d, %d), name:%20s)",
+         NULL, timestamp, x, y, x, y,
+         e_input_thread_client_util_name_get(iec));
+
+   if (!eina_list_count(e_comp_wl->ptr.resources)) return;
+   wc = wl_resource_get_client(surface);
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
+     {
+        if (!e_comp_wl_input_pointer_check(res)) continue;
+        if (wl_resource_get_client(res) != wc) continue;
+
+        ELOGF("Mouse", "call wl_pointer_send_enter", NULL);
+
+        wl_pointer_send_enter(res, serial, surface,
+                              wl_fixed_from_int(x - client_x),
+                              wl_fixed_from_int(y - client_y));
+
+        e_input_thread_client_pointer_enter_sent_set(iec, EINA_TRUE);
+     }
+}
+
+static void
+_e_comp_wl_input_thread_send_mouse_out(E_Input_Thread_Client *iec, int timestamp)
+{
+   struct wl_resource *res;
+   struct wl_client *wc;
+   Eina_List *l;
+   uint32_t serial;
+
+   if (!iec) return;
+
+   struct wl_resource *surface = e_input_thread_client_wl_resource_get(iec);
+   if (!surface) return;
+
+   ELOGF("Mouse", "Out (time: %d, name:%20s)",
+         NULL, timestamp,
+         e_input_thread_client_util_name_get(iec));
+
+   if (!eina_list_count(e_comp_wl->ptr.resources)) return;
+
+   wc = wl_resource_get_client(surface);
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
+     {
+        if (!e_comp_wl_input_pointer_check(res)) continue;
+        if (wl_resource_get_client(res) != wc) continue;
+        if (e_input_thread_client_pointer_enter_sent_get(iec) == EINA_FALSE) continue;
+
+        wl_pointer_send_leave(res, serial, surface);
+
+        e_input_thread_client_pointer_enter_sent_set(iec, EINA_FALSE);
+     }
+}
+
+static void
+_e_comp_wl_input_thread_check_mouse_out(E_Input_Thread_Client *hit_iec, int timestamp)
+{
+   E_Input_Thread_Client *iec = NULL;
+   for (iec = e_input_thread_client_top_get(); iec; iec = e_input_thread_client_below_get(iec))
+     {
+        if (e_input_thread_client_mouse_in_get(iec) && iec != hit_iec)
+          {
+             // send leave
+             _e_comp_wl_input_thread_send_mouse_out(iec, timestamp);
+             e_input_thread_client_mouse_in_set(iec, EINA_FALSE);
+             break;
+          }
+     }
+}
+
 static Eina_Bool
 _e_comp_wl_cb_mouse_move_thread_mode(void *d EINA_UNUSED, int t EINA_UNUSED, void *event)
 {
@@ -182,6 +269,18 @@ _e_comp_wl_cb_mouse_move_thread_mode(void *d EINA_UNUSED, int t EINA_UNUSED, voi
 
    e_input_thread_client_geometry_get(iec, &client_x, &client_y, NULL, NULL);
 
+   // send mouse-out event
+   _e_comp_wl_input_thread_check_mouse_out(iec, ev->timestamp);
+
+   if (!e_input_thread_client_mouse_in_get(iec))
+     {
+        e_input_thread_client_mouse_in_set(iec, EINA_TRUE);
+
+        // send mouse-in event
+        _e_comp_wl_input_thread_send_mouse_in(iec, ev->x, ev->y, client_x, client_y, ev->timestamp);
+     }
+
+   // send mouse move event
    e_comp_wl_surface_send_mouse_move(surface, ev->x, ev->y, client_x, client_y, ev->timestamp);
 
    e_input_thread_client_geometry_get(iec, &client_x, &client_y, NULL, NULL);