split_screen_manager: check desk_area is enabled before assign client to region
[platform/core/uifw/e-mod-tizen-wm-policy.git] / src / splitscreen / e_mod_split_screen_manager.c
1 #include "e.h"
2 #include "e_mod_split_screen_manager_log.h"
3 #include "e_mod_split_screen_manager.h"
4 #include "e_mod_split_screen_region.h"
5 #include "e_mod_appinfo_ext.h"
6
7 typedef Eina_Bool (*E_Mod_Split_Screen_Manager_Hint_Func)(E_Client *ec, const char *name, const char *value);
8 struct _E_Mod_Split_Screen_Manager_Hint_Handler
9 {
10    int type;
11    const char *name;
12    E_Mod_Split_Screen_Manager_Hint_Func func;
13 };
14
15 typedef struct _E_Mod_Split_Screen_Manager_Hint_Handler E_Mod_Split_Screen_Manager_Hint_Handler;
16
17 enum _E_Mod_Split_Screen_Manager_Hint_Type
18 {
19    E_MOD_SPLIT_SCREEN_MANAGER_HINT_ASSIGN_REGION = 0,
20    E_MOD_SPLIT_SCREEN_MANAGER_HINT_LAUNCHER_ROLE_SET,
21    E_MOD_SPLIT_SCREEN_MANAGER_HINT_ASSIGN_REGION_SUB1,
22    E_MOD_SPLIT_SCREEN_MANAGER_HINT_ASSIGN_REGION_SUB2,
23    E_MOD_SPLIT_SCREEN_MANAGER_HINT_ACTIVATE,
24    E_MOD_SPLIT_SCREEN_MANAGER_HINT_DEACTIVATE,
25    E_MOD_SPLIT_SCREEN_MANAGER_HINT_MAX,
26 };
27
28 static Eina_List *_e_mod_split_screen_manager_ec_hook_handlers = NULL;
29 static Eina_List *_e_mod_split_screen_manager_ec_event_handlers = NULL;
30 static Eina_List *_e_mod_split_screen_manager_desk_area_hook_handlers = NULL;
31 static Eina_List *_e_mod_split_screen_manager_zone_hook_handlers = NULL;
32
33 static Eina_List *_e_mod_split_screen_region_list = NULL;
34 static E_Client *_e_mod_split_screen_launcher_ec = NULL;
35
36 /* e_client hooks */
37 static void _e_mod_split_screen_manager_cb_hook_aux_hint_change(void *data, E_Client *ec);
38
39 /* e_client events */
40 static Eina_Bool _e_mod_split_screen_manager_cb_ec_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
41 static Eina_Bool _e_mod_split_screen_manager_cb_ec_remove(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
42
43 /* Aux hint handlers */
44 static Eina_Bool     _e_mod_split_screen_manager_hint_launcher_role_set(E_Client *ec, const char *name, const char *value);
45 static Eina_Bool     _e_mod_split_screen_manager_hint_assign_region(E_Client *ec, const char *name, const char *value);
46 static Eina_Bool     _e_mod_split_screen_manager_hint_assign_region_sub1(E_Client *ec, const char *name, const char *value);
47 static Eina_Bool     _e_mod_split_screen_manager_hint_assign_region_sub2(E_Client *ec, const char *name, const char *value);
48 static Eina_Bool     _e_mod_split_screen_manager_hint_activate(E_Client *ec, const char *name, const char *value);
49 static Eina_Bool     _e_mod_split_screen_manager_hint_deactivate(E_Client *ec, const char *name, const char *value);
50
51 /* e_mod_split_screen_manager internal functions */
52 static void          _e_mod_split_screen_manager_client_manager_role_set(E_Client *ec, Eina_Bool set);
53 static Eina_Bool     _e_mod_split_screen_activate(E_Zone *zone);
54 static Eina_Bool     _e_mod_split_screen_deactivate(E_Zone *zone);
55 static void          _e_mod_split_screen_launcher_ec_set(E_Client *ec);
56 static E_Client *    _e_mod_split_screen_launcher_ec_get(void);
57 static E_Mod_Split_Screen_Region *_e_mod_split_screen_manager_find_region_by_name(const char *name);
58 static E_Mod_Split_Screen_Region *_e_mod_split_screen_manager_find_region_by_desk_area(E_Desk_Area *eda);
59 static void          _e_mod_split_screen_manager_appid_assign(E_Mod_Split_Screen_Region *emssr, const char *appid);
60 static Eina_Bool     _e_mod_split_screen_manager_ec_assign_to_region_name(E_Client *ec, const char *region_name);
61 static Eina_Bool     _e_mod_split_screen_manager_ec_relocate(E_Client *ec);
62 static Eina_Bool     _e_mod_split_screen_manager_ec_relocate_to_region(E_Client *ec, E_Mod_Split_Screen_Region *emssr);
63
64 /* initializer */
65 static Eina_Bool _e_mod_split_screen_manager_handler_init(void);
66 static Eina_Bool _e_mod_split_screen_manager_aux_hint_handler_init(void);
67 static void      _e_mod_split_screen_manager_handler_shutdown(void);
68 static void      _e_mod_split_screen_manager_aux_hint_handler_shutdown(void);
69 static Eina_Bool _e_mod_split_screen_manager_region_init(void);
70 static void      _e_mod_split_screen_manager_region_shutdown(void);
71
72 static const E_Mod_Split_Screen_Manager_Hint_Handler _e_mod_split_screen_manager_hint_handler[] =
73 {
74      {E_MOD_SPLIT_SCREEN_MANAGER_HINT_ASSIGN_REGION, "wm.splitscreen.win.assign_region", _e_mod_split_screen_manager_hint_assign_region},
75      {E_MOD_SPLIT_SCREEN_MANAGER_HINT_LAUNCHER_ROLE_SET, "wm.splitscreen.win.launcher.role_set", _e_mod_split_screen_manager_hint_launcher_role_set},
76      {E_MOD_SPLIT_SCREEN_MANAGER_HINT_ASSIGN_REGION_SUB1, "wm.splitscreen.win.split_screen_manager.assign_region.sub1", _e_mod_split_screen_manager_hint_assign_region_sub1},
77      {E_MOD_SPLIT_SCREEN_MANAGER_HINT_ASSIGN_REGION_SUB2, "wm.splitscreen.win.split_screen_manager.assign_region.sub2", _e_mod_split_screen_manager_hint_assign_region_sub2},
78      {E_MOD_SPLIT_SCREEN_MANAGER_HINT_ACTIVATE, "wm.splitscreen.win.split_screen_manager.activate", _e_mod_split_screen_manager_hint_activate},
79      {E_MOD_SPLIT_SCREEN_MANAGER_HINT_DEACTIVATE, "wm.splitscreen.win.split_screen_manager.deactivate", _e_mod_split_screen_manager_hint_deactivate},
80      {E_MOD_SPLIT_SCREEN_MANAGER_HINT_MAX, NULL, NULL},
81 };
82
83 /* Hook handlers */
84 static void
85 _e_mod_split_screen_manager_cb_hook_aux_hint_change(void *data, E_Client *ec)
86 {
87    const char *hint, *val;
88
89    if (!ec)
90      {
91         SSMINF("ec is NULL", NULL);
92         return;
93      }
94
95    for (int i=0 ; i<E_MOD_SPLIT_SCREEN_MANAGER_HINT_MAX ; i++)
96      {
97         hint = _e_mod_split_screen_manager_hint_handler[i].name;
98         val = e_hints_aux_hint_value_get(ec, hint);
99         if (!val) continue;
100
101         _e_mod_split_screen_manager_hint_handler[i].func(ec, hint, val);
102      }
103
104    return;
105 }
106
107 static void
108 _e_mod_split_screen_manager_cb_hook_eval_fetch(void *data, E_Client *ec)
109 {
110    if (!ec)
111      {
112         SSMINF("ec is NULL", NULL);
113         return;
114      }
115
116    if (!ec->desk->desk_area.enable) return;
117
118    // TODO: FIX blinking issue while launching child window
119    _e_mod_split_screen_manager_ec_relocate(ec);
120
121    return;
122 }
123
124 static void
125 _e_mod_split_screen_manager_cb_hook_assign_appid(void *data EINA_UNUSED, E_Desk_Area *eda, void *appid_ptr)
126 {
127    E_Mod_Split_Screen_Region *emssr;
128    Eina_Stringshare *appid;
129
130    EINA_SAFETY_ON_NULL_RETURN(eda);
131    EINA_SAFETY_ON_NULL_RETURN(appid_ptr);
132
133    appid = eina_stringshare_add(appid_ptr);
134    emssr = _e_mod_split_screen_manager_find_region_by_desk_area(eda);
135    if (!emssr)
136      {
137         SSMERR("Failed to find region for desk area %p", NULL, eda);
138         return;
139      }
140
141    _e_mod_split_screen_manager_appid_assign(emssr, appid);
142
143    return;
144 }
145
146 static void
147 _e_mod_split_screen_manager_cb_hook_activate(void *data, E_Zone *zone)
148 {
149    if (!zone) return;
150    _e_mod_split_screen_activate(zone);
151 }
152
153 static void
154 _e_mod_split_screen_manager_cb_hook_deactivate(void *data, E_Zone *zone)
155 {
156    if (!zone) return;
157    _e_mod_split_screen_deactivate(zone);
158 }
159
160
161 /* e_client events */
162 static Eina_Bool
163 _e_mod_split_screen_manager_cb_ec_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
164 {
165    E_Event_Client *ev;
166
167    ev = event;
168    if (!ev) return ECORE_CALLBACK_PASS_ON;
169
170    if (!ev->ec->desk->desk_area.enable) return ECORE_CALLBACK_PASS_ON;
171
172    _e_mod_split_screen_manager_ec_relocate(ev->ec);
173
174    return ECORE_CALLBACK_PASS_ON;
175 }
176
177 static Eina_Bool
178 _e_mod_split_screen_manager_cb_ec_remove(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
179 {
180    E_Event_Client *ev;
181
182    ev = event;
183    if (!ev) return ECORE_CALLBACK_PASS_ON;
184
185    e_mod_split_screen_region_ec_dismiss(ev->ec);
186
187    return ECORE_CALLBACK_PASS_ON;
188 }
189
190 /* Aux hint handlers */
191 static Eina_Bool
192 _e_mod_split_screen_manager_hint_launcher_role_set(E_Client *ec, const char *name, const char *value)
193 {
194    if (!strncmp(value, "1", 1))
195      {
196         _e_mod_split_screen_manager_client_manager_role_set(ec, EINA_TRUE);
197      }
198    else
199      {
200         _e_mod_split_screen_manager_client_manager_role_set(ec, EINA_FALSE);
201      }
202
203    return EINA_TRUE;
204 }
205
206 static Eina_Bool
207 _e_mod_split_screen_manager_hint_assign_region(E_Client *ec, const char *name, const char *value)
208 {
209    E_Mod_Split_Screen_Region *emssr;
210    Eina_Stringshare *appid;
211
212    char _region_name[10] = {0,};
213    char _appid[255] = {0,};
214
215    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
216
217    // hint value format: region_name/appid
218    sscanf(value, "%[^/]/%s", _region_name, _appid);
219    SSMINF("client appid(%s) -> assign to region:%s", ec, _appid, _region_name);
220
221    if ((strlen(_region_name) <= 0) || strlen(_region_name) > 10)
222      {
223         SSMERR("invalid region name:%s", ec, _region_name);
224         return EINA_FALSE;
225      }
226
227    if ((strlen(_appid) <= 0) || (strlen(_appid) > 255))
228      {
229         SSMERR("invalid app id:%s", ec, _appid);
230         return EINA_FALSE;
231      }
232
233    emssr = _e_mod_split_screen_manager_find_region_by_name(_region_name);
234    if (!emssr)
235      {
236         SSMERR("invalid region name:%s", ec, _region_name);
237         return EINA_FALSE;
238      }
239
240    appid = eina_stringshare_add(_appid);
241
242    _e_mod_split_screen_manager_appid_assign(emssr, appid);
243
244    return EINA_TRUE;
245 }
246
247 static Eina_Bool
248 _e_mod_split_screen_manager_hint_assign_region_sub1(E_Client *ec, const char *name, const char *value)
249 {
250    E_Mod_Split_Screen_Region *emssr;
251    Eina_Stringshare *appid;
252
253    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
254
255    if ((strlen(value) <= 0) || strlen(value) > 255)
256      {
257         SSMERR("invalid app id:%s", ec, value);
258         return EINA_FALSE;
259      }
260
261    appid = eina_stringshare_add(value);
262
263    emssr = _e_mod_split_screen_manager_find_region_by_name("sub1");
264    if (!emssr)
265      {
266         SSMERR("invalid region name:%s", ec, "sub1");
267         return EINA_FALSE;
268      }
269
270    _e_mod_split_screen_manager_appid_assign(emssr, appid);
271
272    return EINA_TRUE;
273 }
274
275 static Eina_Bool
276 _e_mod_split_screen_manager_hint_assign_region_sub2(E_Client *ec, const char *name, const char *value)
277 {
278    E_Mod_Split_Screen_Region *emssr;
279    Eina_Stringshare *appid;
280
281    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
282
283    if ((strlen(value) <= 0) || strlen(value) > 255)
284      {
285         SSMERR("invalid app id:%s", ec, value);
286         return EINA_FALSE;
287      }
288
289    appid = eina_stringshare_add(value);
290
291    emssr = _e_mod_split_screen_manager_find_region_by_name("sub2");
292    if (!emssr)
293      {
294         SSMERR("invalid region name:%s", ec, "sub2");
295         return EINA_FALSE;
296      }
297
298    _e_mod_split_screen_manager_appid_assign(emssr, appid);
299
300    return EINA_TRUE;
301 }
302
303 static Eina_Bool
304 _e_mod_split_screen_manager_hint_activate(E_Client *ec, const char *name, const char *value)
305 {
306    return _e_mod_split_screen_activate(e_zone_current_get());
307 }
308
309 static Eina_Bool
310 _e_mod_split_screen_manager_hint_deactivate(E_Client *ec, const char *name, const char *value)
311 {
312    return _e_mod_split_screen_deactivate(e_zone_current_get());
313 }
314
315 /* internal functions */
316
317 static void
318 _e_mod_split_screen_manager_client_manager_role_set(E_Client *ec, Eina_Bool set)
319 {
320    E_Desk *desk;
321
322    if (!ec) return;
323    if (ec->floating == set) return;
324
325    ec->floating = set;
326
327    if (ec->frame)
328      {
329         if (set)
330           {
331              _e_mod_split_screen_launcher_ec_set(ec);
332              ec->floating_saved_layer = ec->layer;
333              e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
334              ec->netwm.type = E_WINDOW_TYPE_UTILITY;
335
336              desk = e_desk_current_get(e_zone_current_get());
337              if (desk && desk->desk_area.enable)
338                _e_mod_split_screen_manager_ec_assign_to_region_name(ec, "above");
339           }
340         else
341           {
342              e_client_layer_set(ec, ec->floating_saved_layer);
343              ec->netwm.type = E_WINDOW_TYPE_NORMAL;
344              e_mod_split_screen_region_ec_dismiss(ec);
345           }
346      }
347
348    e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
349    e_comp_object_dirty(ec->frame);
350    e_comp_object_render(ec->frame);
351
352    EC_CHANGED(ec);
353 }
354
355 static Eina_Bool
356 _e_mod_split_screen_activate(E_Zone *zone)
357 {
358    E_Desk *desk;
359    E_Client *ec, *launcher;
360    Eina_Bool ret = EINA_FALSE;
361
362    SSMINF("ACTIVATE split screen", NULL);
363
364    desk = e_desk_current_get(zone);
365    ret = e_desk_desk_area_enable(desk);
366
367    // relocate all e clients
368    E_CLIENT_FOREACH(ec)
369      {
370         _e_mod_split_screen_manager_ec_relocate(ec);
371      }
372
373    // launcher window must be above desk group to unobscured by other windows
374    launcher = _e_mod_split_screen_launcher_ec_get();
375    if (launcher)
376      _e_mod_split_screen_manager_ec_assign_to_region_name(launcher, "above");
377
378    return ret;
379 }
380
381 static Eina_Bool
382 _e_mod_split_screen_deactivate(E_Zone *zone)
383 {
384    E_Desk *desk;
385    Eina_Bool ret = EINA_FALSE;
386
387    SSMINF("DEACTIVATE split screen", NULL);
388
389    desk = e_desk_current_get(zone);
390    ret = e_desk_desk_area_disable(desk);
391
392    return ret;
393 }
394
395 static void
396 _e_mod_split_screen_launcher_ec_set(E_Client *ec)
397 {
398    _e_mod_split_screen_launcher_ec = ec;
399 }
400
401 static E_Client *
402 _e_mod_split_screen_launcher_ec_get(void)
403 {
404    return _e_mod_split_screen_launcher_ec;
405 }
406
407 static E_Mod_Split_Screen_Region *
408 _e_mod_split_screen_manager_find_region_by_name(const char *name)
409 {
410    E_Mod_Split_Screen_Region *emssr = NULL;
411    Eina_List *l;
412    const char *region_name;
413
414    EINA_LIST_FOREACH(_e_mod_split_screen_region_list, l, emssr)
415      {
416         region_name = e_mod_split_screen_region_name_get(emssr);
417         if (region_name && !strncmp(region_name, name, strlen(region_name))) break;
418      }
419
420    return emssr;
421 }
422
423 static E_Mod_Split_Screen_Region *
424 _e_mod_split_screen_manager_find_region_by_desk_area(E_Desk_Area *eda)
425 {
426    E_Mod_Split_Screen_Region *emssr = NULL;
427    Eina_List *l;
428
429    EINA_LIST_FOREACH(_e_mod_split_screen_region_list, l, emssr)
430      {
431         if (e_mod_split_screen_region_desk_area_get(emssr) == eda) break;
432      }
433
434    return emssr;
435 }
436
437 static void
438 _e_mod_split_screen_manager_appid_assign(E_Mod_Split_Screen_Region *emssr, const char *appid)
439 {
440    E_Mod_Split_Screen_Region *emssr_iter;
441    E_Client *ec;
442    Eina_Stringshare *region_name;
443    Eina_List *l;
444
445    // reassign AppID to Split screen region
446    EINA_LIST_FOREACH(_e_mod_split_screen_region_list, l, emssr_iter)
447      {
448         e_mod_split_screen_region_appid_dismiss(emssr_iter, appid);
449      }
450    e_mod_split_screen_region_appid_assign(emssr, appid);
451
452    // assign clients of appID to Split screen region
453    l = e_mod_appinfo_ext_find_clients_by_appid(appid);
454    EINA_LIST_FREE(l, ec)
455      {
456         e_mod_split_screen_region_ec_assign(emssr, ec);
457      }
458
459    region_name = e_mod_split_screen_region_name_get(emssr);
460    SSMINF("from now on, appid %s will be assign to region:%s", NULL, appid, region_name);
461 }
462
463 static Eina_Bool
464 _e_mod_split_screen_manager_util_client_special_check(E_Client *ec)
465 {
466    if (!ec) return EINA_FALSE;
467
468    if (_e_mod_split_screen_launcher_ec_get() == ec) return EINA_TRUE;
469
470    if ((e_policy_client_is_lockscreen(ec)) ||
471        (e_policy_client_is_keyboard(ec)) ||
472        (e_policy_client_is_keyboard_sub(ec)) ||
473        (e_policy_client_is_noti(ec)) ||
474        (e_policy_client_is_quickpanel(ec)) ||
475        (e_policy_client_is_volume(ec)) ||
476        (e_policy_client_is_cursor(ec)) ||
477        (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role)))
478      return EINA_TRUE;
479
480    return EINA_FALSE;
481 }
482
483 static Eina_Bool
484 _e_mod_split_screen_manager_ec_assign_to_region_name(E_Client *ec, const char *region_name)
485 {
486    E_Mod_Split_Screen_Region *emssr = NULL;
487
488    if (!ec) return ECORE_CALLBACK_PASS_ON;
489    if (!region_name) return ECORE_CALLBACK_PASS_ON;
490
491    emssr = _e_mod_split_screen_manager_find_region_by_name(region_name);
492    if (!emssr)
493      {
494         SSMERR("invalid region name:%s", ec, region_name);
495         return EINA_FALSE;
496      }
497    return e_mod_split_screen_region_ec_assign(emssr, ec);
498 }
499
500 static Eina_Bool
501 _e_mod_split_screen_manager_ec_relocate(E_Client *ec)
502 {
503    E_Mod_Split_Screen_Region *emssr = NULL;
504    E_Client *parent_ec = NULL;
505    Eina_Bool res = EINA_FALSE;
506    Eina_List *l;
507
508    if (!ec) return ECORE_CALLBACK_PASS_ON;
509
510    if (_e_mod_split_screen_manager_util_client_special_check(ec))
511      {
512         // special prupose windows.
513         _e_mod_split_screen_manager_ec_assign_to_region_name(ec, "above");
514         return EINA_TRUE;
515      }
516
517    EINA_LIST_FOREACH(_e_mod_split_screen_region_list, l, emssr)
518      {
519         res |= _e_mod_split_screen_manager_ec_relocate_to_region(ec, emssr);
520      }
521
522    if (!res)
523      {
524         // find the parent ec that is in the region
525         for (parent_ec = ec->parent;
526              parent_ec != NULL;
527              parent_ec = parent_ec->parent)
528           {
529              EINA_LIST_FOREACH(_e_mod_split_screen_region_list, l, emssr)
530                {
531                   res |= _e_mod_split_screen_manager_ec_relocate_to_region(parent_ec, emssr);
532                }
533           }
534      }
535
536    return res;
537 }
538
539 static Eina_Bool
540 _e_mod_split_screen_manager_ec_relocate_to_region(E_Client *ec, E_Mod_Split_Screen_Region *emssr)
541 {
542    Eina_Stringshare *appid;
543    Eina_List *appid_list, *l;
544    Eina_Bool res = EINA_FALSE;
545
546    if (!ec || !emssr) return EINA_FALSE;
547
548    appid_list = e_mod_split_screen_region_appid_list_get(emssr);
549
550    EINA_LIST_FOREACH(appid_list, l, appid)
551        if (ec->netwm.pid == e_mod_appinfo_ext_find_pid_by_appid(appid))
552          {
553             Eina_Stringshare *region_name = e_mod_split_screen_region_name_get(emssr);
554             SSMINF("client(%p):%s rearrange to region:%s",
555                    ec, ec, ec ? ec->icccm.name : "NULL", region_name);
556             res |= e_mod_split_screen_region_ec_assign(emssr, ec);
557          }
558
559    return res;
560 }
561
562 /* split screen initializer */
563
564 static Eina_Bool
565 _e_mod_split_screen_manager_handler_init(void)
566 {
567    E_Desk_Area_Hook *eda_hook;
568    E_Zone_Hook *ez_hook;
569
570    E_LIST_HANDLER_APPEND(_e_mod_split_screen_manager_ec_event_handlers, E_EVENT_CLIENT_ADD, _e_mod_split_screen_manager_cb_ec_add, NULL);
571    E_LIST_HANDLER_APPEND(_e_mod_split_screen_manager_ec_event_handlers, E_EVENT_CLIENT_REMOVE, _e_mod_split_screen_manager_cb_ec_remove, NULL);
572
573    E_LIST_HOOK_APPEND(_e_mod_split_screen_manager_ec_hook_handlers, E_CLIENT_HOOK_EVAL_FETCH, _e_mod_split_screen_manager_cb_hook_eval_fetch, NULL);
574
575    eda_hook = e_desk_area_hook_add(E_DESK_AREA_HOOK_SET_APPID, _e_mod_split_screen_manager_cb_hook_assign_appid, NULL);
576    if (eda_hook) _e_mod_split_screen_manager_desk_area_hook_handlers = eina_list_append(_e_mod_split_screen_manager_desk_area_hook_handlers, eda_hook);
577
578    ez_hook = e_zone_hook_add(E_ZONE_HOOK_SPLISCREEN_ACTIVATE, _e_mod_split_screen_manager_cb_hook_activate, NULL);
579    if (ez_hook) _e_mod_split_screen_manager_zone_hook_handlers = eina_list_append(_e_mod_split_screen_manager_zone_hook_handlers, ez_hook);
580
581    ez_hook = e_zone_hook_add(E_ZONE_HOOK_SPLISCREEN_DEACTIVATE, _e_mod_split_screen_manager_cb_hook_deactivate, NULL);
582    if (ez_hook) _e_mod_split_screen_manager_zone_hook_handlers = eina_list_append(_e_mod_split_screen_manager_zone_hook_handlers, ez_hook);
583
584    if (!_e_mod_split_screen_manager_ec_event_handlers ||
585        !_e_mod_split_screen_manager_ec_hook_handlers ||
586        !_e_mod_split_screen_manager_desk_area_hook_handlers)
587      return EINA_FALSE;
588
589    return EINA_TRUE;
590 }
591
592 static Eina_Bool
593 _e_mod_split_screen_manager_aux_hint_handler_init(void)
594 {
595    E_LIST_HOOK_APPEND(_e_mod_split_screen_manager_ec_hook_handlers, E_CLIENT_HOOK_AUX_HINT_CHANGE, _e_mod_split_screen_manager_cb_hook_aux_hint_change, NULL);
596
597    if (!_e_mod_split_screen_manager_ec_hook_handlers)
598      return EINA_FALSE;
599
600    for (int i=0 ; i<E_MOD_SPLIT_SCREEN_MANAGER_HINT_MAX ; i++)
601      {
602         e_hints_aux_hint_supported_add(_e_mod_split_screen_manager_hint_handler[i].name);
603      }
604
605    return EINA_TRUE;
606 }
607
608 static void
609 _e_mod_split_screen_manager_handler_shutdown(void)
610 {
611    E_FREE_LIST(_e_mod_split_screen_manager_ec_event_handlers, ecore_event_handler_del);
612    E_FREE_LIST(_e_mod_split_screen_manager_desk_area_hook_handlers, e_desk_area_hook_del);
613 }
614
615 static void
616 _e_mod_split_screen_manager_aux_hint_handler_shutdown(void)
617 {
618    E_FREE_LIST(_e_mod_split_screen_manager_ec_hook_handlers, e_client_hook_del);
619
620    for (int i=0 ; i<E_MOD_SPLIT_SCREEN_MANAGER_HINT_MAX ; i++)
621      {
622         e_hints_aux_hint_supported_del(_e_mod_split_screen_manager_hint_handler[i].name);
623      }
624 }
625
626 static Eina_Bool
627 _e_mod_split_screen_manager_region_init(void)
628 {
629    E_Desk *desk;
630    E_Mod_Split_Screen_Region *emssr_sub1, *emssr_sub2, *emssr_above;
631    int desk_x, desk_y, desk_w, desk_h;
632
633    desk = e_desk_current_get(e_zone_current_get());
634    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
635
636    desk_x = desk->geom.x;
637    desk_y = desk->geom.y;
638    desk_w = desk->geom.w;
639    desk_h = desk->geom.h;
640
641    emssr_sub1 = e_mod_split_screen_region_new("sub1", desk_x, desk_y, desk_w, desk_h / 2);
642    if (!emssr_sub1) return EINA_FALSE;
643
644    _e_mod_split_screen_region_list = eina_list_append(_e_mod_split_screen_region_list, emssr_sub1);
645
646    emssr_sub2 = e_mod_split_screen_region_new("sub2", desk_x, desk_y + desk_h / 2, desk_w, desk_h / 2);
647    if (!emssr_sub2) return EINA_FALSE;
648
649    _e_mod_split_screen_region_list = eina_list_append(_e_mod_split_screen_region_list, emssr_sub2);
650
651    emssr_above = e_mod_split_screen_region_new("above", desk_x, desk_y, desk_w, desk_h);
652    if (!emssr_above) return EINA_FALSE;
653
654    _e_mod_split_screen_region_list = eina_list_append(_e_mod_split_screen_region_list, emssr_above);
655
656    return EINA_TRUE;
657 }
658
659 static void
660 _e_mod_split_screen_manager_region_shutdown(void)
661 {
662    E_Mod_Split_Screen_Region *emssr;
663
664    if (!_e_mod_split_screen_region_list) return;
665
666    EINA_LIST_FREE(_e_mod_split_screen_region_list, emssr)
667      {
668         e_mod_split_screen_region_del(emssr);
669      }
670 }
671
672 EINTERN Eina_Bool
673 e_mod_split_screen_manager_init(void)
674 {
675    Eina_Bool res;
676
677    SSMDBG("SPLIT_SCREEN_MANAGER module init", NULL);
678
679    e_zone_screen_splitscreen_enable(e_zone_current_get());
680
681    res = _e_mod_split_screen_manager_region_init();
682    EINA_SAFETY_ON_FALSE_GOTO(res, err);
683
684    res = _e_mod_split_screen_manager_handler_init();
685    EINA_SAFETY_ON_FALSE_GOTO(res, err);
686
687    res = _e_mod_split_screen_manager_aux_hint_handler_init();
688    EINA_SAFETY_ON_FALSE_GOTO(res, err);
689
690    return EINA_TRUE;
691
692 err:
693    SSMINF("FAILED TO module init!!!", NULL);
694    e_mod_split_screen_manager_shutdown();
695
696    return EINA_FALSE;
697 }
698
699 EINTERN void
700 e_mod_split_screen_manager_shutdown(void)
701 {
702    SSMDBG("SPLIT_SCREEN_MANAGER module shutdown", NULL);
703    _e_mod_split_screen_manager_aux_hint_handler_shutdown();
704    _e_mod_split_screen_manager_handler_shutdown();
705    _e_mod_split_screen_manager_region_shutdown();
706 }