e_devicemgr: create tizen_input_devices only for first bound seat & manager 40/284140/1
authorduna.oh <duna.oh@samsung.com>
Thu, 10 Nov 2022 05:34:33 +0000 (14:34 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Thu, 10 Nov 2022 09:43:41 +0000 (18:43 +0900)
If a wayland_client uses ecore_wl library and efl_util API,
it binds two pairs of wl_seat & tizen_input_device_manager.

ecore_wl listens wayland events (ex. device_add/device_remove) and send
requests properly. (ex. tizen_input_device_release)

However efl_util dispatches event queue only when efl_util API is called.
It doesn't send tizen_input_device_release requests and causes resource leaks.

To fix this resource leak,
this patch is to create tizen_input_device resources only for
the first bound wl_seat & first bound tizen_input_devcie_manager
which ecore_wl binds.
efl_util always binds wl_globals after ecore_wl2 binds ones.

Change-Id: I47c741a36c2205e2bde2a630a4b66d3794aa23ef

src/bin/e_comp_wl.h
src/bin/e_comp_wl_input.c
src/bin/e_devicemgr_private.h
src/bin/e_devicemgr_wl.c

index 6cea0c1..8471de5 100644 (file)
@@ -44,6 +44,7 @@ typedef struct _E_Comp_Wl_Data E_Comp_Wl_Data;
 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 enum _E_Comp_Wl_Buffer_Type
 {
@@ -536,6 +537,11 @@ struct _E_Comp_Wl_Intercept_Hook
    unsigned char delete_me : 1;
 };
 
+struct _E_Comp_Wl_Seat
+{
+   Eina_Bool is_first_resource : 1;
+};
+
 EINTERN Eina_Bool e_comp_wl_init(void);
 EINTERN void e_comp_wl_shutdown(void);
 
index c5354a3..4653983 100644 (file)
@@ -352,21 +352,48 @@ static const struct wl_seat_interface _e_seat_interface =
 static void
 _e_comp_wl_input_cb_unbind_seat(struct wl_resource *resource)
 {
+   E_Comp_Wl_Seat *seat = wl_resource_get_user_data(resource);
+
+   DBG("Unbind seat: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
+
    e_comp_wl->seat.resources =
      eina_list_remove(e_comp_wl->seat.resources, resource);
+   E_FREE(seat);
 }
 
 static void
 _e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
 {
    struct wl_resource *res;
+   Eina_List *l;
+   struct wl_resource *tmp_res;
+   E_Comp_Wl_Seat *seat;
+
+   seat = E_NEW(E_Comp_Wl_Seat, 1);
+   if (!seat)
+     {
+        ERR("Failed to allocate memory for seat data\n");
+        wl_client_post_no_memory(client);
+        return;
+     }
+   seat->is_first_resource = 1;
+
+   EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, tmp_res)
+     {
+        if (wl_resource_get_client(tmp_res) != client) continue;
+        DBG("wl_seat (res: %d) is already bound to client (%p)",
+            wl_resource_get_id(tmp_res), client);
+        seat->is_first_resource = 0;
+     }
 
    res = wl_resource_create(client, &wl_seat_interface, version, id);
    if (!res)
      {
         ERR("Could not create seat resource: %m");
+        E_FREE(seat);
         return;
      }
+   DBG("Bind seat: %u (client: %p)", wl_resource_get_id(res), client);
 
    /* store version of seat interface for reuse in updating capabilities */
    e_comp_wl->seat.version = version;
@@ -374,7 +401,7 @@ _e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data EINA_UNUSED,
      eina_list_append(e_comp_wl->seat.resources, res);
 
    wl_resource_set_implementation(res, &_e_seat_interface,
-                                  e_comp->wl_comp_data,
+                                  seat,
                                   _e_comp_wl_input_cb_unbind_seat);
 
    _e_comp_wl_input_update_seat_caps(client);
index b13391e..5297150 100644 (file)
@@ -53,6 +53,7 @@ typedef struct _E_Devicemgr_Inputgen_Resource_Data E_Devicemgr_Inputgen_Resource
 struct _E_Devicemgr_Input_Device_Mgr_Data
 {
     struct wl_resource *resource;
+    Eina_Bool is_first_resource : 1;
     Eina_List *user_data_list;
 };
 
index 6e09a3e..14af373 100644 (file)
@@ -137,6 +137,7 @@ e_devicemgr_wl_device_add(E_Devicemgr_Input_Device *dev)
    E_Devicemgr_Input_Device_User_Data *device_user_data;
    struct wl_array axes;
    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
+   E_Comp_Wl_Seat *seat_data;
 
    /* TODO: find the seat corresponding to event */
    serial = wl_display_next_serial(e_comp_wl->wl.disp);
@@ -144,12 +145,26 @@ e_devicemgr_wl_device_add(E_Devicemgr_Input_Device *dev)
 
    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
      {
+        seat_data = wl_resource_get_user_data(seat_res);
+        if (!seat_data->is_first_resource)
+          {
+             DMDBG("The seat (res:%d) is not the first resource bound to client (%p)",
+                   wl_resource_get_id(seat_res), wl_resource_get_client(seat_res));
+             continue;
+          }
+
         wc = wl_resource_get_client(seat_res);
 
         EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, ll, mgr_data)
           {
              dev_mgr_res = mgr_data->resource;
              if (wl_resource_get_client(dev_mgr_res) != wc) continue;
+             if (!mgr_data->is_first_resource)
+               {
+                  DMDBG("This device_manager (res:%d) not the first resource bound to client (%p)",
+                        wl_resource_get_id(dev_mgr_res), wc);
+                  continue;
+               }
              res = wl_resource_create(wc, &tizen_input_device_interface, 1, 0);
              if (!res)
                  {
@@ -568,7 +583,7 @@ _e_devicemgr_wl_cb_bind(struct wl_client *client, void *data, uint32_t version,
    E_Devicemgr_Input_Device *dev;
    struct wl_array axes;
    E_Devicemgr_Input_Device_User_Data *device_user_data;
-   E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
+   E_Devicemgr_Input_Device_Mgr_Data *mgr_data, *tmp_data;
 
    mgr_data = E_NEW(E_Devicemgr_Input_Device_Mgr_Data, 1);
    if (!mgr_data)
@@ -577,6 +592,15 @@ _e_devicemgr_wl_cb_bind(struct wl_client *client, void *data, uint32_t version,
         wl_client_post_no_memory(client);
         return;
      }
+   mgr_data->is_first_resource = 1;
+
+   EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, l, tmp_data)
+     {
+        if (wl_resource_get_client(tmp_data->resource) != client) continue;
+        DMDBG("tizen_input_device_manager (res: %d) is already bound to client (%p)",
+              wl_resource_get_id(tmp_data->resource), client);
+        mgr_data->is_first_resource = 0;
+     }
 
    if (!(res = wl_resource_create(client, &tizen_input_device_manager_interface, version, id)))
      {
@@ -586,6 +610,8 @@ _e_devicemgr_wl_cb_bind(struct wl_client *client, void *data, uint32_t version,
         return;
      }
 
+   DMDBG("Bind tizen_input_device_manager: %u (client: %p)", wl_resource_get_id(res), wl_resource_get_client(res));
+
    mgr_data->resource = res;
    mgr_data->user_data_list = NULL;
    e_devicemgr->wl_data->mgr_data_list = eina_list_append(e_devicemgr->wl_data->mgr_data_list, mgr_data);
@@ -593,6 +619,13 @@ _e_devicemgr_wl_cb_bind(struct wl_client *client, void *data, uint32_t version,
    wl_resource_set_implementation(res, &_e_devicemgr_wl_implementation, mgr_data,
                                   _e_devicemgr_wl_cb_unbind);
 
+   if (!mgr_data->is_first_resource)
+   {
+      DMDBG("This device_manager (res:%d) is not the first resource bound to client (%p)",
+            wl_resource_get_id(res), client);
+      return;
+   }
+
    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
      {
         if (wl_resource_get_client(seat_res) != client) continue;