e_client: use e_client_visibility_set/get funtions
[platform/upstream/enlightenment.git] / src / bin / e_zone.c
1 #include "e_zone_intern.h"
2 #include "e_client_intern.h"
3 #include "e_desk_intern.h"
4 #include "e_actions_intern.h"
5 #include "e_appinfo_intern.h"
6 #include "e_bg_intern.h"
7 #include "e_bindings_intern.h"
8 #include "e_comp_wl_rsm_intern.h"
9 #include "e_comp_wl_subsurface_intern.h"
10 #include "e_comp_intern.h"
11 #include "e_input_intern.h"
12 #include "e_place_intern.h"
13 #include "e_policy_intern.h"
14 #include "e_maximize_intern.h"
15 #include "e_focus_intern.h"
16 #include "e_policy_visibility_intern.h"
17 #include "e_comp_object_intern.h"
18 #include "e_comp_canvas_intern.h"
19
20 #include <libds-tizen/screen.h>
21
22 #define ZONE_EC_DATA_KEY  "E_Zone_Client"
23
24 #define PRI(zone) ((E_Zone_Private *)e_object_data_get(E_OBJECT(zone)))
25
26 #define API_ENTRY \
27    EINA_SAFETY_ON_NULL_RETURN(zone); \
28    E_Zone_Private *priv = PRI(zone)
29
30 #define API_ENTRY_VAL(ret) \
31    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, ret); \
32    E_Zone_Private *priv = PRI(zone)
33
34 typedef struct _E_Zone_Private E_Zone_Private;
35 typedef struct _E_Zone_Private_Client E_Zone_Private_Client;
36
37 struct _E_Zone_Private
38 {
39    E_Zone *zone;
40
41    struct
42      {
43         struct wl_signal client_add;
44         struct wl_signal client_remove;
45         struct wl_signal display_state_change;
46         struct wl_signal focus_clear;
47         struct wl_signal focus_reset;
48      } events;
49
50    struct ds_tizen_screen *tizen_screen;
51    struct wl_listener screen_destroy;
52    struct wl_listener screen_get_splitscreen;
53 };
54
55 struct _E_Zone_Private_Client
56 {
57    E_Zone *zone;
58    E_Client *ec;
59
60    struct wl_listener client_destroy;
61    struct wl_listener client_eval_post_new_client;
62    struct wl_listener client_focus_set;
63 #ifdef REFACTOR_DESK_AREA
64 #else
65    struct wl_listener client_iconify;
66    struct wl_listener client_uniconify;
67    struct wl_listener client_stick;
68    struct wl_listener client_unstick;
69    struct wl_listener client_maximize;
70    struct wl_listener client_unmaximize;
71    struct wl_listener client_activate_done;
72    struct wl_listener client_fullscreen;
73    struct wl_listener client_unfullscreen;
74 #endif
75 };
76
77
78 /* E_Zone is a child object of E_Comp. There is one zone per screen
79  * in a xinerama setup. Each zone has one or more desktops.
80  */
81
82 static void        _e_zone_free(E_Zone *zone);
83 static void        _e_zone_cb_bg_mouse_down(void *data,
84                                             Evas *evas,
85                                             Evas_Object *obj,
86                                             void *event_info);
87 static void        _e_zone_cb_bg_mouse_up(void *data,
88                                           Evas *evas,
89                                           Evas_Object *obj,
90                                           void *event_info);
91 static void        _e_zone_event_generic_free(void *data, void *ev);
92 static void        _e_zone_object_del_attach(void *o);
93 static void        _e_zone_hooks_clean(void);
94 static Eina_Bool   _e_zone_hook_call(E_Zone_Hook_Point hookpoint, E_Zone *zone);
95
96 EINTERN int E_EVENT_ZONE_DESK_COUNT_SET = 0;
97 E_API int E_EVENT_ZONE_MOVE_RESIZE = 0;
98 EINTERN int E_EVENT_ZONE_ADD = 0;
99 EINTERN int E_EVENT_ZONE_DEL = 0;
100 #ifdef _F_ZONE_WINDOW_ROTATION_
101 E_API int E_EVENT_ZONE_ROTATION_CHANGE_BEGIN = 0;
102 E_API int E_EVENT_ZONE_ROTATION_CHANGE_CANCEL = 0;
103 E_API int E_EVENT_ZONE_ROTATION_CHANGE_END = 0;
104 E_API int E_EVENT_ZONE_ROTATION_EFFECT_READY = 0;
105 E_API int E_EVENT_ZONE_ROTATION_EFFECT_CANCEL = 0;
106 E_API int E_EVENT_ZONE_ROTATION_EFFECT_DONE = 0;
107 #endif
108 EINTERN int E_EVENT_ZONE_DISPLAY_STATE_CHANGE = 0;
109 EINTERN int E_EVENT_ZONE_USEFUL_GEOMETRY_CHANGE = 0;
110
111 #define E_ZONE_CORNER_RATIO 0.025;
112
113 static int _e_zone_hooks_delete = 0;
114 static int _e_zone_hooks_walking = 0;
115
116 static Eina_Inlist *_e_zone_hooks[] =
117 {
118    [E_ZONE_HOOK_DISPLAY_STATE_CHANGE] = NULL,
119 };
120
121 static Eina_Bool
122 _e_zone_private_init(E_Zone *zone)
123 {
124    E_Zone_Private *priv;
125
126    priv = E_NEW(E_Zone_Private, 1);
127    if (!priv)
128      return EINA_FALSE;
129
130    priv->zone = zone;
131
132    wl_signal_init(&priv->events.client_add);
133    wl_signal_init(&priv->events.client_remove);
134    wl_signal_init(&priv->events.display_state_change);
135    wl_signal_init(&priv->events.focus_clear);
136    wl_signal_init(&priv->events.focus_reset);
137
138    e_object_data_set(E_OBJECT(zone), priv);
139
140    return EINA_TRUE;
141 }
142
143 static void
144 _e_zone_private_finish(E_Zone *zone)
145 {
146    E_Zone_Private *priv;
147
148    priv = PRI(zone);
149    e_object_data_set(E_OBJECT(zone), NULL);
150
151    wl_list_remove(&priv->screen_get_splitscreen.link);
152    wl_list_remove(&priv->screen_destroy.link);
153
154    priv->zone = NULL;
155
156    free(priv);
157 }
158
159 EINTERN int
160 e_zone_init(void)
161 {
162    E_EVENT_ZONE_DESK_COUNT_SET = ecore_event_type_new();
163    E_EVENT_ZONE_MOVE_RESIZE = ecore_event_type_new();
164    E_EVENT_ZONE_ADD = ecore_event_type_new();
165    E_EVENT_ZONE_DEL = ecore_event_type_new();
166 #ifdef _F_ZONE_WINDOW_ROTATION_
167    E_EVENT_ZONE_ROTATION_CHANGE_BEGIN = ecore_event_type_new();
168    E_EVENT_ZONE_ROTATION_CHANGE_CANCEL = ecore_event_type_new();
169    E_EVENT_ZONE_ROTATION_CHANGE_END = ecore_event_type_new();
170    E_EVENT_ZONE_ROTATION_EFFECT_READY = ecore_event_type_new();
171    E_EVENT_ZONE_ROTATION_EFFECT_CANCEL = ecore_event_type_new();
172    E_EVENT_ZONE_ROTATION_EFFECT_DONE = ecore_event_type_new();
173 #endif
174    E_EVENT_ZONE_DISPLAY_STATE_CHANGE = ecore_event_type_new();
175    E_EVENT_ZONE_USEFUL_GEOMETRY_CHANGE = ecore_event_type_new();
176
177    return 1;
178 }
179
180 EINTERN int
181 e_zone_shutdown(void)
182 {
183    return 1;
184 }
185
186 #ifdef REFACTOR_DESK_AREA
187 #else
188 static void
189 _e_zone_client_maximize(E_Zone *zone, E_Desk *desk, E_Client *ec, E_Maximize max)
190 {
191    int x1, yy1, x2, y2;
192    int zx, zy, zw, zh;
193    int desk_x, desk_y, desk_w, desk_h;
194    Eina_Bool override = ec->maximize_override;
195
196    zx = zy = zw = zh = 0;
197    ec->maximize_override = 1;
198
199    if (ec->desk_area.enable && ec->desk_area.desk_area)
200      {
201         desk_x = ec->desk_area.desk_area->x;
202         desk_y = ec->desk_area.desk_area->y;
203         desk_w = ec->desk_area.desk_area->w;
204         desk_h = ec->desk_area.desk_area->h;
205      }
206    else
207      {
208         desk_x = desk->geom.x;
209         desk_y = desk->geom.y;
210         desk_w = desk->geom.w;
211         desk_h = desk->geom.h;
212      }
213
214    switch (max & E_MAXIMIZE_TYPE)
215      {
216       case E_MAXIMIZE_NONE:
217          /* Ignore */
218          break;
219
220       case E_MAXIMIZE_FULLSCREEN:
221       case E_MAXIMIZE_FILL:
222          if (ec->base_output_resolution.use)
223            {
224               zx = desk_x;
225               zy = desk_y;
226               zw = ec->base_output_resolution.w;
227               zh = ec->base_output_resolution.h;
228            }
229          else
230            {
231               e_zone_desk_useful_geometry_get(zone, desk, &zx, &zy, &zw, &zh, EINA_FALSE);
232            }
233
234          switch (max & E_MAXIMIZE_DIRECTION)
235            {
236             case E_MAXIMIZE_BOTH:
237                e_client_maximized_geometry_set(ec, zx, zy, zw, zh);
238                break;
239
240             case E_MAXIMIZE_VERTICAL:
241                e_client_maximized_geometry_set(ec, ec->x, zy, ec->w, zh);
242                break;
243
244             case E_MAXIMIZE_HORIZONTAL:
245                e_client_maximized_geometry_set(ec, zx, ec->y, zw, ec->h);
246                break;
247
248             case E_MAXIMIZE_LEFT:
249                e_client_maximized_geometry_set(ec, zx, zy, zw / 2, zh);
250                break;
251
252             case E_MAXIMIZE_RIGHT:
253                e_client_maximized_geometry_set(ec, zx + zw / 2, zy, zw / 2, zh);
254                break;
255            }
256          break;
257
258       case E_MAXIMIZE_SMART:
259       case E_MAXIMIZE_EXPAND:
260          if (desk->visible)
261            {
262               // base_output_resolution
263               if (ec->base_output_resolution.use)
264                 {
265                    zx = desk_x;
266                    zy = desk_y;
267                    zw = ec->base_output_resolution.w;
268                    zh = ec->base_output_resolution.h;
269                 }
270               else
271                 {
272                    e_zone_desk_useful_geometry_get(zone, desk, &zx, &zy, &zw, &zh, EINA_TRUE);
273                 }
274            }
275          else
276            {
277               x1 = desk_x;
278               yy1 = desk_y;
279               x2 = desk_x + desk_w;
280               y2 = desk_y + desk_h;
281               e_maximize_client_shelf_fill(ec, &x1, &yy1, &x2, &y2, max);
282               zx = x1, zy = yy1;
283               zw = x2 - x1;
284               zh = y2 - yy1;
285            }
286
287          evas_object_smart_callback_call(ec->frame, "maximize", NULL);
288
289          switch (max & E_MAXIMIZE_DIRECTION)
290            {
291             case E_MAXIMIZE_BOTH:
292                e_client_maximized_geometry_set(ec, zx, zy, zw, zh);
293                break;
294
295             case E_MAXIMIZE_VERTICAL:
296                e_client_maximized_geometry_set(ec, ec->x, zy, ec->w, zh);
297                break;
298
299             case E_MAXIMIZE_HORIZONTAL:
300                e_client_maximized_geometry_set(ec, zx, ec->y, zw, ec->h);
301                break;
302
303             case E_MAXIMIZE_LEFT:
304                e_client_maximized_geometry_set(ec, zx, zy, zw / 2, zh);
305                break;
306
307             case E_MAXIMIZE_RIGHT:
308                e_client_maximized_geometry_set(ec, zx + zw / 2, zy, zw / 2, zh);
309                break;
310            }
311          break;
312      }
313
314    if (ec->maximize_override)
315      ec->maximize_override = override;
316 }
317 #endif
318
319 static void
320 _e_zone_client_apply_auto_placement(E_Zone *zone, E_Client *ec)
321 {
322    E_Desk *desk;
323    Eina_List *skiplist = NULL;
324    int new_x, new_y, t = 0;
325    int type;
326    E_Client *parent_ec;
327    int zx = 0, zy = 0, zw = 0, zh = 0;
328    unsigned int seed = (unsigned int)time(NULL);
329
330    // call the intercept hook of the auto placement
331    if (e_client_intercept_hook_auto_placement_call(ec))
332      {
333         ELOGF("POL", "Intercepted auto_placement policy.", ec);
334         return;
335      }
336
337    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
338
339    if (zw > ec->w)
340      new_x = zx + (rand_r(&seed) % (zw - ec->w));
341    else
342      new_x = zx;
343    if (zh > ec->h)
344      new_y = zy + (rand_r(&seed) % (zh - ec->h));
345    else
346      new_y = zy;
347
348    e_comp_object_frame_geometry_get(ec->frame, NULL, NULL, &t, NULL);
349
350    parent_ec = ec->parent;
351    if (parent_ec)
352      {
353         type = 1;
354         new_x = parent_ec->x;
355         new_y = parent_ec->y;
356      }
357    else if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) ||
358             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
359      {
360         type = 2;
361         skiplist = eina_list_append(skiplist, ec);
362         desk = e_zone_desk_find_by_ec(zone, ec);
363         if (desk)
364           e_place_desk_region_smart(desk, skiplist,
365                                     ec->x, ec->y, ec->w, ec->h,
366                                     &new_x, &new_y);
367         else
368           e_place_zone_region_smart(zone, skiplist,
369                                     ec->x, ec->y, ec->w, ec->h,
370                                     &new_x, &new_y);
371
372         eina_list_free(skiplist);
373      }
374    else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
375      {
376         type = 3;
377         e_place_zone_manual(zone, ec->w, t, &new_x, &new_y);
378      }
379    else
380      {
381         type = 0;
382         e_place_zone_cursor(zone, ec->x, ec->y, ec->w, ec->h,
383                             t, &new_x, &new_y);
384      }
385
386    ELOGF("POL", "Apply auto placement (type:%d). (%d,%d) -> (%d,%d).", ec, type, ec->x, ec->y, new_x, new_y);
387    e_client_pos_set(ec, new_x, new_y);
388    ec->changes.pos = 1;
389    ec->placed = 1;
390    ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
391 }
392
393 static void
394 _zone_cb_client_destroy(struct wl_listener *listener, void *data)
395 {
396    E_Zone_Private_Client *zone_client;
397    E_Zone *zone;
398    E_Client *ec;
399    E_Desk *desk;
400
401    zone_client = wl_container_of(listener, zone_client, client_destroy);
402    zone = zone_client->zone;
403    ec = zone_client->ec;
404
405    desk = e_zone_desk_find_by_ec(zone, ec);
406    EINA_SAFETY_ON_NULL_RETURN(desk);
407
408    ELOGF("ZONE", "CLIENT DEL", ec);
409
410    e_desk_visible_client_iconified_list_remove(desk, ec);
411
412    // desk_zoom
413    e_client_transform_core_remove(ec, ec->desk_zoom.transform);
414    e_util_transform_del(ec->desk_zoom.transform);
415    ec->desk_zoom.transform = NULL;
416    E_FREE_FUNC(ec->desk_zoom.hook_subsurf_create, e_comp_wl_hook_del);
417
418 #ifdef REFACTOR_DESK_AREA
419 #else
420    if (ec->desk_area.desk_area)
421      e_desk_area_ec_remove(ec->desk_area.desk_area, ec);
422    e_util_transform_del(ec->desk_area.transform);
423    ec->desk_area.transform = NULL;
424
425    if (ec->fullscreen)
426      {
427         desk->fullscreen_clients = eina_list_remove(desk->fullscreen_clients, ec);
428         if (!desk->fullscreen_clients)
429           e_comp_render_queue();
430      }
431 #endif
432
433    wl_signal_emit_mutable(&PRI(zone)->events.client_remove, ec);
434
435    e_desk_client_del(desk, ec);
436
437 #ifdef REFACTOR_DESK_AREA
438 #else
439    wl_list_remove(&zone_client->client_unfullscreen.link);
440    wl_list_remove(&zone_client->client_fullscreen.link);
441    wl_list_remove(&zone_client->client_activate_done.link);
442    wl_list_remove(&zone_client->client_unmaximize.link);
443    wl_list_remove(&zone_client->client_maximize.link);
444    wl_list_remove(&zone_client->client_unstick.link);
445    wl_list_remove(&zone_client->client_stick.link);
446    wl_list_remove(&zone_client->client_uniconify.link);
447    wl_list_remove(&zone_client->client_iconify.link);
448 #endif
449    wl_list_remove(&zone_client->client_focus_set.link);
450    wl_list_remove(&zone_client->client_eval_post_new_client.link);
451    wl_list_remove(&zone_client->client_destroy.link);
452
453    E_FREE(zone_client);
454 }
455
456 static void
457 _e_zone_cb_hook_client_new_client_post(void *d, E_Client *ec)
458 {
459    E_Zone *zone;
460
461    EINA_SAFETY_ON_NULL_RETURN(ec);
462
463    zone = (E_Zone *)d;
464    EINA_SAFETY_ON_NULL_RETURN(zone);
465
466    // FIXME: A ec is set the current zone now.
467    //        We need to make a policy for the placement of the ec at the zone.
468    if (zone != e_zone_current_get()) return;
469
470    e_policy_client_add(ec);
471    e_zone_client_add(zone, ec);
472 }
473
474 static void
475 _zone_cb_client_eval_post_new_client(struct wl_listener *listener, void *data)
476 {
477    E_Zone_Private_Client *zone_client;
478    E_Zone *zone;
479    E_Client *ec;
480    int tx, ty, tw, th;
481    int nw, nh;
482    int zx = 0, zy = 0, zw = 0, zh = 0;
483
484    zone_client = wl_container_of(listener, zone_client, client_eval_post_new_client);
485    zone = zone_client->zone;
486    ec = zone_client->ec;
487
488    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
489    /* enforce wm size hints for initial sizing */
490    if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
491       {
492          tw = MIN(ec->w, zone->w);
493          th = MIN(ec->h, zone->h);
494          e_client_size_set(ec, tw, th);
495       }
496
497    nw = ec->w;
498    nh = ec->h;
499    e_client_resize_limit(ec, &nw, &nh);
500    e_client_size_set(ec, nw, nh);
501
502    if (ec->re_manage)
503       {
504          int x = ec->x, y = ec->y;
505          if (ec->x) e_comp_object_frame_xy_adjust(ec->frame, ec->x, 0, &ec->x, NULL);
506          if (ec->y) e_comp_object_frame_xy_adjust(ec->frame, 0, ec->y, NULL, &ec->y);
507          if ((x != ec->x) || (y != ec->y)) ec->changes.pos = 1;
508          ec->placed = 1;
509          ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
510       }
511
512    if (!ec->placed)
513       {
514          if (ec->dialog)
515            {
516               tx = zx + ((zw - ec->w) / 2);
517               ty = zy + ((zh - ec->h) / 2);
518               e_client_pos_set(ec, tx, ty);
519
520               ec->changes.pos = 1;
521               ec->placed = 1;
522               ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
523            }
524       }
525
526    E_Appinfo *eai;
527    eai = e_appinfo_find_with_pid(ec->netwm.pid);
528    if (!eai)
529       {
530          if (!ec->placed)
531            _e_zone_client_apply_auto_placement(zone, ec);
532       }
533    else
534       {
535          if (e_appinfo_auto_placement_get(eai))
536            _e_zone_client_apply_auto_placement(zone, ec);
537       }
538
539    /* Recreate state */
540    if (ec->e.state.centered)
541       {
542          tx = zx + (zw - ec->w) / 2;
543          ty = zy + (zh - ec->h) / 2;
544          e_client_pos_set(ec, tx, ty);
545          ec->changes.pos = 1;
546       }
547
548    /* if the explicit geometry request asks for the app to be
549    * in another zone - well move it there */
550    {
551       E_Zone *zone1 = NULL;
552       int x, y;
553
554       x = MAX(ec->x, 0);
555       y = MAX(ec->y, 0);
556       if ((!ec->re_manage) && ((ec->x != x) || (ec->y != y)))
557          zone1 = e_comp_zone_xy_get(x, y);
558
559       if (!zone1)
560          {
561             zone1 = e_comp_zone_xy_get(ec->x + (ec->w / 2), ec->y + (ec->h / 2));
562             if (zone1)
563             {
564                E_Zone *z2 = e_comp_zone_xy_get(ec->x, ec->y);
565
566                if (z2 && (z2 != zone1))
567                   {
568                      size_t psz = 0;
569                      E_Zone *zf = z2;
570                      Eina_List *l;
571
572                      EINA_LIST_FOREACH(e_comp->zones, l, z2)
573                         {
574                            int w, h;
575
576                            x = ec->x, y = ec->y, w = ec->w, h = ec->h;
577                            E_RECTS_CLIP_TO_RECT(x, y, w, h, z2->x, z2->y, z2->w, z2->h);
578                            if (w * h == z2->w * z2->h)
579                               {
580                                  /* client fully covering zone */
581                                  zf = z2;
582                                  break;
583                               }
584                            if ((unsigned)(w * h) > psz)
585                               {
586                                  psz = w * h;
587                                  zf = z2;
588                               }
589                         }
590                      zone = zf;
591                   }
592             }
593          }
594       if (!zone1)
595          zone1 = e_comp_zone_xy_get(ec->x, ec->y);
596       if (!zone1)
597          zone1 = e_comp_zone_xy_get(ec->x + ec->w - 1, ec->y);
598       if (!zone1)
599          zone1 = e_comp_zone_xy_get(ec->x + ec->w - 1, ec->y + ec->h - 1);
600       if (!zone1)
601          zone1 = e_comp_zone_xy_get(ec->x, ec->y + ec->h - 1);
602       if ((zone1) && (zone1 != zone))
603          e_zone_client_add(zone1, ec);
604    }
605 }
606
607 static void
608 _zone_cb_client_focus_set(struct wl_listener *listener, void *data)
609 {
610    E_Zone_Private_Client *zone_client;
611    E_Zone *zone;
612    E_Client *ec;
613    E_Desk *desk;
614
615    zone_client = wl_container_of(listener, zone_client, client_focus_set);
616    zone = zone_client->zone;
617    ec = zone_client->ec;
618
619    desk = e_zone_desk_find_by_ec(zone, ec);
620    EINA_SAFETY_ON_NULL_RETURN(desk);
621
622    if (!desk->visible && ec->sticky)
623      e_desk_client_add(e_desk_current_get(zone), ec);
624 }
625
626 #ifdef REFACTOR_DESK_AREA
627 #else
628 static void
629 _zone_cb_client_iconify(struct wl_listener *listener, void *data)
630 {
631    E_Zone_Private_Client *zone_client;
632    E_Zone *zone;
633    E_Client *ec;
634    E_Desk *desk;
635
636    zone_client = wl_container_of(listener, zone_client, client_iconify);
637    zone = zone_client->zone;
638    ec = zone_client->ec;
639
640    desk = e_zone_desk_find_by_ec(zone, ec);
641    EINA_SAFETY_ON_NULL_RETURN(desk);
642
643    e_comp_wl_remote_surface_image_save(ec);
644
645    ec->iconic = 1;
646    ec->want_focus = ec->take_focus = 0;
647    ec->changes.visible = 0;
648    if (ec->fullscreen)
649      desk->fullscreen_clients = eina_list_remove(desk->fullscreen_clients, ec);
650    e_client_comp_hidden_set(ec, 1);
651    evas_object_hide(ec->frame);
652
653    e_client_iconify_event_send(ec);
654
655    if (e_config->transient.iconify)
656      {
657         E_Client *child;
658         Eina_List *list = eina_list_clone(ec->transients);
659
660         EINA_LIST_FREE(list, child)
661           {
662              if ((child->exp_iconify.type != E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT) &&
663                  (e_client_is_parent_iconify_by_client(child)))
664                {
665                   e_client_iconified_type_set(child, E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT);
666                   child->exp_iconify.by_client = 1;
667                   e_policy_client_iconic_state_change_send(child, 1);
668                }
669              e_client_iconify(child);
670           }
671      }
672 }
673
674 static void
675 _zone_cb_client_uniconify(struct wl_listener *listener, void *data)
676 {
677    E_Zone_Private_Client *zone_client;
678    E_Zone *zone;
679    E_Client *ec;
680    E_Desk *desk;
681    Eina_Bool not_raise;
682
683    zone_client = wl_container_of(listener, zone_client, client_uniconify);
684    zone = zone_client->zone;
685    ec = zone_client->ec;
686
687    desk = e_zone_desk_find_by_ec(zone, ec);
688    EINA_SAFETY_ON_NULL_RETURN(desk);
689
690    e_comp_wl_remote_surface_image_save_cancel(ec);
691
692    e_desk_client_add(desk, ec);
693    not_raise = ec->exp_iconify.not_raise;
694
695    ec->exp_iconify.by_client = 0;
696    e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
697
698    if (e_config->transient.iconify)
699      {
700         E_Client *child;
701         Eina_List *list = eina_list_clone(ec->transients);
702
703         EINA_LIST_FREE(list, child)
704           {
705              if (e_client_transient_policy_get(child) == E_TRANSIENT_BELOW)
706                {
707                   child->exp_iconify.not_raise = not_raise;
708                   e_client_uniconify(child);
709                }
710           }
711      }
712
713    if (!not_raise)
714      e_client_raise(ec);
715
716    if (ec->internal)
717      {
718         ELOGF("TZVIS", "UNICONIFY|internal object force show", ec);
719         evas_object_show(ec->frame);
720      }
721
722    if (ec->pixmap)
723      {
724          E_Comp_Wl_Client_Data *cdata;
725
726          cdata = e_client_cdata_get(ec);
727
728         if (e_pixmap_usable_get(ec->pixmap))
729           {
730              if (cdata && cdata->mapped)
731                {
732                   ELOGF("TZVIS", "UNICONIFY|object show. frame_visible:%d", ec,
733                         evas_object_visible_get(ec->frame));
734                   evas_object_show(ec->frame);
735                }
736              else
737                {
738                   ELOGF("TZVIS", "UNICONIFY|object no show. currently unmapped", ec);
739                }
740           }
741         else
742           {
743              if (!ec->exp_iconify.buffer_flush &&
744                  !ec->exp_iconify.deiconify_update)
745                {
746                   if (cdata && cdata->mapped)
747                     {
748                        ELOGF("TZVIS", "UNICONIFY|object show. no use buffer flush. frame_visible:%d", ec,
749                              evas_object_visible_get(ec->frame));
750                        evas_object_show(ec->frame);
751                     }
752                }
753           }
754      }
755    e_client_comp_hidden_set(ec, 0);
756    ec->deskshow = ec->iconic = 0;
757
758 #if 0 // focus should be set to the top window not uniconify window
759    if (ec->pixmap && e_pixmap_usable_get(ec->pixmap))
760       e_client_frame_focus_set(ec, EINA_TRUE);
761 #endif
762
763    // send the uniconify event of a client
764    e_client_uniconify_event_send(ec);
765
766    if (e_config->transient.iconify)
767      {
768         E_Client *child;
769         Eina_List *list = eina_list_clone(ec->transients);
770
771         EINA_LIST_FREE(list, child)
772           {
773              if (e_client_transient_policy_get(child) == E_TRANSIENT_ABOVE)
774                {
775                   if (child->exp_iconify.type == E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT)
776                     e_policy_client_iconic_state_change_send(child, 0);
777                   child->exp_iconify.not_raise = not_raise;
778                   e_client_uniconify(child);
779                }
780           }
781      }
782
783    ec->exp_iconify.not_raise = 0;
784 }
785
786 static void
787 _zone_cb_client_stick(struct wl_listener *listener, void *data)
788 {
789    E_Zone_Private_Client *zone_client;
790    E_Zone *zone;
791    E_Client *ec;
792    E_Desk *desk;
793
794    zone_client = wl_container_of(listener, zone_client, client_stick);
795    zone = zone_client->zone;
796    ec = zone_client->ec;
797
798    desk = e_zone_desk_find_by_ec(zone, ec);
799    EINA_SAFETY_ON_NULL_RETURN(desk);
800
801    e_desk_client_del(desk, ec);
802    ec->sticky = 1;
803    ec->hidden = 0;
804
805    e_desk_client_add(desk, ec);
806
807    evas_object_smart_callback_call(ec->frame, "stick", NULL);
808
809    if (e_config->transient.desktop)
810      {
811         E_Client *child;
812         Eina_List *list = eina_list_clone(ec->transients);
813
814         EINA_LIST_FREE(list, child)
815           {
816              child->sticky = 1;
817              evas_object_show(ec->frame);
818           }
819      }
820 }
821
822 static void
823 _zone_cb_client_unstick(struct wl_listener *listener, void *data)
824 {
825    E_Zone_Private_Client *zone_client;
826    E_Zone *zone;
827    E_Client *ec;
828    E_Desk *desk, *curr_desk;
829
830    zone_client = wl_container_of(listener, zone_client, client_unstick);
831    zone = zone_client->zone;
832    ec = zone_client->ec;
833
834    desk = e_zone_desk_find_by_ec(zone, ec);
835    EINA_SAFETY_ON_NULL_RETURN(desk);
836
837    e_desk_client_del(desk, ec);
838    ec->hidden = ec->sticky = 0;
839
840    curr_desk = e_desk_current_get(zone);
841    e_desk_client_add(curr_desk, ec);
842
843    evas_object_smart_callback_call(ec->frame, "unstick", NULL);
844
845    if (e_config->transient.desktop)
846      {
847         E_Client *child;
848         Eina_List *list = eina_list_clone(ec->transients);
849
850         EINA_LIST_FREE(list, child)
851           {
852              child->sticky = 0;
853           }
854      }
855 }
856
857 static void
858 _zone_cb_client_maximize(struct wl_listener *listener, void *data)
859 {
860    E_Zone_Private_Client *zone_client;
861    E_Zone *zone;
862    E_Client *ec;
863    E_Desk *desk;
864    int desk_x, desk_y;
865    E_Maximize max;
866
867    zone_client = wl_container_of(listener, zone_client, client_maximize);
868    zone = zone_client->zone;
869    ec = zone_client->ec;
870
871    max = *((E_Maximize *)data);
872
873    desk = e_zone_desk_find_by_ec(zone, ec);
874    EINA_SAFETY_ON_NULL_RETURN(desk);
875
876    if (ec->desk_area.enable && ec->desk_area.desk_area)
877      {
878         desk_x = ec->desk_area.desk_area->x;
879         desk_y = ec->desk_area.desk_area->y;
880      }
881    else
882      {
883         desk_x = desk->geom.x;
884         desk_y = desk->geom.y;
885      }
886
887    ec->pre_res_change.valid = 0;
888
889    if (!ec->fullscreen)
890      {
891         evas_object_smart_callback_call(ec->frame, "maximize_pre", NULL);
892
893         if (!(ec->maximized & E_MAXIMIZE_HORIZONTAL))
894           {
895              /* Horizontal hasn't been set */
896              ec->saved.x = ec->client.x - desk_x;
897              ec->saved.w = ec->client.w;
898           }
899         if (!(ec->maximized & E_MAXIMIZE_VERTICAL))
900           {
901              /* Vertical hasn't been set */
902              ec->saved.y = ec->client.y - desk_y;
903              ec->saved.h = ec->client.h;
904           }
905
906         ec->saved.zone = zone->num;
907
908         _e_zone_client_maximize(zone, desk, ec, max);
909      }
910 }
911
912 static void
913 _zone_cb_client_unmaximize(struct wl_listener *listener, void *data)
914 {
915    E_Zone_Private_Client *zone_client;
916    E_Zone *zone;
917    E_Client *ec;
918    E_Maximize max;
919
920    zone_client = wl_container_of(listener, zone_client, client_unmaximize);
921    zone = zone_client->zone;
922    ec = zone_client->ec;
923
924    if (ec->fullscreen) return;
925
926    max = *((E_Maximize *)data);
927
928    if (ec->maximized & E_MAXIMIZE_TYPE)
929      {
930         ec->pre_res_change.valid = 0;
931         ec->changes.need_maximize = 0;
932
933         if ((ec->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
934           {
935              E_Maximize tmp_max = ec->maximized;
936
937              //un-set maximized state for updating frame.
938              ec->maximized = E_MAXIMIZE_NONE;
939              e_client_frame_update(ec);
940              // re-set maximized state for unmaximize smart callback.
941              ec->maximized = tmp_max;
942              evas_object_smart_callback_call(ec->frame, "unfullscreen", NULL);
943              // un-set maximized state.
944              ec->maximized = E_MAXIMIZE_NONE;
945              e_client_util_move_resize_without_frame(ec,
946                                                      ec->saved.x + zone->x,
947                                                      ec->saved.y + zone->y,
948                                                      ec->saved.w, ec->saved.h);
949              ec->saved.x = ec->saved.y = ec->saved.w = ec->saved.h = 0;
950           }
951         else
952           {
953              int w, h, x, y;
954              Eina_Bool horiz = EINA_FALSE, vert = EINA_FALSE;
955
956              w = ec->client.w;
957              h = ec->client.h;
958              x = ec->client.x;
959              y = ec->client.y;
960
961              if (max & E_MAXIMIZE_VERTICAL)
962                {
963                   /* Remove vertical */
964                   h = ec->saved.h;
965                   vert = EINA_TRUE;
966                   y = ec->saved.y + zone->y;
967                   if ((max & E_MAXIMIZE_VERTICAL) == E_MAXIMIZE_VERTICAL)
968                     {
969                        ec->maximized &= ~E_MAXIMIZE_VERTICAL;
970                        ec->maximized &= ~E_MAXIMIZE_LEFT;
971                        ec->maximized &= ~E_MAXIMIZE_RIGHT;
972                     }
973                   if ((max & E_MAXIMIZE_LEFT) == E_MAXIMIZE_LEFT)
974                     ec->maximized &= ~E_MAXIMIZE_LEFT;
975                   if ((max & E_MAXIMIZE_RIGHT) == E_MAXIMIZE_RIGHT)
976                     ec->maximized &= ~E_MAXIMIZE_RIGHT;
977                }
978              if (max & E_MAXIMIZE_HORIZONTAL)
979                {
980                   /* Remove horizontal */
981                   w = ec->saved.w;
982                   x = ec->saved.x + zone->x;
983                   horiz = EINA_TRUE;
984                   ec->maximized &= ~E_MAXIMIZE_HORIZONTAL;
985                }
986
987              if (!(ec->maximized & E_MAXIMIZE_DIRECTION))
988                {
989                   ec->maximized = E_MAXIMIZE_NONE;
990                   e_client_frame_update(ec);
991                   evas_object_smart_callback_call(ec->frame, "unmaximize", NULL);
992                   e_client_resize_limit(ec, &w, &h);
993                   e_client_pos_set(ec, x, y);
994                   if ((ec->saved.w != 0) && (ec->saved.h != 0))
995                     {
996                        if ((w != ec->saved.w) || (h != ec->saved.h))
997                          {
998                             e_policy_visibility_client_defer_move(ec);
999                          }
1000                     }
1001                }
1002              else
1003                {
1004                   evas_object_smart_callback_call(ec->frame, "unmaximize", NULL);
1005                   e_client_resize_limit(ec, &w, &h);
1006                   e_client_pos_set(ec, x, y);
1007                   if ((ec->saved.w != 0) && (ec->saved.h != 0))
1008                     {
1009                        if ((w != ec->saved.w) || (h != ec->saved.h))
1010                          {
1011                             e_policy_visibility_client_defer_move(ec);
1012                          }
1013                     }
1014                }
1015              if (vert)
1016                ec->saved.h = ec->saved.y = 0;
1017              if (horiz)
1018                ec->saved.w = ec->saved.x = 0;
1019           }
1020      }
1021 }
1022
1023 static void
1024 _zone_cb_client_activate_done(struct wl_listener *listener, void *data)
1025 {
1026    E_Zone_Private_Client *zone_client;
1027    E_Zone *zone;
1028    E_Client *ec;
1029    E_Desk *desk;
1030
1031    zone_client = wl_container_of(listener, zone_client, client_activate_done);
1032    zone = zone_client->zone;
1033    ec = zone_client->ec;
1034
1035    desk = e_zone_desk_find_by_ec(zone, ec);
1036    EINA_SAFETY_ON_NULL_RETURN(desk);
1037
1038    if ((!ec->iconic) && (!ec->sticky))
1039      {
1040         e_desk_show(desk);
1041      }
1042
1043    if (!ec->lock_user_stacking)
1044      e_client_raise(ec);
1045
1046    if (!e_client_desk_iconify_skip_get(ec))
1047      {
1048         e_desk_visible_client_iconified_list_remove_all(desk);
1049      }
1050 }
1051
1052 static void
1053 _zone_cb_client_fullscreen(struct wl_listener *listener, void *data)
1054 {
1055    E_Zone_Private_Client *zone_client;
1056    E_Zone *zone;
1057    E_Client *ec;
1058    E_Desk *desk;
1059    E_Fullscreen fullscreen_policy;
1060
1061    zone_client = wl_container_of(listener, zone_client, client_fullscreen);
1062    zone = zone_client->zone;
1063    ec = zone_client->ec;
1064
1065    fullscreen_policy = *((E_Fullscreen *)data);
1066
1067    desk = e_zone_desk_find_by_ec(zone, ec);
1068    EINA_SAFETY_ON_NULL_RETURN(desk);
1069
1070    if (!desk->visible) return;
1071
1072    if (e_comp->nocomp_ec && (e_desk_has_ec(desk, e_comp->nocomp_ec)))
1073      e_comp->nocomp_ec = ec;
1074    desk->fullscreen_clients = eina_list_append(desk->fullscreen_clients, ec);
1075    ec->pre_res_change.valid = 0;
1076
1077    if (!ec->maximized)
1078      {
1079         ec->saved.x = ec->client.x - zone->x;
1080         ec->saved.y = ec->client.y - zone->y;
1081         ec->saved.w = ec->client.w;
1082         ec->saved.h = ec->client.h;
1083      }
1084    ec->saved.maximized = ec->maximized;
1085    ec->saved.zone = zone->num;
1086
1087    if ((eina_list_count(e_comp->zones) > 1) ||
1088        (fullscreen_policy == E_FULLSCREEN_RESIZE))
1089      {
1090         e_client_frame_geometry_set(ec, zone->x, zone->y, zone->w, zone->h);
1091      }
1092
1093    if (!e_client_util_ignored_get(ec))
1094      e_client_frame_update(ec);
1095
1096    evas_object_smart_callback_call(ec->frame, "fullscreen", NULL);
1097 }
1098
1099 static void
1100 _zone_cb_client_unfullscreen(struct wl_listener *listener, void *data)
1101 {
1102    E_Zone_Private_Client *zone_client;
1103    E_Zone *zone;
1104    E_Client *ec;
1105    E_Desk *desk;
1106
1107    zone_client = wl_container_of(listener, zone_client, client_unfullscreen);
1108    zone = zone_client->zone;
1109    ec = zone_client->ec;
1110
1111    desk = e_zone_desk_find_by_ec(zone, ec);
1112    EINA_SAFETY_ON_NULL_RETURN(desk);
1113
1114    ec->pre_res_change.valid = 0;
1115    desk->fullscreen_clients = eina_list_remove(desk->fullscreen_clients, ec);
1116
1117    if (!e_client_util_ignored_get(ec))
1118      e_client_frame_update(ec);
1119
1120    evas_object_smart_callback_call(ec->frame, "unfullscreen", NULL);
1121
1122    if (ec->maximized)
1123      {
1124         int saved_x = ec->saved.x;
1125         int saved_y = ec->saved.y;
1126         int saved_w = ec->saved.w;
1127         int saved_h = ec->saved.h;
1128         e_client_maximize_update(ec);
1129         ec->saved.x = saved_x;
1130         ec->saved.y = saved_y;
1131         ec->saved.w = saved_w;
1132         ec->saved.h = saved_h;
1133      }
1134    else
1135      {
1136         e_client_util_move_resize_without_frame(ec, zone->x + ec->saved.x,
1137                                                 zone->y + ec->saved.y,
1138                                                 ec->saved.w, ec->saved.h);
1139      }
1140
1141    if (!desk->fullscreen_clients)
1142      e_comp_render_queue();
1143 }
1144 #endif
1145
1146 static void
1147 _e_zone_client_data_set(E_Zone *zone, E_Client *ec)
1148 {
1149   E_Zone *data;
1150
1151   data = evas_object_data_get(ec->frame, ZONE_EC_DATA_KEY);
1152   if (data)
1153     {
1154        if (data == zone)
1155          {
1156             ELOGF("E_Zone", "EC is already added to zone_id:%d", ec, zone->id);
1157             return;
1158          }
1159
1160        evas_object_data_del(ec->frame, ZONE_EC_DATA_KEY);
1161     }
1162
1163   evas_object_data_set(ec->frame, ZONE_EC_DATA_KEY, zone);
1164 }
1165
1166 EINTERN E_Zone *
1167 e_zone_new(int num, int id, int x, int y, int w, int h)
1168 {
1169    E_Zone *zone;
1170    Evas_Object *o;
1171    E_Event_Zone_Add *ev;
1172    char name[40];
1173
1174    zone = E_OBJECT_ALLOC(E_Zone, E_ZONE_TYPE, _e_zone_free);
1175    if (!zone) return NULL;
1176
1177    if (!_e_zone_private_init(zone))
1178      {
1179         e_object_del(E_OBJECT(zone));
1180         return NULL;
1181      }
1182
1183    zone->x = x;
1184    zone->y = y;
1185    zone->w = w;
1186    zone->h = h;
1187    zone->num = num;
1188    zone->id = id;
1189
1190    zone->display_state = E_ZONE_DISPLAY_STATE_ON;
1191
1192    // Create E_Focus at only default zone which the zone num is 0
1193    if (zone->num == 0)
1194      {
1195         if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK)
1196           zone->focus = e_focus_new(zone, E_FOCUS_EXT_TOP_STACK);
1197         else
1198           // default focus policy is E_FOCUS_EXT_HISTORY
1199           zone->focus = e_focus_new(zone, E_FOCUS_EXT_HISTORY);
1200         if (!zone->focus)
1201           {
1202              e_object_del(E_OBJECT(zone));
1203              ERR("Fail to create focus object at zone %d", zone->num);
1204              return NULL;
1205           }
1206      }
1207
1208    //printf("@@@@@@@@@@ e_zone_new: %i %i | %i %i %ix%i = %p\n", num, id, x, y, w, h, zone);
1209
1210    snprintf(name, sizeof(name), "Zone %d", zone->num);
1211    zone->name = eina_stringshare_add(name);
1212
1213    e_comp->zones = eina_list_append(e_comp->zones, zone);
1214
1215    o = evas_object_rectangle_add(e_comp->evas);
1216    zone->bg_clip_object = o;
1217    evas_object_repeat_events_set(o, 1);
1218    evas_object_layer_set(o, E_LAYER_BG);
1219    evas_object_name_set(o, "zone->bg_clip_object");
1220    evas_object_move(o, x, y);
1221    evas_object_resize(o, w, h);
1222    evas_object_color_set(o, 255, 255, 255, 255);
1223    evas_object_show(o);
1224
1225    o = evas_object_rectangle_add(e_comp->evas);
1226    zone->bg_event_object = o;
1227    evas_object_name_set(o, "zone->bg_event_object");
1228    evas_object_clip_set(o, zone->bg_clip_object);
1229    evas_object_layer_set(o, E_LAYER_BG);
1230    evas_object_repeat_events_set(o, 1);
1231    evas_object_move(o, x, y);
1232    evas_object_resize(o, w, h);
1233    evas_object_color_set(o, 0, 0, 0, 0);
1234    evas_object_repeat_events_set(o, 1);
1235    evas_object_show(o);
1236    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _e_zone_cb_bg_mouse_down, zone);
1237    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _e_zone_cb_bg_mouse_up, zone);
1238
1239    /* TODO: config the ecore_evas type. */
1240
1241    zone->desk_x_count = 0;
1242    zone->desk_y_count = 0;
1243    zone->desk_x_current = 0;
1244    zone->desk_y_current = 0;
1245    e_zone_desk_count_set(zone, e_config->zone_desks_x_count,
1246                          e_config->zone_desks_y_count);
1247
1248    e_object_del_attach_func_set(E_OBJECT(zone), _e_zone_object_del_attach);
1249
1250    // CLIENT HOOK Handlers
1251    E_LIST_HOOK_APPEND(zone->ec_hooks, E_CLIENT_HOOK_NEW_CLIENT_POST, _e_zone_cb_hook_client_new_client_post, zone);
1252
1253    if (starting) return zone;
1254
1255    ev = E_NEW(E_Event_Zone_Add, 1);
1256    if (ev)
1257      {
1258         ev->zone = zone;
1259         e_object_ref(E_OBJECT(ev->zone));
1260         ecore_event_add(E_EVENT_ZONE_ADD, ev, _e_zone_event_generic_free, NULL);
1261      }
1262
1263    return zone;
1264 }
1265
1266 EINTERN void
1267 e_zone_name_set(E_Zone *zone,
1268                 const char *name)
1269 {
1270    E_OBJECT_CHECK(zone);
1271    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1272
1273    if (zone->name) eina_stringshare_del(zone->name);
1274    zone->name = eina_stringshare_add(name);
1275 }
1276
1277 static void
1278 e_zone_reconfigure_clients(E_Zone *zone, int dx, int dy, int dw, int dh)
1279 {
1280    E_Client *ec;
1281
1282    E_CLIENT_FOREACH(ec)
1283      {
1284         if (!e_zone_has_ec(zone, ec)) continue;
1285
1286         if ((dx != 0) || (dy != 0))
1287           evas_object_move(ec->frame, ec->x + dx, ec->y + dy);
1288         // we shrank the zone - adjust windows more
1289         if ((dw < 0) || (dh < 0))
1290           {
1291              e_client_res_change_geometry_save(ec);
1292              e_client_res_change_geometry_restore(ec);
1293           }
1294      }
1295 }
1296
1297 EINTERN void
1298 e_zone_move(E_Zone *zone,
1299             int x,
1300             int y)
1301 {
1302    E_Event_Zone_Move_Resize *ev;
1303    int dx, dy;
1304
1305    E_OBJECT_CHECK(zone);
1306    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1307
1308    if ((x == zone->x) && (y == zone->y)) return;
1309    dx = x - zone->x;
1310    dy = y - zone->y;
1311    zone->x = x;
1312    zone->y = y;
1313    evas_object_move(zone->bg_object, x, y);
1314    evas_object_move(zone->bg_event_object, x, y);
1315    evas_object_move(zone->bg_clip_object, x, y);
1316
1317    ev = E_NEW(E_Event_Zone_Move_Resize, 1);
1318    if (ev)
1319      {
1320         ev->zone = zone;
1321         e_object_ref(E_OBJECT(ev->zone));
1322         ecore_event_add(E_EVENT_ZONE_MOVE_RESIZE, ev, _e_zone_event_generic_free, NULL);
1323      }
1324
1325    e_zone_bg_reconfigure(zone);
1326    e_zone_reconfigure_clients(zone, dx, dy, 0, 0);
1327 }
1328
1329 EINTERN void
1330 e_zone_resize(E_Zone *zone,
1331               int w,
1332               int h)
1333 {
1334    E_Event_Zone_Move_Resize *ev;
1335    int dw, dh;
1336
1337    E_OBJECT_CHECK(zone);
1338    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1339
1340    if ((w == zone->w) && (h == zone->h)) return;
1341
1342    dw = w - zone->w;
1343    dh = h - zone->h;
1344    zone->w = w;
1345    zone->h = h;
1346    evas_object_resize(zone->bg_object, w, h);
1347    evas_object_resize(zone->bg_event_object, w, h);
1348    evas_object_resize(zone->bg_clip_object, w, h);
1349
1350    ev = E_NEW(E_Event_Zone_Move_Resize, 1);
1351    if (ev)
1352      {
1353         ev->zone = zone;
1354         e_object_ref(E_OBJECT(ev->zone));
1355         ecore_event_add(E_EVENT_ZONE_MOVE_RESIZE, ev,
1356                         _e_zone_event_generic_free, NULL);
1357      }
1358
1359    e_zone_bg_reconfigure(zone);
1360    e_zone_reconfigure_clients(zone, 0, 0, dw, dh);
1361 }
1362
1363 EINTERN Eina_Bool
1364 e_zone_move_resize(E_Zone *zone,
1365                    int x,
1366                    int y,
1367                    int w,
1368                    int h)
1369 {
1370    E_Event_Zone_Move_Resize *ev;
1371    int dx, dy, dw, dh;
1372
1373    E_OBJECT_CHECK_RETURN(zone, EINA_FALSE);
1374    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE);
1375
1376    if ((x == zone->x) && (y == zone->y) && (w == zone->w) && (h == zone->h))
1377      return EINA_FALSE;
1378
1379    dx = x - zone->x;
1380    dy = y - zone->y;
1381    dw = w - zone->w;
1382    dh = h - zone->h;
1383    zone->x = x;
1384    zone->y = y;
1385    zone->w = w;
1386    zone->h = h;
1387
1388    evas_object_move(zone->bg_object, x, y);
1389    evas_object_move(zone->bg_event_object, x, y);
1390    evas_object_move(zone->bg_clip_object, x, y);
1391    evas_object_resize(zone->bg_object, w, h);
1392    evas_object_resize(zone->bg_event_object, w, h);
1393    evas_object_resize(zone->bg_clip_object, w, h);
1394
1395    ev = E_NEW(E_Event_Zone_Move_Resize, 1);
1396    if (ev)
1397      {
1398         ev->zone = zone;
1399         e_object_ref(E_OBJECT(ev->zone));
1400         ecore_event_add(E_EVENT_ZONE_MOVE_RESIZE, ev,
1401                         _e_zone_event_generic_free, NULL);
1402      }
1403
1404    e_zone_bg_reconfigure(zone);
1405    e_zone_reconfigure_clients(zone, dx, dy, dw, dh);
1406    return EINA_TRUE;
1407 }
1408
1409 E_API E_Zone *
1410 e_zone_current_get(void)
1411 {
1412    Eina_List *l = NULL;
1413    E_Zone *zone;
1414
1415    if (!starting)
1416      {
1417         int x, y;
1418
1419         e_input_device_pointer_xy_get(NULL, &x, &y);
1420
1421         EINA_LIST_FOREACH(e_comp->zones, l, zone)
1422           {
1423              if (E_INSIDE(x, y, zone->x, zone->y, zone->w, zone->h))
1424                return zone;
1425           }
1426      }
1427    if (!e_comp->zones) return NULL;
1428    return eina_list_data_get(e_comp->zones);
1429 }
1430
1431 EINTERN E_Zone *
1432 e_zone_get_by_id(int id)
1433 {
1434    Eina_List *l = NULL;
1435    E_Zone *zone;
1436
1437    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1438      {
1439         if (zone->id == id)
1440           {
1441              return zone;
1442           }
1443      }
1444
1445    ELOGF("E_ZONE", "No zone id:%d", NULL, id);
1446    return NULL;
1447 }
1448
1449 EINTERN E_Zone *
1450 e_zone_get_by_position(int x, int y)
1451 {
1452    Eina_List *l = NULL;
1453    E_Zone *zone;
1454
1455    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1456      {
1457         if (E_INSIDE(x, y, zone->x, zone->y, zone->w, zone->h))
1458           {
1459              return zone;
1460           }
1461      }
1462
1463    ELOGF("E_ZONE", "No zone under position(%d,%d)", NULL, x, y);
1464    return NULL;
1465 }
1466
1467 EINTERN void
1468 e_zone_bg_reconfigure(E_Zone *zone)
1469 {
1470    E_OBJECT_CHECK(zone);
1471    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1472
1473    e_bg_zone_update(zone, E_BG_TRANSITION_CHANGE);
1474 }
1475
1476 EINTERN void
1477 e_zone_desk_count_set(E_Zone *zone,
1478                       int x_count,
1479                       int y_count)
1480 {
1481    E_Desk **new_desks;
1482    E_Desk *desk, *new_desk;
1483    E_Client *ec;
1484    E_Event_Zone_Desk_Count_Set *ev;
1485    int x, y, xx, yy, moved, nx, ny;
1486
1487    E_OBJECT_CHECK(zone);
1488    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1489
1490    xx = x_count;
1491    if (xx < 1) xx = 1;
1492    yy = y_count;
1493    if (yy < 1) yy = 1;
1494
1495    /* Orphaned window catcher; in case desk count gets reset */
1496    moved = 0;
1497    if (zone->desk_x_current >= xx) moved = 1;
1498    if (zone->desk_y_current >= yy) moved = 1;
1499    if (moved)
1500      {
1501         nx = zone->desk_x_current;
1502         ny = zone->desk_y_current;
1503         if (zone->desk_x_current >= xx) nx = xx - 1;
1504         if (zone->desk_y_current >= yy) ny = yy - 1;
1505         e_desk_show(e_desk_at_xy_get(zone, nx, ny));
1506      }
1507
1508    new_desks = malloc(xx * yy * sizeof(E_Desk *));
1509    if (!new_desks) return;
1510    for (x = 0; x < xx; x++)
1511      {
1512         for (y = 0; y < yy; y++)
1513           {
1514              if ((x < zone->desk_x_count) && (y < zone->desk_y_count))
1515                desk = zone->desks[x + (y * zone->desk_x_count)];
1516              else
1517                desk = e_desk_new(zone, x, y);
1518              new_desks[x + (y * xx)] = desk;
1519           }
1520      }
1521
1522    /* catch windows that have fallen off the end if we got smaller */
1523    if (xx < zone->desk_x_count)
1524      {
1525         for (y = 0; y < zone->desk_y_count; y++)
1526           {
1527              new_desk = zone->desks[xx - 1 + (y * zone->desk_x_count)];
1528              for (x = xx; x < zone->desk_x_count; x++)
1529                {
1530                   desk = zone->desks[x + (y * zone->desk_x_count)];
1531
1532                   E_CLIENT_FOREACH(ec)
1533                     {
1534                        if (e_desk_has_ec(desk, ec))
1535                          e_desk_client_add(new_desk, ec);
1536                     }
1537                   e_object_del(E_OBJECT(desk));
1538                }
1539           }
1540      }
1541    if (yy < zone->desk_y_count)
1542      {
1543         for (x = 0; x < zone->desk_x_count; x++)
1544           {
1545              new_desk = zone->desks[x + ((yy - 1) * zone->desk_x_count)];
1546              for (y = yy; y < zone->desk_y_count; y++)
1547                {
1548                   desk = zone->desks[x + (y * zone->desk_x_count)];
1549
1550                   E_CLIENT_FOREACH(ec)
1551                     {
1552                        if (e_desk_has_ec(desk, ec))
1553                          e_desk_client_add(new_desk, ec);
1554                     }
1555                   e_object_del(E_OBJECT(desk));
1556                }
1557           }
1558      }
1559    free(zone->desks);
1560    zone->desks = new_desks;
1561
1562    zone->desk_x_count = xx;
1563    zone->desk_y_count = yy;
1564    e_config->zone_desks_x_count = xx;
1565    e_config->zone_desks_y_count = yy;
1566    e_config_save_queue();
1567
1568    /* Cannot call desk_current_get until the zone desk counts have been set
1569     * or else we end up with a "white background" because desk_current_get will
1570     * return NULL.
1571     */
1572    desk = e_desk_current_get(zone);
1573    if (desk)
1574      {
1575         /* need to simulate "startup" conditions to force desk show to reevaluate here */
1576         int s = starting;
1577         desk->visible = 0;
1578         starting = 1;
1579         e_desk_show(desk);
1580         starting = s;
1581      }
1582
1583    ev = E_NEW(E_Event_Zone_Desk_Count_Set, 1);
1584    if (!ev) return;
1585    ev->zone = zone;
1586    e_object_ref(E_OBJECT(ev->zone));
1587    ecore_event_add(E_EVENT_ZONE_DESK_COUNT_SET, ev,
1588                    _e_zone_event_generic_free, NULL);
1589 }
1590
1591 EINTERN void
1592 e_zone_desk_count_get(E_Zone *zone,
1593                       int *x_count,
1594                       int *y_count)
1595 {
1596    E_OBJECT_CHECK(zone);
1597    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1598
1599    if (x_count) *x_count = zone->desk_x_count;
1600    if (y_count) *y_count = zone->desk_y_count;
1601 }
1602
1603 EINTERN Eina_Bool
1604 e_zone_obstacle_add(E_Zone *zone, E_Client *ec, Eina_Rectangle *geom, Eina_Bool vertical)
1605 {
1606    E_Zone_Obstacle *obs;
1607    Eina_List *l;
1608
1609    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
1610    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1611    EINA_SAFETY_ON_NULL_RETURN_VAL(geom, EINA_FALSE);
1612    EINA_SAFETY_ON_FALSE_RETURN_VAL(e_zone_has_ec(zone, ec), EINA_FALSE);
1613
1614    // check in the list...
1615    EINA_LIST_FOREACH(zone->obstacles, l, obs)
1616      {
1617         if (obs->ec == ec)
1618           {
1619              ELOGF("E_ZONE", "Already ADDED in the obstacle list", ec);
1620              return EINA_TRUE;
1621           }
1622      }
1623
1624    obs = E_NEW(E_Zone_Obstacle, 1);
1625    if (!obs) return EINA_FALSE;
1626    obs->ec = ec;
1627    obs->x = geom->x;
1628    obs->y = geom->y;
1629    obs->w = geom->w;
1630    obs->h = geom->h;
1631    obs->vertical = !!vertical;
1632
1633    ELOGF("E_ZONE", "ADD obstacle... geo(%d,%d,%dx%d), vertical:%d", ec, obs->x, obs->y, obs->w, obs->h, obs->vertical);
1634
1635    zone->obstacles = eina_list_append(zone->obstacles, obs);
1636
1637    e_zone_useful_geometry_dirty(zone);
1638    return EINA_TRUE;
1639 }
1640
1641 EINTERN Eina_Bool
1642 e_zone_obstacle_update(E_Zone *zone, E_Client *ec, Eina_Rectangle *geom, Eina_Bool vertical)
1643 {
1644    E_Zone_Obstacle *obs;
1645    Eina_List *l;
1646    Eina_Bool changed = EINA_FALSE;
1647
1648    if (!zone) return EINA_FALSE;
1649    if (!ec) return EINA_FALSE;
1650    if (!e_zone_has_ec(zone, ec)) return EINA_FALSE;
1651
1652    EINA_LIST_FOREACH(zone->obstacles, l, obs)
1653      {
1654         if (obs->ec == ec)
1655           break;
1656      }
1657
1658    if (!obs)
1659      {
1660         ELOGF("E_ZONE", "Not found in the obstacle list", ec);
1661         return EINA_FALSE;
1662      }
1663
1664    if (geom)
1665      {
1666         if ((obs->x != geom->x) ||
1667             (obs->y != geom->y) ||
1668             (obs->w != geom->w) ||
1669             (obs->h != geom->h))
1670           {
1671              obs->x = geom->x;
1672              obs->y = geom->y;
1673              obs->w = geom->w;
1674              obs->h = geom->h;
1675              changed = EINA_TRUE;
1676           }
1677      }
1678
1679    if (obs->vertical != vertical)
1680      {
1681         obs->vertical = !!vertical;
1682         changed = EINA_TRUE;
1683      }
1684
1685    ELOGF("E_ZONE", "UPDATE obstacle... geo(%d,%d,%dx%d), vertical:%d", ec, obs->x, obs->y, obs->w, obs->h, obs->vertical);
1686
1687    if (changed)
1688      e_zone_useful_geometry_dirty(zone);
1689
1690    return EINA_TRUE;
1691 }
1692
1693 EINTERN void
1694 e_zone_obstacle_remove(E_Zone *zone, E_Client *ec)
1695 {
1696    E_Zone_Obstacle *obs;
1697    Eina_List *l, *ll;
1698
1699    if (!zone) return;
1700    if (!ec) return;
1701    if (!e_zone_has_ec(zone, ec)) return;
1702
1703    EINA_LIST_FOREACH_SAFE(zone->obstacles, l, ll, obs)
1704      {
1705         if (obs->ec == ec)
1706           {
1707              ELOGF("E_ZONE", "REMOVE obstacle...", ec);
1708              zone->obstacles = eina_list_remove_list(zone->obstacles, l);
1709              E_FREE(obs);
1710              break;
1711           }
1712      }
1713
1714    e_zone_useful_geometry_dirty(zone);
1715 }
1716
1717 static void
1718 _e_zone_useful_geometry_calc(const E_Zone *zone, E_Desk *desk, int *x, int *y, int *w, int *h)
1719 {
1720    Eina_Tiler *tiler;
1721    E_Zone_Obstacle *obs;
1722    Eina_List *l;
1723    int zx, zy, zw, zh;
1724    Eina_Iterator *it;
1725    Eina_Rectangle geom = { 0 } , *rect;
1726    int size = 0;
1727
1728    zx = zone->x;
1729    zy = zone->y;
1730    zw = zone->w;
1731    zh = zone->h;
1732
1733    if (desk)
1734      {
1735         zx = desk->geom.x;
1736         zy = desk->geom.y;
1737         zw = desk->geom.w;
1738         zh = desk->geom.h;
1739      }
1740
1741    tiler = eina_tiler_new(zw, zh);
1742    eina_tiler_tile_size_set(tiler, 1, 1);
1743    eina_tiler_rect_add(tiler, &(Eina_Rectangle){0, 0, zw, zh});
1744
1745    EINA_LIST_FOREACH(zone->obstacles, l, obs)
1746      {
1747         if (!E_INTERSECTS(obs->x, obs->y, obs->w, obs->h, zx, zy, zw, zh)) continue;
1748
1749         if (obs->vertical)
1750           eina_tiler_rect_del(tiler, &(Eina_Rectangle){obs->x - zx, 0, obs->w, zh});
1751         else
1752           eina_tiler_rect_del(tiler, &(Eina_Rectangle){0, obs->y - zy, zw, obs->h});
1753      }
1754
1755    it = eina_tiler_iterator_new(tiler);
1756    EINA_ITERATOR_FOREACH(it, rect)
1757      {
1758         if (rect->w * rect->h < size) continue;
1759         size = rect->w * rect->h;
1760         geom = *rect;
1761      }
1762    eina_iterator_free(it);
1763    eina_tiler_free(tiler);
1764
1765    if (x) *x = geom.x + zx;
1766    if (y) *y = geom.y + zy;
1767    if (w) *w = geom.w;
1768    if (h) *h = geom.h;
1769 }
1770
1771 /**
1772  * Get (or calculate) the useful (or free, without any shelves) area.
1773  */
1774 E_API void
1775 e_zone_useful_geometry_get(E_Zone *zone,
1776                            int *x,
1777                            int *y,
1778                            int *w,
1779                            int *h)
1780 {
1781    E_OBJECT_CHECK(zone);
1782    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1783
1784    if (x) *x = zone->x;
1785    if (y) *y = zone->y;
1786    if (w) *w = zone->w;
1787    if (h) *h = zone->h;
1788 }
1789
1790 EINTERN void
1791 e_zone_desk_useful_geometry_get(E_Zone *zone, E_Desk *desk, int *x, int *y, int *w, int *h, Eina_Bool consider_obstacle_area)
1792 {
1793    E_OBJECT_CHECK(zone);
1794    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1795    E_OBJECT_CHECK(desk);
1796    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1797    E_OBJECT_CHECK(desk->zone);
1798
1799    if (desk->zone != zone)
1800      {
1801         ELOGF("E_ZONE", "CRI... Zone(%d) and Desk's zone(%d) mismatch!", NULL, zone->id, desk->zone->id);
1802         return;
1803      }
1804
1805    if (consider_obstacle_area)
1806      _e_zone_useful_geometry_calc(zone, desk, x, y, w, h);
1807    else
1808      e_zone_useful_geometry_get(zone, x, y, w, h);
1809 }
1810
1811 /**
1812  * Mark as dirty so e_zone_useful_geometry_get() will need to recalculate.
1813  *
1814  * Call this function when shelves are added or important properties changed.
1815  */
1816 EINTERN void
1817 e_zone_useful_geometry_dirty(E_Zone *zone)
1818 {
1819    E_Event_Zone_Useful_Geometry_Change *ev;
1820
1821    E_OBJECT_CHECK(zone);
1822    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1823
1824    ev = E_NEW(E_Event_Zone_Useful_Geometry_Change, 1);
1825    if (!ev) return;
1826    ev->zone = zone;
1827    e_object_ref(E_OBJECT(ev->zone));
1828    ecore_event_add(E_EVENT_ZONE_USEFUL_GEOMETRY_CHANGE, ev, _e_zone_event_generic_free, NULL);
1829 }
1830
1831 E_API void
1832 e_zone_display_state_set(E_Zone *zone, E_Zone_Display_State state)
1833 {
1834    E_Event_Zone_Display_State_Change *ev;
1835
1836    E_OBJECT_CHECK(zone);
1837    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1838
1839    zone->display_state = state;
1840
1841    wl_signal_emit_mutable(&PRI(zone)->events.display_state_change, NULL);
1842    _e_zone_hook_call(E_ZONE_HOOK_DISPLAY_STATE_CHANGE, zone);
1843
1844    ev = E_NEW(E_Event_Zone_Display_State_Change, 1);
1845    if (!ev) return;
1846    ev->zone = zone;
1847    e_object_ref(E_OBJECT(ev->zone));
1848    ecore_event_add(E_EVENT_ZONE_DISPLAY_STATE_CHANGE, ev, _e_zone_event_generic_free, NULL);
1849 }
1850
1851 EINTERN E_Zone_Display_State
1852 e_zone_display_state_get(E_Zone *zone)
1853 {
1854    E_OBJECT_CHECK_RETURN(zone, E_ZONE_DISPLAY_STATE_OFF);
1855    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, E_ZONE_DISPLAY_STATE_OFF);
1856
1857    return zone->display_state;
1858 }
1859
1860 E_API void
1861 e_zone_orientation_callback_set(E_Zone *zone,
1862                                 E_Zone_Cb_Orientation_Block_Set block_set,
1863                                 E_Zone_Cb_Orientation_Force_Update_Add force_update_add,
1864                                 E_Zone_Cb_Orientation_Force_Update_Del force_update_del)
1865 {
1866    E_OBJECT_CHECK(zone);
1867    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1868
1869    zone->orientation.block_set = block_set;
1870    zone->orientation.force_update_add = force_update_add;
1871    zone->orientation.force_update_del = force_update_del;
1872 }
1873
1874 E_API Eina_Bool
1875 e_zone_orientation_block_set(E_Zone *zone, const char* name_hint,  Eina_Bool set)
1876 {
1877    E_OBJECT_CHECK_RETURN(zone, EINA_FALSE);
1878    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE);
1879
1880    if (zone->orientation.block_set)
1881      return zone->orientation.block_set(zone, name_hint, set);
1882
1883    return EINA_FALSE;
1884 }
1885
1886 E_API void
1887 e_zone_orientation_force_update_add(E_Zone *zone, E_Client *client)
1888 {
1889    E_OBJECT_CHECK(zone);
1890    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1891
1892    if (zone->orientation.force_update_add)
1893      zone->orientation.force_update_add(zone, (void*)client);
1894 }
1895
1896 E_API void
1897 e_zone_orientation_force_update_del(E_Zone *zone, E_Client *client)
1898 {
1899    E_OBJECT_CHECK(zone);
1900    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1901
1902    if (zone->orientation.force_update_del)
1903      zone->orientation.force_update_del(zone, (void*)client);
1904 }
1905
1906 /* local subsystem functions */
1907 static void
1908 _e_zone_free(E_Zone *zone)
1909 {
1910    int x, y;
1911    E_Zone_Obstacle *obs;
1912
1913    if(zone->focus) e_focus_del(zone->focus);
1914
1915    /* Delete the hooks */
1916    E_FREE_LIST(zone->ec_hooks, e_client_hook_del);
1917
1918    /* Delete the object event callbacks */
1919    evas_object_event_callback_del(zone->bg_event_object,
1920                                   EVAS_CALLBACK_MOUSE_DOWN,
1921                                   _e_zone_cb_bg_mouse_down);
1922    evas_object_event_callback_del(zone->bg_event_object,
1923                                   EVAS_CALLBACK_MOUSE_UP,
1924                                   _e_zone_cb_bg_mouse_up);
1925
1926    E_FREE_FUNC(zone->cur_mouse_action, e_object_unref);
1927
1928    /* remove handlers */
1929    E_FREE_LIST(zone->handlers, ecore_event_handler_del);
1930
1931    if (zone->name) eina_stringshare_del(zone->name);
1932    e_comp->zones = eina_list_remove(e_comp->zones, zone);
1933    evas_object_del(zone->bg_event_object);
1934    evas_object_del(zone->bg_clip_object);
1935    evas_object_del(zone->bg_object);
1936    if (zone->prev_bg_object) evas_object_del(zone->prev_bg_object);
1937    if (zone->transition_object) evas_object_del(zone->transition_object);
1938
1939    evas_object_del(zone->base);
1940    evas_object_del(zone->over);
1941
1942    /* free desks */
1943    for (x = 0; x < zone->desk_x_count; x++)
1944      {
1945         for (y = 0; y < zone->desk_y_count; y++)
1946           e_object_del(E_OBJECT(zone->desks[x + (y * zone->desk_x_count)]));
1947      }
1948    EINA_LIST_FREE(zone->obstacles, obs)
1949      {
1950         E_FREE(obs);
1951      }
1952    free(zone->desks);
1953    free(zone->output_id);
1954
1955    _e_zone_private_finish(zone);
1956    free(zone);
1957 }
1958
1959 static void
1960 _e_zone_cb_bg_mouse_down(void *data,
1961                          Evas *evas       EINA_UNUSED,
1962                          Evas_Object *obj EINA_UNUSED,
1963                          void *event_info)
1964 {
1965    E_Zone *zone;
1966
1967    zone = data;
1968    if (e_comp_util_mouse_grabbed()) return;
1969
1970    if (!zone->cur_mouse_action)
1971      {
1972         zone->cur_mouse_action =
1973           e_bindings_mouse_down_evas_event_handle(E_BINDING_CONTEXT_ZONE,
1974                                              E_OBJECT(zone), event_info);
1975         if (zone->cur_mouse_action)
1976           {
1977              if ((!zone->cur_mouse_action->func.end_mouse) &&
1978                  (!zone->cur_mouse_action->func.end))
1979                zone->cur_mouse_action = NULL;
1980              if (zone->cur_mouse_action)
1981                e_object_ref(E_OBJECT(zone->cur_mouse_action));
1982           }
1983      }
1984 }
1985
1986 static void
1987 _e_zone_cb_bg_mouse_up(void *data,
1988                        Evas *evas       EINA_UNUSED,
1989                        Evas_Object *obj EINA_UNUSED,
1990                        void *event_info)
1991 {
1992    E_Zone *zone;
1993
1994    zone = data;
1995    if (zone->cur_mouse_action)
1996      {
1997         E_Binding_Event_Mouse_Button event;
1998
1999         e_bindings_evas_event_mouse_up_button_convert(event_info, &event);
2000         if (zone->cur_mouse_action->func.end_mouse)
2001           zone->cur_mouse_action->func.end_mouse(E_OBJECT(zone), "", &event);
2002         else if (zone->cur_mouse_action->func.end)
2003           zone->cur_mouse_action->func.end(E_OBJECT(zone), "");
2004
2005         e_object_unref(E_OBJECT(zone->cur_mouse_action));
2006         zone->cur_mouse_action = NULL;
2007      }
2008    else
2009      {
2010         E_Binding_Event_Mouse_Button event;
2011
2012         e_bindings_ecore_event_mouse_button_convert(event_info, &event);
2013         e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_ZONE,
2014                                          E_OBJECT(zone), &event);
2015      }
2016 }
2017
2018 static void
2019 _e_zone_event_generic_free(void *data EINA_UNUSED, void *ev)
2020 {
2021    struct _E_Event_Zone_Generic *e;
2022    // also handes E_Event_Zone_Add, E_Event_Zone_Del, E_Event_Zone_Stow,
2023    // E_Event_Zone_Unstow, E_Event_Zone_Desk_Count_Set due to them all
2024    // having the same content
2025
2026    e = ev;
2027    e_object_unref(E_OBJECT(e->zone));
2028    free(e);
2029 }
2030
2031 static void
2032 _e_zone_object_del_attach(void *o)
2033 {
2034    E_Zone *zone;
2035    E_Event_Zone_Del *ev;
2036
2037    zone = o;
2038    if (stopping) return;
2039    ev = E_NEW(E_Event_Zone_Del, 1);
2040    if (!ev) return;
2041    ev->zone = zone;
2042    e_object_ref(E_OBJECT(ev->zone));
2043    ecore_event_add(E_EVENT_ZONE_DEL, ev, _e_zone_event_generic_free, NULL);
2044
2045   if (zone->global)
2046     wl_global_destroy(zone->global);
2047 }
2048
2049 static void
2050 _e_zone_hooks_clean(void)
2051 {
2052    Eina_Inlist *l;
2053    E_Zone_Hook *zh;
2054    unsigned int x;
2055
2056    for (x = 0; x < E_ZONE_HOOK_LAST; x++)
2057      EINA_INLIST_FOREACH_SAFE(_e_zone_hooks[x], l, zh)
2058        {
2059           if (!zh->delete_me) continue;
2060           _e_zone_hooks[x] = eina_inlist_remove(_e_zone_hooks[x], EINA_INLIST_GET(zh));
2061           free(zh);
2062        }
2063 }
2064
2065 static Eina_Bool
2066 _e_zone_hook_call(E_Zone_Hook_Point hookpoint, E_Zone *zone)
2067 {
2068    E_Zone_Hook *zh;
2069
2070    e_object_ref(E_OBJECT(zone));
2071    _e_zone_hooks_walking++;
2072    EINA_INLIST_FOREACH(_e_zone_hooks[hookpoint], zh)
2073      {
2074         if (zh->delete_me) continue;
2075         zh->func(zh->data, zone);
2076      }
2077    _e_zone_hooks_walking--;
2078    if ((_e_zone_hooks_walking == 0) && (_e_zone_hooks_delete > 0))
2079      _e_zone_hooks_clean();
2080
2081    return !!e_object_unref(E_OBJECT(zone));
2082 }
2083
2084 E_API E_Zone_Hook *
2085 e_zone_hook_add(E_Zone_Hook_Point hookpoint, E_Zone_Hook_Cb func, const void *data)
2086 {
2087    E_Zone_Hook *zh;
2088
2089    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_ZONE_HOOK_LAST, NULL);
2090    zh = E_NEW(E_Zone_Hook, 1);
2091    if (!zh) return NULL;
2092    zh->hookpoint = hookpoint;
2093    zh->func = func;
2094    zh->data = (void*)data;
2095    _e_zone_hooks[hookpoint] = eina_inlist_append(_e_zone_hooks[hookpoint], EINA_INLIST_GET(zh));
2096    return zh;
2097 }
2098
2099 E_API void
2100 e_zone_hook_del(E_Zone_Hook *zh)
2101 {
2102    zh->delete_me = 1;
2103    if (_e_zone_hooks_walking == 0)
2104      {
2105         _e_zone_hooks[zh->hookpoint] = eina_inlist_remove(_e_zone_hooks[zh->hookpoint], EINA_INLIST_GET(zh));
2106         free(zh);
2107      }
2108    else
2109      _e_zone_hooks_delete++;
2110 }
2111
2112 static void
2113 _e_zone_cb_get_splitscreen(struct wl_listener *listener, void *data)
2114 {
2115   E_Zone_Private *priv;
2116   E_Desk *desk;
2117   struct ds_tizen_splitscreen *splitscreen;
2118
2119   priv = container_of(listener, E_Zone_Private, screen_get_splitscreen);
2120   splitscreen = (struct ds_tizen_splitscreen *)data;
2121
2122   // The splitscreen_regions are the e_desk_areas associated with this
2123   // E_Zone(E_Desk) and these are already created by the e20 module with the
2124   // specific policy. So e20 sends the splitscreen_regions associated with each
2125   // e_desk_area.
2126   desk = e_desk_current_get(priv->zone);
2127   if (!e_desk_splitscreen_enable(desk, splitscreen))
2128     {
2129        ELOGF("E_Zone", "e_desk_splitscreen_enable() failed.", NULL);
2130        return;
2131     }
2132
2133   ELOGF("E_Zone", "Enable SplitScreen. zone_id:%d", NULL, priv->zone->id);
2134 }
2135
2136 static void
2137 _e_zone_cb_screen_destroy(struct wl_listener *listener EINA_UNUSED, void *data EINA_UNUSED)
2138 {
2139   E_Zone_Private *priv;
2140
2141   priv = container_of(listener, E_Zone_Private, screen_destroy);
2142   priv->tizen_screen = NULL;
2143 }
2144
2145 EINTERN E_Zone *
2146 e_zone_screen_new(int num, int w, int h)
2147 {
2148   E_Zone *zone;
2149   E_Zone_Private *priv;
2150
2151   zone = e_zone_new(num, num, 0, 0, w, h);
2152   EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL);
2153
2154   priv = PRI(zone);
2155
2156   priv->tizen_screen = ds_tizen_screen_create(e_comp_wl->wl.disp);
2157   EINA_SAFETY_ON_NULL_RETURN_VAL(priv->tizen_screen, NULL);
2158
2159   priv->screen_destroy.notify = _e_zone_cb_screen_destroy;
2160   ds_tizen_screen_add_destroy_listener(priv->tizen_screen, &priv->screen_destroy);
2161
2162   priv->screen_get_splitscreen.notify = _e_zone_cb_get_splitscreen;
2163   ds_tizen_screen_add_get_splitscreen_listener(priv->tizen_screen, &priv->screen_get_splitscreen);
2164
2165   return zone;
2166 }
2167
2168 E_API Eina_Bool
2169 e_zone_screen_splitscreen_enable(E_Zone *zone)
2170 {
2171   E_OBJECT_CHECK_RETURN(zone, EINA_FALSE);
2172   E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE);
2173
2174   if (zone->splitscreen_enabled)
2175     {
2176        ELOGF("E_Zone", "Splitscreen is already enabled. zone_id:%d", NULL,
2177               zone->id);
2178        return EINA_TRUE;
2179     }
2180
2181   zone->splitscreen_enabled = EINA_TRUE;
2182
2183   return EINA_TRUE;
2184 }
2185
2186 static void
2187 _e_client_event_zone_set_free(void *d EINA_UNUSED, E_Event_Client_Zone_Set *ev)
2188 {
2189    UNREFD(ev->ec, 5);
2190    e_object_unref(E_OBJECT(ev->ec));
2191    e_object_unref(E_OBJECT(ev->zone));
2192    free(ev);
2193 }
2194
2195 static void
2196 _e_zone_client_set(E_Zone *zone, E_Client *ec)
2197 {
2198    E_Event_Client_Zone_Set *ev;
2199
2200    ev = E_NEW(E_Event_Client_Zone_Set, 1);
2201    if (!ev) return;
2202
2203    /* if the window does not lie in the new zone, move it so that it does */
2204    if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))
2205      {
2206         int x, y;
2207
2208         x = ec->x, y = ec->y;
2209
2210         /* keep window from hanging off bottom and left */
2211         if (x + ec->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + ec->w);
2212         if (y + ec->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + ec->h);
2213
2214         /* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
2215         if (x < zone->x) x = zone->x;
2216         if (y < zone->y) y = zone->y;
2217
2218         if (!E_INTERSECTS(x, y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))
2219           {
2220              /* still not in zone at all, so just move it to closest edge */
2221              if (x < zone->x) x = zone->x;
2222              if (x >= zone->x + zone->w) x = zone->x + zone->w - ec->w;
2223              if (y < zone->y) y = zone->y;
2224              if (y >= zone->y + zone->h) y = zone->y + zone->h - ec->h;
2225           }
2226         evas_object_move(ec->frame, x, y);
2227      }
2228
2229    ec->zone = zone; // FIXME: This line must be deleted.
2230
2231    ev->ec = ec;
2232    REFD(ec, 5);
2233    e_object_ref(E_OBJECT(ec));
2234    ev->zone = zone;
2235    e_object_ref(E_OBJECT(zone));
2236
2237    ecore_event_add(E_EVENT_CLIENT_ZONE_SET, ev, (Ecore_End_Cb)_e_client_event_zone_set_free, NULL);
2238 }
2239
2240 EINTERN void
2241 e_zone_client_add(E_Zone *zone, E_Client *ec)
2242 {
2243    E_Desk *desk;
2244    E_Zone_Private_Client *zone_client;
2245
2246    EINA_SAFETY_ON_NULL_RETURN(zone);
2247    EINA_SAFETY_ON_NULL_RETURN(ec);
2248    if (e_zone_has_ec(zone, ec)) return;
2249
2250    ELOGF("ZONE", "CLIENT ADD", ec);
2251
2252    zone_client = E_NEW(E_Zone_Private_Client, 1);
2253    EINA_SAFETY_ON_NULL_RETURN(zone_client);
2254
2255    zone_client->zone = zone;
2256    zone_client->ec = ec;
2257
2258    // e_client listeners
2259    zone_client->client_destroy.notify = _zone_cb_client_destroy;
2260    e_client_destroy_listener_add(ec, &zone_client->client_destroy);
2261
2262    zone_client->client_eval_post_new_client.notify = _zone_cb_client_eval_post_new_client;
2263    e_client_eval_post_new_client_listener_add(ec, &zone_client->client_eval_post_new_client);
2264
2265    zone_client->client_focus_set.notify = _zone_cb_client_focus_set;
2266    e_client_focus_set_listener_add(ec, &zone_client->client_focus_set);
2267
2268 #ifdef REFACTOR_DESK_AREA
2269 #else
2270    zone_client->client_iconify.notify = _zone_cb_client_iconify;
2271    e_client_iconify_listener_add(ec, &zone_client->client_iconify);
2272
2273    zone_client->client_uniconify.notify = _zone_cb_client_uniconify;
2274    e_client_uniconify_listener_add(ec, &zone_client->client_uniconify);
2275
2276    zone_client->client_stick.notify = _zone_cb_client_stick;
2277    e_client_stick_listener_add(ec, &zone_client->client_stick);
2278
2279    zone_client->client_unstick.notify = _zone_cb_client_unstick;
2280    e_client_unstick_listener_add(ec, &zone_client->client_unstick);
2281
2282    zone_client->client_maximize.notify = _zone_cb_client_maximize;
2283    e_client_maximize_listener_add(ec, &zone_client->client_maximize);
2284
2285    zone_client->client_unmaximize.notify = _zone_cb_client_unmaximize;
2286    e_client_unmaximize_listener_add(ec, &zone_client->client_unmaximize);
2287
2288    zone_client->client_activate_done.notify = _zone_cb_client_activate_done;
2289    e_client_activate_done_listener_add(ec, &zone_client->client_activate_done);
2290
2291    zone_client->client_fullscreen.notify = _zone_cb_client_fullscreen;
2292    e_client_fullscreen_listener_add(ec, &zone_client->client_fullscreen);
2293
2294    zone_client->client_unfullscreen.notify = _zone_cb_client_unfullscreen;
2295    e_client_unfullscreen_listener_add(ec, &zone_client->client_unfullscreen);
2296 #endif
2297
2298    _e_zone_client_set(zone, ec);
2299    _e_zone_client_data_set(zone, ec);
2300
2301    wl_signal_emit_mutable(&PRI(zone)->events.client_add, ec);
2302
2303    // Currently, ec is set to the current desk now.
2304    // At this moment, ec should not belong to any desk
2305    desk = e_desk_current_get(zone);
2306    e_desk_client_add(desk, ec);
2307
2308    if (ec->override)
2309      e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
2310    else
2311      e_client_layer_set(ec, E_LAYER_CLIENT_NORMAL);
2312
2313    e_client_res_change_geometry_save(ec);
2314    e_client_res_change_geometry_restore(ec);
2315    ec->pre_res_change.valid = 0;
2316 }
2317
2318 EINTERN Eina_Bool
2319 e_zone_has_ec(E_Zone *zone, E_Client *ec)
2320 {
2321    E_Zone *data;
2322
2323    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
2324
2325    data = evas_object_data_get(ec->frame, ZONE_EC_DATA_KEY);
2326    if (data == zone) return EINA_TRUE;
2327
2328    return EINA_FALSE;
2329 }
2330
2331 EINTERN Eina_Bool
2332 e_zone_is_displaying(E_Zone *zone)
2333 {
2334   Eina_Bool ret = EINA_FALSE;
2335
2336   EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
2337
2338   if (zone->display_state == E_ZONE_DISPLAY_STATE_ON)
2339     ret = EINA_TRUE;
2340
2341   return ret;
2342 }
2343
2344 #ifdef EC_IS_NOT_VISIBLE
2345 # undef EC_IS_NOT_VISIBLE
2346 #endif
2347 #define EC_IS_NOT_VISIBLE if (e_client_visibility_get(ec) != E_VISIBILITY_UNOBSCURED)
2348
2349 EINTERN Eina_Bool
2350 e_zone_visibility_calculate(E_Zone *zone)
2351 {
2352    E_Client *ec;
2353
2354    Eina_Tiler *t;
2355    Eina_Rectangle r, *_r;
2356    Eina_Iterator *it;
2357    Eina_Bool canvas_vis = EINA_TRUE;
2358    Eina_Bool ec_vis, ec_opaque, calc_region;
2359    Eina_Bool skip_rot_pending_show = EINA_FALSE;
2360    int skip_by_pending_show = 0;
2361    Eina_Bool is_above_show_pending = EINA_FALSE;
2362    Eina_Bool is_launching_effect = EINA_FALSE;
2363    Eina_Bool is_vis_on_skip = EINA_FALSE;
2364
2365    int x = 0, y = 0, w = 0, h = 0;
2366    const int edge = 1;
2367    E_Comp_Wl_Client_Data *cdata;
2368    Eina_List *changed_list = NULL;
2369    Eina_List *l = NULL;
2370    Eina_Bool effect_running = EINA_FALSE;
2371    Eina_Bool ec_frame_visible = EINA_FALSE;
2372    int calc_skip_type = 0;
2373
2374    Eina_Bool touched_win_changed = EINA_FALSE;
2375    E_Client *touched_ec;
2376
2377    Eina_Bool iconified_by_client = EINA_FALSE;
2378    Eina_Bool e_visibility_changed = EINA_FALSE;
2379
2380    if (!e_config->calc_vis_without_effect)
2381      {
2382         if (e_comp->animating) return EINA_FALSE;
2383      }
2384
2385    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
2386
2387    TRACE_DS_BEGIN(CLIENT:VISIBILITY CALCULATE);
2388
2389    t = eina_tiler_new(zone->w + zone->x + edge, zone->h + zone->y + edge);
2390    eina_tiler_tile_size_set(t, 1, 1);
2391
2392    if (e_zone_is_displaying(zone))
2393      {
2394         EINA_RECTANGLE_SET(&r, zone->x, zone->y, zone->w, zone->h);
2395         eina_tiler_rect_add(t, &r);
2396      }
2397    else
2398      {
2399         canvas_vis = EINA_FALSE;
2400      }
2401
2402    E_CLIENT_REVERSE_FOREACH(ec)
2403      {
2404         calc_skip_type = 0;
2405         if (e_object_is_del(E_OBJECT(ec))) continue;
2406         if (e_client_util_ignored_get(ec)) continue;
2407         if (!e_zone_has_ec(zone, ec)) continue;
2408         if (!ec->frame) continue;
2409         if (ec->visibility.skip) continue;
2410         if (ec->is_cursor) continue;
2411         cdata = e_client_cdata_get(ec);
2412         if (e_comp_wl_subsurface_check(ec)) continue;
2413         if ((!ec->first_mapped) &&
2414             (e_comp_object_content_type_get(ec->frame) == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)) continue;
2415
2416         /* TODO: need to check whether window intersects with entire screen, not zone. */
2417         /* if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h)) continue; */
2418
2419         if (!e_zone_is_displaying(zone))
2420           {
2421              if ((e_client_visibility_get(ec) == E_VISIBILITY_FULLY_OBSCURED) &&
2422                  (ec->visibility.last_sent_type != E_VISIBILITY_FULLY_OBSCURED))
2423                {
2424                   ec->visibility.changed = 1;
2425                }
2426           }
2427
2428         if (!e_config->calc_vis_without_effect)
2429           {
2430              if ((e_comp_object_is_animating(ec->frame)) ||
2431                  (evas_object_data_get(ec->frame, "effect_running")))
2432                {
2433                   effect_running = EINA_TRUE;
2434                   if (ec->launching)
2435                     is_launching_effect = EINA_TRUE;
2436                   continue;
2437                }
2438           }
2439
2440         e_client_geometry_get(ec, &x, &y, &w, &h);
2441         w = w + edge;
2442         h = h + edge;
2443
2444         ec_vis = ec_opaque = skip_rot_pending_show = is_vis_on_skip = EINA_FALSE;
2445         skip_by_pending_show = 0;
2446         calc_region = EINA_TRUE;
2447         ec_frame_visible = evas_object_visible_get(ec->frame);
2448         iconified_by_client = e_client_is_iconified_by_client(ec);
2449
2450         if (!ec->visible)
2451           {
2452              EC_IS_NOT_VISIBLE continue;
2453              calc_region = EINA_FALSE;
2454              calc_skip_type |= 0x01;
2455           }
2456         else if (!ec_frame_visible)
2457           {
2458              if (ec->e.state.rot.pending_show)
2459                {
2460                   calc_region = EINA_FALSE;
2461                   calc_skip_type |= 0x02;
2462                   skip_rot_pending_show = EINA_TRUE;
2463                   skip_by_pending_show = 1;
2464                }
2465              else if (ec->show_pending.count > 0)
2466                {
2467                   calc_region = EINA_FALSE;
2468                   calc_skip_type |= 0x100;
2469                   skip_by_pending_show = 2;
2470                }
2471              else
2472                {
2473                   if (cdata && !cdata->mapped)
2474                     {
2475                        EC_IS_NOT_VISIBLE continue;
2476                        calc_region = EINA_FALSE;
2477                        calc_skip_type |= 0x04;
2478                     }
2479
2480                   if (!ec->iconic)
2481                     {
2482                        EC_IS_NOT_VISIBLE continue;
2483                        calc_region = EINA_FALSE;
2484                        calc_skip_type |= 0x08;
2485                     }
2486                   else
2487                     {
2488                        if (iconified_by_client)
2489                          {
2490                             EC_IS_NOT_VISIBLE continue;
2491
2492                             E_Iconified_Type iconified_type;
2493                             iconified_type = e_client_iconified_type_get(ec);
2494                             if (iconified_type == E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT)
2495                               calc_skip_type |= 0x10;
2496                             else if (iconified_type == E_ICONIFIED_TYPE_DESK_ICONIFY_BY_CLIENT)
2497                               calc_skip_type |= 0x20;
2498                             else if (iconified_type == E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT)
2499                               calc_skip_type |= 0x40;
2500                             else
2501                               {
2502                                  ELOGF("POL_VIS", "CRI. Check iconified_type... cur type:%d", ec, iconified_type);
2503                                  calc_skip_type |= 0x80;
2504                               }
2505                             calc_region = EINA_FALSE;
2506                          }
2507                     }
2508
2509                   if (ec->bg_state)
2510                     {
2511                        EC_IS_NOT_VISIBLE continue;
2512                        calc_region = EINA_FALSE;
2513                        calc_skip_type |= 0x200;
2514                     }
2515                }
2516           }
2517
2518         if (ec->visibility.ignore_geometry)
2519           {
2520              calc_region = EINA_FALSE;
2521              if (e_zone_is_displaying(zone) && ec_frame_visible)
2522                ec_vis = EINA_TRUE;
2523           }
2524
2525         if (canvas_vis)
2526           {
2527              if (calc_region &&
2528                  (!ec->visibility.force_obscured) &&
2529                  (!ec->iconic || (ec->iconic && (!iconified_by_client))))
2530                {
2531                   it = eina_tiler_iterator_new(t);
2532                   EINA_ITERATOR_FOREACH(it, _r)
2533                     {
2534                        if (E_INTERSECTS(x, y, w, h,
2535                                         _r->x, _r->y, _r->w, _r->h))
2536                          {
2537                             ec_vis = EINA_TRUE;
2538                             break;
2539                          }
2540                     }
2541                   eina_iterator_free(it);
2542                }
2543           }
2544
2545         if (ec_vis)
2546           {
2547              /* unobscured case */
2548              EC_IS_NOT_VISIBLE
2549                {
2550                   if ((!is_above_show_pending) &&
2551                       ((!effect_running) ||
2552                        ((effect_running) && (!is_launching_effect))))
2553                     {
2554                        /* previous state is obscured: -1 or 1 */
2555                        e_client_visibility_set(ec, E_VISIBILITY_UNOBSCURED);
2556                        ec->visibility.changed = 1;
2557                        ELOGF("POL_VIS", "CLIENT VIS ON.  argb:%d, opaque:%2d, frame_v:%d, ignore_geometry:%d, cdata:%p, geo(%d,%d,%dx%d), asp:%d, er:%d, le:%d", ec, ec->argb, ec->visibility.opaque, ec_frame_visible, ec->visibility.ignore_geometry, cdata, x, y, w, h, is_above_show_pending, effect_running, is_launching_effect);
2558                     }
2559                   else
2560                     {
2561                        if (!is_above_show_pending)
2562                          is_vis_on_skip = EINA_TRUE;
2563                        ELOGF("POL_VIS", "CLIENT VIS ON-SKIP. argb:%d, opaque:%2d, frame_v:%d, ignore_geometry:%d, cdata:%p, geo(%d,%d,%dx%d), asp:%d, er:%d, le:%d", ec, ec->argb, ec->visibility.opaque, ec_frame_visible, ec->visibility.ignore_geometry, cdata, x, y, w, h, is_above_show_pending, effect_running, is_launching_effect);
2564                     }
2565                }
2566
2567              /* subtract window region from canvas region */
2568              if (canvas_vis && !skip_by_pending_show && !is_vis_on_skip)
2569                {
2570                   /* check alpha window is opaque or not. */
2571                   if ((ec->visibility.opaque > 0) && (ec->argb))
2572                     ec_opaque = EINA_TRUE;
2573
2574                   /* if e_client is not alpha or opaque then delete intersect rect */
2575                   if (((!ec->argb) || (ec_opaque)) &&
2576                       (!ec->floating))
2577                     {
2578                        EINA_RECTANGLE_SET(&r,
2579                                           x,
2580                                           y,
2581                                           w,
2582                                           h);
2583                        eina_tiler_rect_del(t, &r);
2584
2585                        if (eina_tiler_empty(t))
2586                          canvas_vis = EINA_FALSE;
2587                     }
2588                }
2589           }
2590         else
2591           {
2592              /* It prevents unwanted iconification of the top visible window
2593               * while showing an window with rotation mode.
2594               * However, with rotation mode, iconification is done if client
2595               * is iconified by itself.
2596               */
2597              if ((!skip_by_pending_show) ||
2598                  (ec->visibility.force_obscured) ||
2599                  (ec->bg_state) ||
2600                  (iconified_by_client))
2601                {
2602                   /* obscured case */
2603                   if (e_client_visibility_get(ec) != E_VISIBILITY_FULLY_OBSCURED)
2604                     {
2605                        /* previous state is unobscured: -1 or 0 */
2606                        e_client_visibility_set(ec, E_VISIBILITY_FULLY_OBSCURED);
2607                        ec->visibility.changed = 1;
2608                        ELOGF("POL_VIS", "CLIENT VIS OFF. argb:%d, opaque:%2d, frame_v:%d, canvas_v:%d, calc_r:%d(%d), ignore_geometry:%d, show_p:%d, geo(%d,%d,%dx%d)",
2609                              ec, ec->argb, ec->visibility.opaque,
2610                              ec_frame_visible, canvas_vis, calc_region, calc_skip_type, ec->visibility.ignore_geometry, skip_by_pending_show, x, y, w, h);
2611                     }
2612                }
2613           }
2614
2615         if (!is_vis_on_skip &&
2616             (!skip_rot_pending_show || ec->visibility.changed))
2617           changed_list = eina_list_append(changed_list, ec);
2618
2619         if (skip_rot_pending_show)
2620           {
2621              if (ec->e.state.rot.pending_show && !ec->argb)
2622                is_above_show_pending = EINA_TRUE;
2623              ELOGF("POL_VIS", "Rotation pending show. srps:%d, rps:%d, argb:%d, asp:%d", ec, skip_rot_pending_show, ec->e.state.rot.pending_show, ec->argb, is_above_show_pending);
2624           }
2625      }
2626
2627    if (changed_list)
2628      {
2629         touched_ec = e_comp_wl->ptr.ec ? e_comp_wl->ptr.ec : e_comp_wl->touch.faked_ec;
2630         EINA_LIST_FOREACH(changed_list, l, ec)
2631           {
2632              e_client_visibility_change_notify(ec);
2633
2634              if (ec == touched_ec)
2635                touched_win_changed = EINA_TRUE;
2636
2637              if (e_client_visibility_get(ec) == E_VISIBILITY_UNOBSCURED)
2638                {
2639                   if (e_comp_wl->touch.pressed && !touched_win_changed && !e_policy_client_is_keyboard_sub(ec))
2640                     {
2641                        if (e_client_visibility_touched_check(ec))
2642                          {
2643                             touched_win_changed = EINA_TRUE;
2644                             e_comp_wl_touch_cancel();
2645                          }
2646                     }
2647                }
2648
2649              ec->visibility.changed = 0;
2650              e_visibility_changed = EINA_TRUE;
2651           }
2652
2653         changed_list = eina_list_free(changed_list);
2654      }
2655    eina_tiler_free(t);
2656
2657    // FIXME: need to notify a hook call for zone, not for client
2658    e_client_visibility_end_notify();
2659
2660    TRACE_DS_END();
2661
2662    return e_visibility_changed;
2663 }
2664
2665 E_API E_Desk *
2666 e_zone_desk_find_by_ec(E_Zone *zone, E_Client *ec)
2667 {
2668    int i, n;
2669
2670    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL);
2671    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
2672
2673    n = zone->desk_y_count * zone->desk_x_count;
2674    for (i = 0; i < n; i++)
2675      {
2676         if (e_desk_has_ec(zone->desks[i], ec))
2677           return zone->desks[i];
2678
2679      }
2680
2681    return NULL;
2682 }
2683
2684 EINTERN void
2685 e_zone_focus_clear(E_Zone *zone)
2686 {
2687    EINA_SAFETY_ON_NULL_RETURN(zone);
2688
2689    wl_signal_emit_mutable(&PRI(zone)->events.focus_clear, NULL);
2690 }
2691
2692 EINTERN void
2693 e_zone_focus_reset(E_Zone *zone)
2694 {
2695    EINA_SAFETY_ON_NULL_RETURN(zone);
2696
2697    wl_signal_emit_mutable(&PRI(zone)->events.focus_reset, NULL);
2698 }
2699
2700 EINTERN void
2701 e_zone_client_add_listener_add(E_Zone *zone, struct wl_listener *listener)
2702 {
2703    API_ENTRY;
2704    wl_signal_add(&priv->events.client_add, listener);
2705 }
2706
2707 EINTERN void
2708 e_zone_client_remove_listener_add(E_Zone *zone, struct wl_listener *listener)
2709 {
2710    API_ENTRY;
2711    wl_signal_add(&priv->events.client_remove, listener);
2712 }
2713
2714 EINTERN void
2715 e_zone_display_state_change_listener_add(E_Zone *zone, struct wl_listener *listener)
2716 {
2717    API_ENTRY;
2718    wl_signal_add(&priv->events.display_state_change, listener);
2719 }
2720
2721 EINTERN void
2722 e_zone_focus_clear_listener_add(E_Zone *zone, struct wl_listener *listener)
2723 {
2724    API_ENTRY;
2725    wl_signal_add(&priv->events.focus_clear, listener);
2726 }
2727
2728 EINTERN void
2729 e_zone_focus_reset_listener_add(E_Zone *zone, struct wl_listener *listener)
2730 {
2731    API_ENTRY;
2732    wl_signal_add(&priv->events.focus_reset, listener);
2733 }