pingpong: added a initial version for reference implementation of ping-pong policy. 39/197639/1
authorGwanglim Lee <gl77.lee@samsung.com>
Tue, 15 Jan 2019 01:10:28 +0000 (10:10 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Tue, 15 Jan 2019 01:10:28 +0000 (10:10 +0900)
This implementation asks the touched client if it's still alive.
However there is no specific policy how to handle if the client doesn't respond.
An implementor should make your own way for handling unresponsive client such as kill.

To enable this feature, use_pingpong_policy configuration value must be set.

Change-Id: I138f6023573f7f425f4af92adcc5cc6bc1cd9926

src/Makefile.am
src/e_mod_config.c
src/e_mod_main.c
src/e_mod_main.h
src/e_mod_pol_pingpong.c [new file with mode: 0644]
src/e_mod_pol_pingpong.h [new file with mode: 0644]

index f4c90b5..0194a93 100644 (file)
@@ -34,6 +34,8 @@ ROT_SRC  += rotation/e_mod_rotation_wl.c \
 module_la_SOURCES      = e_mod_config.c \
                          e_mod_main.c \
                          e_mod_main.h \
+                         e_mod_pol_pingpong.c \
+                         e_mod_pol_pingpong.h \
                          $(WL_SRC) \
                          $(ROT_SRC)
 
index bd6a585..467080f 100644 (file)
@@ -17,6 +17,7 @@ e_mod_pol_conf_init(Mod *mod)
 #define T Config
 #define D mod->conf_edd
    E_CONFIG_LIST(D, T, rotations, mod->conf_rot_edd);
+   E_CONFIG_VAL(D, T, use_pingpong_policy, INT);
 #undef T
 #undef D
 
@@ -57,3 +58,9 @@ e_mod_pol_conf_rot_enable_get(int angle)
 
    return EINA_FALSE;
 }
+
+EINTERN Eina_Bool
+e_mod_pol_conf_use_pingpoing_policy_get(void)
+{
+   return _pol_mod->conf->use_pingpong_policy;
+}
index 5f5ec7e..b474868 100644 (file)
@@ -1,5 +1,6 @@
 #include "e_mod_main.h"
 #include "e_mod_rotation.h"
+#include "e_mod_pol_pingpong.h"
 #include "e_mod_ivi_home.h"
 #include <stdlib.h>
 #include <system_info.h>
@@ -68,6 +69,7 @@ e_modapi_init(E_Module *m)
 
    e_mod_pol_conf_init(mod);
    e_mod_pol_rotation_init();
+   e_mod_pol_pingpong_init();
    if (_tz_profile_type_get() == TZ_PROFILE_TYPE_IVI)
      e_mod_ivi_home_init();
 
@@ -79,6 +81,7 @@ e_modapi_shutdown(E_Module *m)
 {
    Mod *mod = m->data;
 
+   e_mod_pol_pingpong_shutdown();
    e_mod_pol_rotation_shutdown();
    e_mod_pol_conf_shutdown(mod);
    if (_tz_profile_type_get() == TZ_PROFILE_TYPE_IVI)
index 58cfbf1..2b29a8c 100644 (file)
@@ -15,6 +15,7 @@ struct _Config_Rot
 struct _Config
 {
    Eina_List       *rotations;
+   int              use_pingpong_policy;
 };
 
 struct _Mod
@@ -62,4 +63,5 @@ extern Mod *_pol_mod;
 EINTERN void             e_mod_pol_conf_init(Mod *mod);
 EINTERN void             e_mod_pol_conf_shutdown(Mod *mod);
 EINTERN Eina_Bool        e_mod_pol_conf_rot_enable_get(int angle);
+EINTERN Eina_Bool        e_mod_pol_conf_use_pingpoing_policy_get(void);
 #endif
diff --git a/src/e_mod_pol_pingpong.c b/src/e_mod_pol_pingpong.c
new file mode 100644 (file)
index 0000000..154c2d7
--- /dev/null
@@ -0,0 +1,239 @@
+#include <e.h>
+#include "e_mod_main.h"
+#include "e_mod_pol_pingpong.h"
+
+#define PONG_WAIT_TIME 2.0
+
+typedef struct _PP_Win
+{
+   E_Client    *ec;
+   Ecore_Timer *t_pong_wait;
+   Eina_Bool    ping_sent;
+} PP_Win;
+
+static Eina_List *_handlers = NULL;
+static Eina_List *_pp_wins  = NULL;
+
+static void _cb_client_mouse_down(void *data, Evas *e, Evas_Object *o, void *event);
+
+static PP_Win *
+_pp_win_add(E_Client *ec)
+{
+   PP_Win *ppw;
+
+   ppw = E_NEW(PP_Win, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ppw, NULL);
+
+   ppw->ec = ec;
+
+   evas_object_event_callback_add(ec->frame,
+                                  EVAS_CALLBACK_MOUSE_DOWN,
+                                  _cb_client_mouse_down,
+                                  ppw);
+
+   _pp_wins = eina_list_append(_pp_wins, ppw);
+
+   return ppw;
+}
+
+static void
+_pp_win_del(PP_Win *ppw)
+{
+   if (ppw->t_pong_wait)
+     ecore_timer_del(ppw->t_pong_wait);
+
+   evas_object_event_callback_del(ppw->ec->frame,
+                                  EVAS_CALLBACK_MOUSE_DOWN,
+                                  _cb_client_mouse_down);
+   E_FREE(ppw);
+}
+
+static PP_Win *
+_pp_win_find(E_Client *ec)
+{
+   PP_Win *ppw = NULL;
+   Eina_List *l;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+
+   EINA_LIST_FOREACH(_pp_wins, l, ppw)
+     {
+        if (ppw->ec == ec)
+          return ppw;
+     }
+
+   return NULL;
+}
+
+static Eina_Bool
+_cb_pong_check(void *data)
+{
+   PP_Win *ppw = (PP_Win *)data;
+   E_Client* ec = ppw->ec;
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ppw->ping_sent, ECORE_CALLBACK_CANCEL);
+
+   ppw->t_pong_wait = NULL;
+   ppw->ping_sent = EINA_FALSE;
+
+   ELOGF("PP", "PONG CHK  | pid:%d name:%s ping_ok:%u",
+         ec, ec->netwm.pid, ec->icccm.name, ec->ping_ok);
+
+   if (ec->ping_ok) return ECORE_CALLBACK_CANCEL;
+
+   /* TODO: kill the unresponsive client here */
+   ;;
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_ping_send(PP_Win *ppw)
+{
+   E_Client *ec = ppw->ec;
+
+   /* if ping is already sent, do nothing */
+   if (ppw->t_pong_wait)
+     {
+        ELOGF("PP", "PING SKIP | pid:%d name:%s",
+              ec, ec->netwm.pid, ec->icccm.name);
+        return EINA_FALSE;
+     }
+
+   ELOGF("PP", "PING SENT | pid:%d name:%s",
+         ec, ec->netwm.pid, ec->icccm.name);
+
+   ec->ping_ok = 0;
+   evas_object_smart_callback_call(ec->frame, "ping", NULL);
+
+   ppw->t_pong_wait = ecore_timer_add(PONG_WAIT_TIME,
+                                      _cb_pong_check,
+                                      ppw);
+   ppw->ping_sent = EINA_TRUE;
+
+   return EINA_TRUE;
+}
+
+static void
+_cb_client_mouse_down(void *data,
+                      Evas *e EINA_UNUSED,
+                      Evas_Object *o EINA_UNUSED,
+                      void *event)
+{
+   PP_Win *ppw = (PP_Win *)data;
+   E_Client *ec = ppw->ec;
+   Eina_Bool res;
+
+   if (!ec->visible) return;
+   if (e_client_util_ignored_get(ec)) return;
+   if (!evas_object_visible_get(ec->frame)) return;
+   if (ec->visibility.obscured == E_VISIBILITY_UNKNOWN ||
+       ec->visibility.obscured == E_VISIBILITY_PARTIALLY_OBSCURED) return;
+   if (evas_object_data_get(ec->frame, "comp_skip")) return;
+
+   /* send ping to visible top-level window */
+   res = _ping_send(ppw);
+   if (!res) return;
+
+   /* get a list of tizen remote surface providers which is used in given ec */
+   if (!ec->remote_surface.consumer) return;
+
+   Eina_List *tzrs_provs, *l;
+   E_Client *prov_ec;
+   PP_Win *prov_ppw;
+
+   tzrs_provs = e_comp_wl_remote_surface_providers_get(ec);
+   if (!tzrs_provs) return;
+
+   EINA_LIST_FOREACH(tzrs_provs, l, prov_ec)
+     {
+        /* check remote surface provider */
+        if (!prov_ec->remote_surface.provider) continue;
+        if (prov_ec->comp_data->remote_surface.onscreen_parent != ec) continue;
+        if (prov_ec->visible) continue;
+        if (evas_object_visible_get(prov_ec->frame)) continue;
+        if (prov_ec->comp_data->mapped) continue;
+
+        prov_ppw = _pp_win_find(prov_ec);
+        if (!prov_ppw)
+          prov_ppw = _pp_win_add(prov_ec);
+
+        /* send ping to invisible tizen remote surface provider */
+        _ping_send(prov_ppw);
+     }
+
+   eina_list_free(tzrs_provs);
+}
+
+static Eina_Bool
+_cb_client_show(void *data EINA_UNUSED,
+                int type EINA_UNUSED,
+                void *event)
+{
+   PP_Win *ppw = NULL;
+   E_Event_Client *ev = (E_Event_Client *)event;
+   E_Client *ec = ev->ec;
+
+   ppw = _pp_win_find(ec);
+   if (ppw) return ECORE_CALLBACK_PASS_ON;
+
+   ppw = _pp_win_add(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ppw, ECORE_CALLBACK_PASS_ON);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_cb_client_hide(void *data EINA_UNUSED,
+                int type EINA_UNUSED,
+                void *event)
+{
+   PP_Win *ppw = NULL;
+   E_Event_Client *ev = (E_Event_Client *)event;
+   E_Client *ec = ev->ec;
+
+   ppw = _pp_win_find(ec);
+   if (!ppw) return ECORE_CALLBACK_PASS_ON;
+
+   _pp_wins = eina_list_remove(_pp_wins, ppw);
+   _pp_win_del(ppw);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_cb_client_del(void *data EINA_UNUSED,
+               int type EINA_UNUSED,
+               void *event)
+{
+   PP_Win *ppw = NULL;
+   E_Event_Client *ev = (E_Event_Client *)event;
+   E_Client *ec = ev->ec;
+
+   ppw = _pp_win_find(ec);
+   if (!ppw) return ECORE_CALLBACK_PASS_ON;
+
+   _pp_wins = eina_list_remove(_pp_wins, ppw);
+   _pp_win_del(ppw);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+EINTERN void
+e_mod_pol_pingpong_init(void)
+{
+   if (!e_mod_pol_conf_use_pingpoing_policy_get()) return;
+
+   E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_SHOW,   _cb_client_show, NULL);
+   E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_HIDE,   _cb_client_hide, NULL);
+   E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_REMOVE, _cb_client_del,  NULL);
+}
+
+EINTERN void
+e_mod_pol_pingpong_shutdown(void)
+{
+   if (!e_mod_pol_conf_use_pingpoing_policy_get()) return;
+
+   E_FREE_LIST(_pp_wins, _pp_win_del);
+   E_FREE_LIST(_handlers, ecore_event_handler_del);
+}
diff --git a/src/e_mod_pol_pingpong.h b/src/e_mod_pol_pingpong.h
new file mode 100644 (file)
index 0000000..2089b7e
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef E_MOD_POL_PINGPONG_H
+#define E_MOD_POL_PINGPONG_H
+
+EINTERN void e_mod_pol_pingpong_init(void);
+EINTERN void e_mod_pol_pingpong_shutdown(void);
+
+#endif