e_mod_pol_pingpong: code cleanup
[platform/core/uifw/e-mod-tizen-wm-policy.git] / src / e_mod_pol_pingpong.c
1 #include <e.h>
2 #include "e_mod_main.h"
3 #include "e_mod_pol_pingpong.h"
4
5 #define PONG_WAIT_TIME 2.0
6
7 typedef struct _PP_Win
8 {
9    E_Client    *ec;
10    Ecore_Timer *t_pong_wait;
11    Eina_Bool    ping_sent;
12 } PP_Win;
13
14 static Eina_List *_handlers = NULL;
15 static Eina_List *_pp_wins  = NULL;
16
17 static void _cb_client_mouse_down(void *data, Evas *e, Evas_Object *o, void *event);
18
19 static PP_Win *
20 _pp_win_add(E_Client *ec)
21 {
22    PP_Win *ppw;
23
24    ppw = E_NEW(PP_Win, 1);
25    EINA_SAFETY_ON_NULL_RETURN_VAL(ppw, NULL);
26
27    ppw->ec = ec;
28
29    evas_object_event_callback_add(ec->frame,
30                                   EVAS_CALLBACK_MOUSE_DOWN,
31                                   _cb_client_mouse_down,
32                                   ppw);
33
34    _pp_wins = eina_list_append(_pp_wins, ppw);
35
36    return ppw;
37 }
38
39 static void
40 _pp_win_del(PP_Win *ppw)
41 {
42    if (ppw->t_pong_wait)
43      ecore_timer_del(ppw->t_pong_wait);
44
45    evas_object_event_callback_del(ppw->ec->frame,
46                                   EVAS_CALLBACK_MOUSE_DOWN,
47                                   _cb_client_mouse_down);
48    E_FREE(ppw);
49 }
50
51 static PP_Win *
52 _pp_win_find(E_Client *ec)
53 {
54    PP_Win *ppw = NULL;
55    Eina_List *l;
56
57    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
58
59    EINA_LIST_FOREACH(_pp_wins, l, ppw)
60      {
61         if (ppw->ec == ec)
62           return ppw;
63      }
64
65    return NULL;
66 }
67
68 static void
69 _pp_win_remove(E_Client *ec)
70 {
71    PP_Win *ppw = NULL;
72
73    ppw = _pp_win_find(ec);
74    if (!ppw) return;
75
76    _pp_wins = eina_list_remove(_pp_wins, ppw);
77    _pp_win_del(ppw);
78 }
79
80 static Eina_Bool
81 _cb_pong_check(void *data)
82 {
83    PP_Win *ppw = (PP_Win *)data;
84    E_Client* ec = ppw->ec;
85
86    EINA_SAFETY_ON_FALSE_RETURN_VAL(ppw->ping_sent, ECORE_CALLBACK_CANCEL);
87
88    ppw->t_pong_wait = NULL;
89    ppw->ping_sent = EINA_FALSE;
90
91    ELOGF("PP", "PONG CHK  | pid:%d name:%s ping_ok:%u",
92          ec, ec->netwm.pid, ec->icccm.name, ec->ping_ok);
93
94    if (ec->ping_ok) return ECORE_CALLBACK_CANCEL;
95
96    /* TODO: kill the unresponsive client here */
97    ;;
98
99    return ECORE_CALLBACK_CANCEL;
100 }
101
102 static Eina_Bool
103 _ping_send(PP_Win *ppw)
104 {
105    E_Client *ec = ppw->ec;
106
107    /* if ping is already sent, do nothing */
108    if (ppw->t_pong_wait)
109      {
110         ELOGF("PP", "PING SKIP | pid:%d name:%s",
111               ec, ec->netwm.pid, ec->icccm.name);
112         return EINA_FALSE;
113      }
114
115    ELOGF("PP", "PING SENT | pid:%d name:%s",
116          ec, ec->netwm.pid, ec->icccm.name);
117
118    ec->ping_ok = 0;
119    evas_object_smart_callback_call(ec->frame, "ping", NULL);
120
121    ppw->t_pong_wait = ecore_timer_add(PONG_WAIT_TIME,
122                                       _cb_pong_check,
123                                       ppw);
124    ppw->ping_sent = EINA_TRUE;
125
126    return EINA_TRUE;
127 }
128
129 static void
130 _cb_client_mouse_down(void *data,
131                       Evas *e EINA_UNUSED,
132                       Evas_Object *o EINA_UNUSED,
133                       void *event)
134 {
135    PP_Win *ppw = (PP_Win *)data;
136    E_Client *ec = ppw->ec;
137    Eina_Bool res;
138
139    if (!ec->visible) return;
140    if (e_client_util_ignored_get(ec)) return;
141    if (!evas_object_visible_get(ec->frame)) return;
142    if (ec->visibility.obscured == E_VISIBILITY_UNKNOWN ||
143        ec->visibility.obscured == E_VISIBILITY_PARTIALLY_OBSCURED) return;
144    if (evas_object_data_get(ec->frame, "comp_skip")) return;
145
146    /* send ping to visible top-level window */
147    res = _ping_send(ppw);
148    if (!res) return;
149
150    /* get a list of tizen remote surface providers which is used in given ec */
151    if (!ec->remote_surface.consumer) return;
152
153    Eina_List *tzrs_provs, *l;
154    E_Client *prov_ec;
155    PP_Win *prov_ppw;
156
157    tzrs_provs = e_comp_wl_remote_surface_providers_get(ec);
158    if (!tzrs_provs) return;
159
160    EINA_LIST_FOREACH(tzrs_provs, l, prov_ec)
161      {
162         /* check remote surface provider */
163         if (!prov_ec->remote_surface.provider) continue;
164         if (prov_ec->comp_data->remote_surface.onscreen_parent != ec) continue;
165         if (prov_ec->visible) continue;
166         if (evas_object_visible_get(prov_ec->frame)) continue;
167         if (prov_ec->comp_data->mapped) continue;
168
169         prov_ppw = _pp_win_find(prov_ec);
170         if (!prov_ppw)
171           prov_ppw = _pp_win_add(prov_ec);
172
173         /* send ping to invisible tizen remote surface provider */
174         _ping_send(prov_ppw);
175      }
176
177    eina_list_free(tzrs_provs);
178 }
179
180 static Eina_Bool
181 _cb_client_show(void *data EINA_UNUSED,
182                 int type EINA_UNUSED,
183                 void *event)
184 {
185    PP_Win *ppw = NULL;
186    E_Event_Client *ev = (E_Event_Client *)event;
187    E_Client *ec = ev->ec;
188
189    ppw = _pp_win_find(ec);
190    if (ppw) return ECORE_CALLBACK_PASS_ON;
191
192    ppw = _pp_win_add(ec);
193    EINA_SAFETY_ON_NULL_RETURN_VAL(ppw, ECORE_CALLBACK_PASS_ON);
194
195    return ECORE_CALLBACK_PASS_ON;
196 }
197
198 static Eina_Bool
199 _cb_client_hide(void *data EINA_UNUSED,
200                 int type EINA_UNUSED,
201                 void *event)
202 {
203    E_Event_Client *ev = (E_Event_Client *)event;
204
205    if (ev->ec)
206      _pp_win_remove(ev->ec);
207
208    return ECORE_CALLBACK_PASS_ON;
209 }
210
211 static Eina_Bool
212 _cb_client_del(void *data EINA_UNUSED,
213                int type EINA_UNUSED,
214                void *event)
215 {
216    E_Event_Client *ev = (E_Event_Client *)event;
217
218    if (ev->ec)
219      _pp_win_remove(ev->ec);
220
221    return ECORE_CALLBACK_PASS_ON;
222 }
223
224 EINTERN void
225 e_mod_pol_pingpong_init(void)
226 {
227    if (!e_mod_pol_conf_use_pingpoing_policy_get()) return;
228
229    E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_SHOW,   _cb_client_show, NULL);
230    E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_HIDE,   _cb_client_hide, NULL);
231    E_LIST_HANDLER_APPEND(_handlers, E_EVENT_CLIENT_REMOVE, _cb_client_del,  NULL);
232 }
233
234 EINTERN void
235 e_mod_pol_pingpong_shutdown(void)
236 {
237    if (!e_mod_pol_conf_use_pingpoing_policy_get()) return;
238
239    E_FREE_LIST(_pp_wins, _pp_win_del);
240    E_FREE_LIST(_handlers, ecore_event_handler_del);
241 }