e_mod_ivi_home: use e_client api instead of evas_obj api
[platform/core/uifw/e-mod-tizen-wm-policy.git] / src / e_mod_ivi_home.c
1 #include "e_mod_main.h"
2 #include "e_mod_ivi_home.h"
3
4 typedef enum
5 {
6    IVI_HOME_SIZE_MODE_NONE,
7    IVI_HOME_SIZE_MODE_HALF,
8    IVI_HOME_SIZE_MODE_FULL,
9    IVI_HOME_SIZE_MODE_SMALL,
10 } IVI_Home_Size_Mode;
11
12 typedef struct
13 {
14    E_Client *ec;
15    IVI_Home_Size_Mode ivi_policy_mode;
16    Eina_Bool ivi_policy_state;
17 } IVI_Home_Client;
18
19 typedef enum
20 {
21    IVI_HOME_HINT_SIZE_MODE,
22 } IVI_Home_Hint;
23
24 static const char *ivi_home_hint_names[] =
25 {
26    "wm.policy.ivi.win.size.mode",
27 };
28
29 static Eina_Hash *hash_clients = NULL;
30 static Eina_List *hooks_ec = NULL;
31 static E_Client *ivi_clients[2] = {NULL, NULL};
32
33 static void
34 _ivi_home_policy_pre(IVI_Home_Client *ic, IVI_Home_Size_Mode mode, int slot)
35 {
36    E_Client *ec;
37    int zx, zy, zw, zh;
38
39    ec = ic->ec;
40
41    if (ec->desk->visible)
42      e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
43    else
44      {
45         zx = ec->zone->x;
46         zy = ec->zone->y;
47         zw = ec->zone->w;
48         zh = ec->zone->h;
49      }
50
51    ic->ivi_policy_mode = mode;
52    switch (mode)
53      {
54       case IVI_HOME_SIZE_MODE_FULL:
55          if (slot)
56            {
57               ec->x = ec->client.x = zx;
58               ec->y = ec->client.y = zy;
59               ec->w = ec->client.w = zw;
60               ec->h = ec->client.h = zh;
61            }
62          break;;
63       case IVI_HOME_SIZE_MODE_SMALL:
64          if (!!!slot)
65            {
66               ec->x = ec->client.x = zx;
67               ec->y = ec->client.y = zy;
68               ec->w = ec->client.w = zw;
69               ec->h = ec->client.h = zh * 9 / 10;
70            }
71          else
72            {
73               ec->x = ec->client.x = zx;
74               ec->y = ec->client.y = zh - zh / 10;
75               ec->w = ec->client.w = zw;
76               ec->h = ec->client.h = zh / 10;
77            }
78          break;
79       case IVI_HOME_SIZE_MODE_HALF:
80       case IVI_HOME_SIZE_MODE_NONE:
81       default:
82          ic->ivi_policy_mode = IVI_HOME_SIZE_MODE_HALF;
83          if (!!!slot)
84            {
85               ec->x = ec->client.x = zx;
86               ec->y = ec->client.y = zy;
87            }
88          else
89            {
90               ec->x = ec->client.x = zx;
91               ec->y = ec->client.y = zh / 2;
92            }
93          ec->w = ec->client.w = zw;
94          ec->h = ec->client.h = zh / 2;
95      }
96
97    EC_CHANGED(ec);
98 }
99
100 static void
101 _ivi_home_policy_apply(IVI_Home_Client *ic, int slot)
102 {
103    E_Client *ec;
104
105    if (!ic) return;
106    if (ic->ivi_policy_state) return;
107
108    ic->ivi_policy_state = EINA_TRUE;
109    ec = ic->ec;
110
111    ivi_clients[slot] = ec;
112
113    /* skip hooks of e_remeber for eval_pre_post_fetch and eval_post_new_client */
114    ec->internal_no_remember = 1;
115
116    if (!ec->borderless)
117      {
118         ec->borderless = 1;
119         ec->border.changed = 1;
120         EC_CHANGED(ec);
121      }
122
123    _ivi_home_policy_pre(ic, ic->ivi_policy_mode, slot);
124    evas_object_move(ec->frame, ec->x, ec->y);
125    evas_object_resize(ec->frame, ec->w, ec->h);
126    ec->placed = EINA_TRUE;
127    e_client_visibility_calculate();
128
129    /* do not allow client to change these properties */
130    ec->lock_user_location = 1;
131    ec->lock_client_location = 1;
132    ec->lock_user_size = 1;
133    ec->lock_client_size = 1;
134    ec->lock_user_shade = 1;
135    ec->lock_client_shade = 1;
136    ec->lock_user_maximize = 1;
137    ec->lock_client_maximize = 1;
138    ec->lock_user_fullscreen = 1;
139    ec->lock_client_fullscreen = 1;
140    ec->skip_fullscreen = 1;
141 }
142
143 static void
144 _ivi_home_policy_change(IVI_Home_Client *ic, IVI_Home_Size_Mode mode, int slot)
145 {
146    E_Client *ec;
147
148    if (!ic) return;
149    if (!ic->ec) return;
150    if (ic->ivi_policy_mode == mode) return;
151
152    ec = ic->ec;
153    if (!ic->ivi_policy_state)
154      {
155         _ivi_home_policy_apply(ic, slot);
156         return;
157      }
158
159    _ivi_home_policy_pre(ic, mode, slot);
160    evas_object_move(ec->frame, ec->x, ec->y);
161    evas_object_resize(ec->frame, ec->w, ec->h);
162    ec->placed = EINA_TRUE;
163    e_client_visibility_calculate();
164 }
165
166 static Eina_Bool
167 _ivi_home_client_is_ivi_home(E_Client *ec)
168 {
169    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
170    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
171
172    if (!e_util_strcmp("ivi-home", ec->icccm.window_role))
173      return EINA_TRUE;
174
175    return EINA_FALSE;
176 }
177
178 static Eina_Bool
179 _ivi_home_client_is_ivi_navi(E_Client *ec)
180 {
181    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
182    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
183
184    if (!e_util_strcmp("ivi-navi", ec->icccm.window_role))
185      return EINA_TRUE;
186
187    return EINA_FALSE;
188 }
189
190 static void
191 _ivi_home_size_mode_set(E_Client *ec, IVI_Home_Size_Mode mode)
192 {
193    IVI_Home_Client *ic;
194
195    if (!_ivi_home_client_is_ivi_home(ec)) return;
196
197    ic = eina_hash_find(hash_clients, &ec);
198    _ivi_home_policy_change(ic, mode, 1);
199
200    if (ivi_clients[0] && _ivi_home_client_is_ivi_navi(ivi_clients[0]))
201      {
202         ic = eina_hash_find(hash_clients, &ivi_clients[0]);
203         _ivi_home_policy_change(ic, mode, 0);
204      }
205 }
206
207 static void
208 _ivi_home_cb_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
209 {
210    IVI_Home_Client *ic;
211
212    if (e_object_is_del(E_OBJECT(ec))) return;
213
214    ic = eina_hash_find(hash_clients, &ec);
215    if (ic) return;
216
217    ic = E_NEW(IVI_Home_Client, 1);
218    if (!ic) return;
219    ic->ec = ec;
220
221    eina_hash_add(hash_clients, &ec, ic);
222 }
223
224 static void
225 _ivi_home_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
226 {
227    if (ivi_clients[0] == ec)
228      ivi_clients[0] = NULL;
229    else if (ivi_clients[1] == ec)
230      ivi_clients[1] = NULL;
231
232    eina_hash_del_by_key(hash_clients, &ec);
233 }
234
235 static void
236 _ivi_home_cb_hook_aux_hint_changed(void *d EINA_UNUSED, E_Client *ec)
237 {
238    E_Comp_Wl_Client_Data *cdata;
239    Eina_List *l;
240    E_Comp_Wl_Aux_Hint *hint;
241
242    if (EINA_UNLIKELY(!ec))
243      return;
244
245    cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
246    if (cdata)
247      {
248         EINA_LIST_FOREACH(cdata->aux_hint.hints, l, hint)
249           {
250              if (!strcmp(hint->hint, ivi_home_hint_names[IVI_HOME_HINT_SIZE_MODE]))
251                {
252                   if (hint->deleted)
253                     _ivi_home_size_mode_set(ec, IVI_HOME_SIZE_MODE_NONE);
254                   else if (!strcmp(hint->val, "half"))
255                     _ivi_home_size_mode_set(ec, IVI_HOME_SIZE_MODE_HALF);
256                   else if (!strcmp(hint->val, "full"))
257                     _ivi_home_size_mode_set(ec, IVI_HOME_SIZE_MODE_FULL);
258                   else if (!strcmp(hint->val, "small"))
259                     _ivi_home_size_mode_set(ec, IVI_HOME_SIZE_MODE_SMALL);
260                }
261           }
262      }
263 }
264
265 static void
266 _ivi_home_cb_hook_role_changed(void *d EINA_UNUSED, E_Client *ec)
267 {
268    if (e_object_is_del(E_OBJECT(ec))) return;
269
270    if (_ivi_home_client_is_ivi_home(ec))
271      {
272         e_policy_allow_user_geometry_set(ec, EINA_TRUE);
273         e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
274      }
275    else if (_ivi_home_client_is_ivi_navi(ec))
276      {
277         e_policy_allow_user_geometry_set(ec, EINA_TRUE);
278         e_client_layer_set(ec, E_LAYER_CLIENT_BELOW);
279      }
280 }
281
282 static void
283 _ivi_home_cb_hook_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec)
284 {
285    IVI_Home_Client *ic;
286
287    if (e_object_is_del(E_OBJECT(ec))) return;
288    if ((ec->new_client) && (!e_pixmap_usable_get(ec->pixmap))) return;
289
290    ic = eina_hash_find(hash_clients, &ec);
291    if (!ic) return;
292
293    if (_ivi_home_client_is_ivi_home(ec))
294      {
295         _ivi_home_policy_apply(ic, 1);
296      }
297    else if (_ivi_home_client_is_ivi_navi(ec))
298      {
299         _ivi_home_policy_apply(ic, 0);
300      }
301 }
302
303 static void
304 e_mod_ivi_home_aux_hint_init(void)
305 {
306    int i, n;
307    n = (sizeof(ivi_home_hint_names) / sizeof(char *));
308
309    for (i = 0; i < n; i++)
310      {
311         e_hints_aux_hint_supported_add(ivi_home_hint_names[i]);
312      }
313 }
314
315 static void
316 _ivi_home_cb_client_data_free(void *data)
317 {
318    free(data);
319 }
320
321 EINTERN void
322 e_mod_ivi_home_init(void)
323 {
324    hash_clients = eina_hash_pointer_new(_ivi_home_cb_client_data_free);
325
326    E_CLIENT_HOOK_APPEND(hooks_ec, E_CLIENT_HOOK_NEW_CLIENT, _ivi_home_cb_hook_client_new, NULL);
327    E_CLIENT_HOOK_APPEND(hooks_ec, E_CLIENT_HOOK_DEL, _ivi_home_cb_hook_client_del, NULL);
328    E_CLIENT_HOOK_APPEND(hooks_ec, E_CLIENT_HOOK_AUX_HINT_CHANGE, _ivi_home_cb_hook_aux_hint_changed, NULL);
329    E_CLIENT_HOOK_APPEND(hooks_ec, E_CLIENT_HOOK_WINDOW_ROLE_CHANGE, _ivi_home_cb_hook_role_changed, NULL);
330    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_POST_FETCH,     _ivi_home_cb_hook_eval_post_fetch, NULL);
331
332    e_mod_ivi_home_aux_hint_init();
333 }
334
335 EINTERN void
336 e_mod_ivi_home_shutdown(void)
337 {
338    E_FREE_LIST(hooks_ec, e_client_hook_del);
339    E_FREE_FUNC(hash_clients, eina_hash_free);
340 }