e_client: Introduce E_Client_Private 28/299228/2
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 21 Sep 2023 00:15:39 +0000 (09:15 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 22 Sep 2023 05:33:48 +0000 (05:33 +0000)
This commit introduces an E_Client_Private within the E_Client.

It's designed to store private data related to E_Client. This approach
prevents us from breaking ABI when adding or removing fields from the
E_Client structure. Instead, we can modify the E_Client_Private
structure as needed.

A pointer to E_Client_Private will be assigned to e_object's data and
accessed through e_object's data using e_object_data_{set,get}. So it's
crucial to ensure that no one overwrites it with different data using
e_object_data_set.

Change-Id: I4dff782d2d661f6eb0007253484640ebc9e3c2c4

src/bin/e_client.c
src/bin/e_client_intern.h [new file with mode: 0644]

index 10f4097..b89d32c 100644 (file)
@@ -1,4 +1,25 @@
 #include "e.h"
+#include "e_client_intern.h"
+
+#define PRI(ec) ((E_Client_Private *)e_object_data_get(E_OBJECT(ec)))
+
+#define API_ENTRY \
+   EINA_SAFETY_ON_NULL_RETURN(ec); \
+   E_Client_Private *priv = PRI(ec)
+
+#define API_ENTRY_VAL(ret) \
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ret); \
+   E_Client_Private *priv = PRI(ec)
+
+typedef struct _E_Client_Private E_Client_Private;
+
+struct _E_Client_Private
+{
+   struct
+     {
+        struct wl_signal destroy;
+     } events;
+};
 
 static int _e_client_hooks_delete = 0;
 static int _e_client_hooks_walking = 0;
@@ -1052,6 +1073,33 @@ e_client_check_above_focused(E_Client *ec)
    return EINA_FALSE;
 }
 
+static Eina_Bool
+_e_client_private_init(E_Client *ec)
+{
+   E_Client_Private *priv;
+
+   priv = E_NEW(E_Client_Private, 1);
+   if (!priv)
+     return EINA_FALSE;
+
+   wl_signal_init(&priv->events.destroy);
+
+   e_object_data_set(E_OBJECT(ec), priv);
+
+   return EINA_TRUE;
+}
+
+static void
+_e_client_private_finish(E_Client *ec)
+{
+   E_Client_Private *priv;
+
+   priv = PRI(ec);
+   e_object_data_set(E_OBJECT(ec), NULL);
+
+   free(priv);
+}
+
 static void
 _e_client_free(E_Client *ec)
 {
@@ -1152,6 +1200,8 @@ _e_client_free(E_Client *ec)
 #else
    e_desk_client_del(ec->desk, ec);
 #endif
+
+   _e_client_private_finish(ec);
    free(ec);
 }
 
@@ -1202,6 +1252,8 @@ _e_client_del(E_Client *ec)
    /* must be called before parent/child clear */
    _e_client_hook_call(E_CLIENT_HOOK_DEL, ec);
 
+   wl_signal_emit_mutable(&PRI(ec)->events.destroy, ec);
+
    _e_client_event_remove(ec);
 
    ELOGF("COMP", "CLIENT DEL", ec);
@@ -4079,6 +4131,12 @@ e_client_new(E_Pixmap *cp, int first_map, int internal)
    if (!ec) return NULL;
    e_object_del_func_set(E_OBJECT(ec), E_OBJECT_CLEANUP_FUNC(_e_client_del));
 
+   if (!_e_client_private_init(ec))
+     {
+        e_object_del(E_OBJECT(ec));
+        return NULL;
+     }
+
    uuid_generate(ec->uuid);
 
    ec->focus_policy_override = E_FOCUS_LAST;
@@ -8780,3 +8838,16 @@ e_client_uniconify_event_send(E_Client *ec)
 }
 #endif
 
+EINTERN void
+e_client_destroy_listener_add(E_Client *ec, struct wl_listener *listener)
+{
+   API_ENTRY;
+   wl_signal_add(&priv->events.destroy, listener);
+}
+
+EINTERN struct wl_listener *
+e_client_destroy_listener_get(E_Client *ec, wl_notify_func_t notify)
+{
+   API_ENTRY_VAL(NULL);
+   return wl_signal_get(&priv->events.destroy, notify);
+}
\ No newline at end of file
diff --git a/src/bin/e_client_intern.h b/src/bin/e_client_intern.h
new file mode 100644 (file)
index 0000000..d2aea09
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef E_CLIENT_INTERN_H
+#define E_CLIENT_INTERN_H
+
+#include <wayland-server.h>
+
+typedef struct E_Client E_Client;
+
+void e_client_destroy_listener_add(E_Client *ec, struct wl_listener *listener);
+struct wl_listener *e_client_destroy_listener_get(E_Client *ec, wl_notify_func_t notify);
+
+#endif