From ae09d93ad6070dad3a3758ef76aef5e8d8a4c9b4 Mon Sep 17 00:00:00 2001 From: Jihoon Kim Date: Fri, 30 Aug 2024 16:30:50 +0900 Subject: [PATCH] input: send mouse in/out event in input thread Change-Id: I51159429223ed052d405e9872867c7c992006049 Signed-off-by: Jihoon Kim --- src/bin/inputmgr/e_input_thread_client.c | 33 +++++++++ src/bin/inputmgr/e_input_thread_client_intern.h | 6 ++ src/bin/server/e_comp_wl_input_thread.c | 99 +++++++++++++++++++++++++ 3 files changed, 138 insertions(+) diff --git a/src/bin/inputmgr/e_input_thread_client.c b/src/bin/inputmgr/e_input_thread_client.c index a9c0185..ba7efe1 100644 --- a/src/bin/inputmgr/e_input_thread_client.c +++ b/src/bin/inputmgr/e_input_thread_client.c @@ -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 diff --git a/src/bin/inputmgr/e_input_thread_client_intern.h b/src/bin/inputmgr/e_input_thread_client_intern.h index bb7b0d6..8b761c9 100644 --- a/src/bin/inputmgr/e_input_thread_client_intern.h +++ b/src/bin/inputmgr/e_input_thread_client_intern.h @@ -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 diff --git a/src/bin/server/e_comp_wl_input_thread.c b/src/bin/server/e_comp_wl_input_thread.c index c945255..772f805 100644 --- a/src/bin/server/e_comp_wl_input_thread.c +++ b/src/bin/server/e_comp_wl_input_thread.c @@ -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); -- 2.7.4