Change Flora License Version
[platform/core/uifw/e17.git] / src / bin / e_zone.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * This file is a modified version of BSD licensed file and
5  * licensed under the Flora License, Version 1.1 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://floralicense.org/license/
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an AS IS BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * Please, see the COPYING file for the original copyright owner and
18  * license.
19  */
20 #include "e.h"
21
22 /* E_Zone is a child object of E_Container. There is one zone per screen
23  * in a xinerama setup. Each zone has one or more desktops.
24  */
25
26 static void _e_zone_free(E_Zone *zone);
27 static void _e_zone_cb_bg_mouse_down(void        *data,
28                                      Evas        *evas,
29                                      Evas_Object *obj,
30                                      void        *event_info);
31 static void _e_zone_cb_bg_mouse_up(void        *data,
32                                    Evas        *evas,
33                                    Evas_Object *obj,
34                                    void        *event_info);
35 static void      _e_zone_event_zone_desk_count_set_free(void *data,
36                                                         void *ev);
37 static Eina_Bool _e_zone_cb_mouse_in(void *data,
38                                      int   type,
39                                      void *event);
40 static Eina_Bool _e_zone_cb_mouse_out(void *data,
41                                       int   type,
42                                       void *event);
43 static Eina_Bool _e_zone_cb_mouse_down(void *data,
44                                        int   type,
45                                        void *event);
46 static Eina_Bool _e_zone_cb_mouse_up(void *data,
47                                      int   type,
48                                      void *event);
49 static Eina_Bool _e_zone_cb_mouse_move(void *data,
50                                        int   type,
51                                        void *event);
52 static Eina_Bool _e_zone_cb_desk_after_show(void *data,
53                                             int   type,
54                                             void *event);
55 static Eina_Bool   _e_zone_cb_edge_timer(void *data);
56 static void        _e_zone_event_move_resize_free(void *data,
57                                                   void *ev);
58 static void        _e_zone_event_add_free(void *data,
59                                           void *ev);
60 static void        _e_zone_event_del_free(void *data,
61                                           void *ev);
62 static void        _e_zone_object_del_attach(void *o);
63 static E_Zone_Edge _e_zone_detect_edge(E_Zone        *zone,
64                                        Ecore_X_Window win);
65 static void        _e_zone_edge_move_resize(E_Zone *zone);
66 static void        _e_zone_border_geometry_update(E_Zone *zone);
67 #ifdef _F_ZONE_WINDOW_ROTATION_
68 static void        _e_zone_event_rotation_change_free(void *data,
69                                                       void *ev);
70 #endif
71
72 EAPI int E_EVENT_ZONE_DESK_COUNT_SET = 0;
73 EAPI int E_EVENT_POINTER_WARP = 0;
74 EAPI int E_EVENT_ZONE_MOVE_RESIZE = 0;
75 EAPI int E_EVENT_ZONE_ADD = 0;
76 EAPI int E_EVENT_ZONE_DEL = 0;
77 EAPI int E_EVENT_ZONE_EDGE_IN = 0;
78 EAPI int E_EVENT_ZONE_EDGE_OUT = 0;
79 EAPI int E_EVENT_ZONE_EDGE_MOVE = 0;
80 #ifdef _F_ZONE_WINDOW_ROTATION_
81 EAPI int E_EVENT_ZONE_ROTATION_CHANGE = 0;
82 #endif
83
84 #define E_ZONE_FLIP_LEFT(zone)  (((e_config->desk_flip_wrap && ((zone)->desk_x_count > 1)) || ((zone)->desk_x_current > 0)) && (zone)->edge.left)
85 #define E_ZONE_FLIP_RIGHT(zone) (((e_config->desk_flip_wrap && ((zone)->desk_x_count > 1)) || (((zone)->desk_x_current + 1) < (zone)->desk_x_count)) && (zone)->edge.right)
86 #define E_ZONE_FLIP_UP(zone)    (((e_config->desk_flip_wrap && ((zone)->desk_y_count > 1)) || ((zone)->desk_y_current > 0)) && (zone)->edge.top)
87 #define E_ZONE_FLIP_DOWN(zone)  (((e_config->desk_flip_wrap && ((zone)->desk_y_count > 1)) || (((zone)->desk_y_current + 1) < (zone)->desk_y_count)) && (zone)->edge.bottom)
88
89 #define E_ZONE_CORNER_RATIO 0.025;
90
91 EINTERN int
92 e_zone_init(void)
93 {
94    E_EVENT_ZONE_DESK_COUNT_SET = ecore_event_type_new();
95    E_EVENT_POINTER_WARP = ecore_event_type_new();
96    E_EVENT_ZONE_MOVE_RESIZE = ecore_event_type_new();
97    E_EVENT_ZONE_ADD = ecore_event_type_new();
98    E_EVENT_ZONE_DEL = ecore_event_type_new();
99    E_EVENT_ZONE_EDGE_IN = ecore_event_type_new();
100    E_EVENT_ZONE_EDGE_OUT = ecore_event_type_new();
101    E_EVENT_ZONE_EDGE_MOVE = ecore_event_type_new();
102 #ifdef _F_ZONE_WINDOW_ROTATION_
103    E_EVENT_ZONE_ROTATION_CHANGE = ecore_event_type_new();
104 #endif
105    return 1;
106 }
107
108 EINTERN int
109 e_zone_shutdown(void)
110 {
111    return 1;
112 }
113
114 EAPI void
115 e_zone_all_edge_flip_eval(void)
116 {
117    Eina_List *l, *ll, *lll;
118    E_Manager *man;
119    E_Container *con;
120    E_Zone *zone;
121
122    EINA_LIST_FOREACH(e_manager_list(), l, man)
123      {
124         EINA_LIST_FOREACH(man->containers, ll, con)
125           {
126              EINA_LIST_FOREACH(con->zones, lll, zone)
127                {
128                   e_zone_edge_flip_eval(zone);
129                }
130           }
131      }
132 }
133
134 static void
135 _e_zone_black_new(E_Zone *zone)
136 {
137    Evas_Object *o;
138    char name[256];
139
140    if (zone->black_ecore_evas) return;
141    zone->black_ecore_evas = e_canvas_new(zone->container->win,
142                                          zone->x, zone->y, 1, 1, 1, 1,
143                                          &(zone->black_win));
144    e_canvas_add(zone->black_ecore_evas);
145    ecore_evas_layer_set(zone->black_ecore_evas, 6);
146    zone->black_evas = ecore_evas_get(zone->black_ecore_evas);
147
148    o = evas_object_rectangle_add(zone->black_evas);
149    evas_object_move(o, 0, 0);
150    evas_object_resize(o, zone->w, zone->h);
151    evas_object_color_set(o, 0, 0, 0, 255);
152    evas_object_show(o);
153
154    ecore_evas_name_class_set(zone->black_ecore_evas, "E", "Black_Window");
155    snprintf(name, sizeof(name), "Enlightenment Black Zone (%d)", zone->num);
156    ecore_evas_title_set(zone->black_ecore_evas, name);
157 }
158
159 static void
160 _e_zone_black_free(E_Zone *zone)
161 {
162    if (!zone->black_ecore_evas) return;
163    e_canvas_del(zone->black_ecore_evas);
164    ecore_evas_free(zone->black_ecore_evas);
165    zone->black_ecore_evas = NULL;
166    zone->black_win = 0;
167 }
168
169 static void
170 _e_zone_black_get(E_Zone *zone)
171 {
172    zone->black_need++;
173    if (!zone->black_ecore_evas) return;
174    if (zone->black_need == 1)
175      {
176         ecore_evas_move(zone->black_ecore_evas, zone->x, zone->y);
177         ecore_evas_resize(zone->black_ecore_evas, zone->w, zone->h);
178      }
179 }
180
181 static void
182 _e_zone_black_unget(E_Zone *zone)
183 {
184    zone->black_need--;
185    if (!zone->black_ecore_evas) return;
186    if (zone->black_need == 0)
187      {
188         ecore_evas_move(zone->black_ecore_evas, zone->x, zone->y);
189         ecore_evas_resize(zone->black_ecore_evas, 1, 1);
190      }
191 }
192
193 EAPI E_Zone *
194 e_zone_new(E_Container *con,
195            int          num,
196            int          id,
197            int          x,
198            int          y,
199            int          w,
200            int          h)
201 {
202    E_Zone *zone;
203    Evas_Object *o;
204    E_Event_Zone_Add *ev;
205    char name[40];
206
207    zone = E_OBJECT_ALLOC(E_Zone, E_ZONE_TYPE, _e_zone_free);
208    if (!zone) return NULL;
209
210    zone->container = con;
211
212    zone->x = x;
213    zone->y = y;
214    zone->w = w;
215    zone->h = h;
216    zone->num = num;
217    zone->id = id;
218    e_zone_useful_geometry_dirty(zone);
219
220    //printf("@@@@@@@@@@ e_zone_new: %i %i | %i %i %ix%i = %p\n", num, id, x, y, w, h, zone);
221
222    zone->handlers =
223      eina_list_append(zone->handlers,
224                       ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN,
225                                               _e_zone_cb_mouse_in, zone));
226    zone->handlers =
227      eina_list_append(zone->handlers,
228                       ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT,
229                                               _e_zone_cb_mouse_out, zone));
230    zone->handlers =
231      eina_list_append(zone->handlers,
232                       ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
233                                               _e_zone_cb_mouse_down, zone));
234    zone->handlers =
235      eina_list_append(zone->handlers,
236                       ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
237                                               _e_zone_cb_mouse_up, zone));
238    zone->handlers =
239      eina_list_append(zone->handlers,
240                       ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
241                                               _e_zone_cb_mouse_move, zone));
242    zone->handlers =
243      eina_list_append(zone->handlers,
244                       ecore_event_handler_add(E_EVENT_DESK_AFTER_SHOW,
245                                               _e_zone_cb_desk_after_show, zone));
246
247    snprintf(name, sizeof(name), "Zone %d", zone->num);
248    zone->name = eina_stringshare_add(name);
249
250    con->zones = eina_list_append(con->zones, zone);
251
252    o = evas_object_rectangle_add(con->bg_evas);
253    zone->bg_clip_object = o;
254    evas_object_move(o, x, y);
255    evas_object_resize(o, w, h);
256    evas_object_color_set(o, 255, 255, 255, 255);
257    evas_object_show(o);
258
259    o = evas_object_rectangle_add(con->bg_evas);
260    zone->bg_event_object = o;
261    evas_object_clip_set(o, zone->bg_clip_object);
262    evas_object_move(o, x, y);
263    evas_object_resize(o, w, h);
264    evas_object_color_set(o, 0, 0, 0, 0);
265    evas_object_repeat_events_set(o, 1);
266    evas_object_show(o);
267    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _e_zone_cb_bg_mouse_down, zone);
268    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _e_zone_cb_bg_mouse_up, zone);
269
270    /* TODO: config the ecore_evas type. */
271
272    zone->desk_x_count = 0;
273    zone->desk_y_count = 0;
274    zone->desk_x_current = 0;
275    zone->desk_y_current = 0;
276    e_zone_desk_count_set(zone, e_config->zone_desks_x_count,
277                          e_config->zone_desks_y_count);
278
279    e_object_del_attach_func_set(E_OBJECT(zone), _e_zone_object_del_attach);
280
281    _e_zone_black_new(zone);
282
283    ev = E_NEW(E_Event_Zone_Add, 1);
284    ev->zone = zone;
285    e_object_ref(E_OBJECT(ev->zone));
286    ecore_event_add(E_EVENT_ZONE_ADD, ev, _e_zone_event_add_free, NULL);
287
288    e_zone_all_edge_flip_eval();
289    return zone;
290 }
291
292 EAPI void
293 e_zone_name_set(E_Zone     *zone,
294                 const char *name)
295 {
296    E_OBJECT_CHECK(zone);
297    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
298
299    if (zone->name) eina_stringshare_del(zone->name);
300    zone->name = eina_stringshare_add(name);
301 }
302
303 EAPI void
304 e_zone_move(E_Zone *zone,
305             int     x,
306             int     y)
307 {
308    E_Event_Zone_Move_Resize *ev;
309
310    E_OBJECT_CHECK(zone);
311    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
312
313    if ((x == zone->x) && (y == zone->y)) return;
314    zone->x = x;
315    zone->y = y;
316    evas_object_move(zone->bg_object, x, y);
317    evas_object_move(zone->bg_event_object, x, y);
318    evas_object_move(zone->bg_clip_object, x, y);
319
320    ev = E_NEW(E_Event_Zone_Move_Resize, 1);
321    ev->zone = zone;
322    e_object_ref(E_OBJECT(ev->zone));
323    ecore_event_add(E_EVENT_ZONE_MOVE_RESIZE, ev, _e_zone_event_move_resize_free, NULL);
324
325    _e_zone_edge_move_resize(zone);
326    e_zone_bg_reconfigure(zone);
327    if (zone->black_need > 0)
328      {
329         ecore_evas_move(zone->black_ecore_evas, zone->x, zone->y);
330         ecore_evas_resize(zone->black_ecore_evas, zone->w, zone->h);
331      }
332    _e_zone_border_geometry_update(zone);
333 }
334
335 EAPI void
336 e_zone_resize(E_Zone *zone,
337               int     w,
338               int     h)
339 {
340    E_Event_Zone_Move_Resize *ev;
341
342    E_OBJECT_CHECK(zone);
343    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
344
345    if ((w == zone->w) && (h == zone->h)) return;
346    zone->w = w;
347    zone->h = h;
348    evas_object_resize(zone->bg_object, w, h);
349    evas_object_resize(zone->bg_event_object, w, h);
350    evas_object_resize(zone->bg_clip_object, w, h);
351
352    ev = E_NEW(E_Event_Zone_Move_Resize, 1);
353    ev->zone = zone;
354    e_object_ref(E_OBJECT(ev->zone));
355    ecore_event_add(E_EVENT_ZONE_MOVE_RESIZE, ev,
356                    _e_zone_event_move_resize_free, NULL);
357
358    _e_zone_edge_move_resize(zone);
359    e_zone_bg_reconfigure(zone);
360    if (zone->black_need > 0)
361      {
362         ecore_evas_move(zone->black_ecore_evas, zone->x, zone->y);
363         ecore_evas_resize(zone->black_ecore_evas, zone->w, zone->h);
364      }
365    _e_zone_border_geometry_update(zone);
366 }
367
368 EAPI void
369 e_zone_move_resize(E_Zone *zone,
370                    int     x,
371                    int     y,
372                    int     w,
373                    int     h)
374 {
375    E_Event_Zone_Move_Resize *ev;
376
377    E_OBJECT_CHECK(zone);
378    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
379
380    if ((x == zone->x) && (y == zone->y) && (w == zone->w) && (h == zone->h))
381      return;
382
383    zone->x = x;
384    zone->y = y;
385    zone->w = w;
386    zone->h = h;
387
388    evas_object_move(zone->bg_object, x, y);
389    evas_object_move(zone->bg_event_object, x, y);
390    evas_object_move(zone->bg_clip_object, x, y);
391    evas_object_resize(zone->bg_object, w, h);
392    evas_object_resize(zone->bg_event_object, w, h);
393    evas_object_resize(zone->bg_clip_object, w, h);
394
395    ev = E_NEW(E_Event_Zone_Move_Resize, 1);
396    ev->zone = zone;
397    e_object_ref(E_OBJECT(ev->zone));
398    ecore_event_add(E_EVENT_ZONE_MOVE_RESIZE, ev,
399                    _e_zone_event_move_resize_free, NULL);
400
401    _e_zone_edge_move_resize(zone);
402
403    e_zone_bg_reconfigure(zone);
404    if (zone->black_need > 0)
405      {
406         ecore_evas_move(zone->black_ecore_evas, zone->x, zone->y);
407         ecore_evas_resize(zone->black_ecore_evas, zone->w, zone->h);
408      }
409    _e_zone_border_geometry_update(zone);
410 }
411
412 EAPI void
413 e_zone_fullscreen_set(E_Zone *zone,
414                       int     on)
415 {
416    E_OBJECT_CHECK(zone);
417    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
418
419    if ((!zone->fullscreen) && (on))
420      {
421         _e_zone_black_get(zone);
422         ecore_evas_show(zone->black_ecore_evas);
423         e_container_window_raise(zone->container, zone->black_win, 150);
424         zone->fullscreen = 1;
425      }
426    else if ((zone->fullscreen) && (!on))
427      {
428         ecore_evas_hide(zone->black_ecore_evas);
429         zone->fullscreen = 0;
430         _e_zone_black_unget(zone);
431      }
432 }
433
434 EAPI E_Zone *
435 e_zone_current_get(E_Container *con)
436 {
437    Eina_List *l = NULL;
438    E_Zone *zone;
439
440    E_OBJECT_CHECK_RETURN(con, NULL);
441    E_OBJECT_TYPE_CHECK_RETURN(con, E_CONTAINER_TYPE, NULL);
442    if (!starting)
443      {
444         int x, y;
445
446         ecore_x_pointer_xy_get(con->win, &x, &y);
447         EINA_LIST_FOREACH(con->zones, l, zone)
448           {
449              if (E_INSIDE(x, y, zone->x, zone->y, zone->w, zone->h))
450                return zone;
451           }
452      }
453    if (!con->zones) return NULL;
454    return (E_Zone *)eina_list_data_get(con->zones);
455 }
456
457 EAPI void
458 e_zone_bg_reconfigure(E_Zone *zone)
459 {
460    E_OBJECT_CHECK(zone);
461    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
462
463    e_bg_zone_update(zone, E_BG_TRANSITION_CHANGE);
464 }
465
466 EAPI void
467 e_zone_flip_coords_handle(E_Zone *zone,
468                           int     x,
469                           int     y)
470 {
471    E_Event_Zone_Edge *zev;
472    E_Binding_Edge *binding;
473    E_Zone_Edge edge;
474    Eina_List *l;
475    E_Shelf *es;
476    int ok = 0;
477    int one_row = 1;
478    int one_col = 1;
479
480    E_OBJECT_CHECK(zone);
481    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
482
483    if (!e_config->edge_flip_dragging || zone->flip.switching) return;
484    /* if we have only 1 row we can flip up/down even if we have xinerama */
485    if (eina_list_count(zone->container->zones) > 1)
486      {
487         Eina_List *zones;
488         E_Zone *next_zone;
489         int cx, cy;
490
491         zones = zone->container->zones;
492         next_zone = (E_Zone *)eina_list_data_get(zones);
493         cx = next_zone->x;
494         cy = next_zone->y;
495         zones = eina_list_next(zones);
496         EINA_LIST_FOREACH(eina_list_next(zones), zones, next_zone)
497           {
498              if (next_zone->x != cx) one_col = 0;
499              if (next_zone->y != cy) one_row = 0;
500           }
501      }
502    if (eina_list_count(zone->container->manager->containers) > 1)
503      goto noflip;
504    if (!E_INSIDE(x, y, zone->x, zone->y, zone->w, zone->h))
505      goto noflip;
506    if ((one_row) && (y == 0))
507      edge = E_ZONE_EDGE_TOP;
508    else if ((one_col) && (x == (zone->w - 1)))
509      edge = E_ZONE_EDGE_RIGHT;
510    else if ((one_row) && (y == (zone->h - 1)))
511      edge = E_ZONE_EDGE_BOTTOM;
512    else if ((one_col) && (x == 0))
513      edge = E_ZONE_EDGE_LEFT;
514    else
515      {
516 noflip:
517         if (zone->flip.es)
518           e_shelf_toggle(zone->flip.es, 0);
519         zone->flip.es = NULL;
520         return;
521      }
522    EINA_LIST_FOREACH(e_shelf_list(), l, es)
523      {
524         if (es->zone != zone) continue;
525         switch (es->gadcon->orient)
526           {
527            case E_GADCON_ORIENT_TOP:
528            case E_GADCON_ORIENT_CORNER_TL:
529            case E_GADCON_ORIENT_CORNER_TR:
530              if (edge == E_ZONE_EDGE_TOP) ok = 1;
531              break;
532
533            case E_GADCON_ORIENT_BOTTOM:
534            case E_GADCON_ORIENT_CORNER_BL:
535            case E_GADCON_ORIENT_CORNER_BR:
536              if (edge == E_ZONE_EDGE_BOTTOM) ok = 1;
537              break;
538
539            case E_GADCON_ORIENT_LEFT:
540            case E_GADCON_ORIENT_CORNER_LT:
541            case E_GADCON_ORIENT_CORNER_LB:
542              if (edge == E_ZONE_EDGE_LEFT) ok = 1;
543              break;
544
545            case E_GADCON_ORIENT_RIGHT:
546            case E_GADCON_ORIENT_CORNER_RT:
547            case E_GADCON_ORIENT_CORNER_RB:
548              if (edge == E_ZONE_EDGE_RIGHT) ok = 1;
549              break;
550
551            default:
552              ok = 0;
553              break;
554           }
555
556         if (!ok) continue;
557         if (!E_INSIDE(x, y, es->x, es->y, es->w, es->h))
558           continue;
559
560         if (zone->flip.es)
561           e_shelf_toggle(zone->flip.es, 0);
562
563         zone->flip.es = es;
564         e_shelf_toggle(es, 1);
565      }
566    switch (edge)
567      {
568       case E_ZONE_EDGE_LEFT:
569         if (E_ZONE_FLIP_LEFT(zone)) ok = 1;
570         break;
571
572       case E_ZONE_EDGE_TOP:
573         if (E_ZONE_FLIP_UP(zone)) ok = 1;
574         break;
575
576       case E_ZONE_EDGE_RIGHT:
577         if (E_ZONE_FLIP_RIGHT(zone)) ok = 1;
578         break;
579
580       case E_ZONE_EDGE_BOTTOM:
581         if (E_ZONE_FLIP_DOWN(zone)) ok = 1;
582         break;
583
584       default:
585         ok = 0;
586         break;
587      }
588    if (!ok) return;
589    binding = e_bindings_edge_get("desk_flip_in_direction", edge, 0);
590    if (!binding) binding = e_bindings_edge_get("desk_flip_by", edge, 0);
591    if (binding && (!binding->timer))
592      {
593         zev = E_NEW(E_Event_Zone_Edge, 1);
594         zev->zone = zone;
595         zev->x = x;
596         zev->y = y;
597         zev->edge = edge;
598         zone->flip.ev = zev;
599         zone->flip.bind = binding;
600         zone->flip.switching = 1;
601         binding->timer = ecore_timer_add(((double)binding->delay), _e_zone_cb_edge_timer, zone);
602      }
603 }
604
605 EAPI void
606 e_zone_desk_count_set(E_Zone *zone,
607                       int     x_count,
608                       int     y_count)
609 {
610    E_Desk **new_desks;
611    E_Desk *desk, *new_desk;
612    E_Border *bd;
613    E_Event_Zone_Desk_Count_Set *ev;
614    E_Border_List *bl;
615    int x, y, xx, yy, moved, nx, ny;
616
617    E_OBJECT_CHECK(zone);
618    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
619
620    xx = x_count;
621    if (xx < 1) xx = 1;
622    yy = y_count;
623    if (yy < 1) yy = 1;
624
625    /* Orphaned window catcher; in case desk count gets reset */
626    moved = 0;
627    if (zone->desk_x_current >= xx) moved = 1;
628    if (zone->desk_y_current >= yy) moved = 1;
629    if (moved)
630      {
631         nx = zone->desk_x_current;
632         ny = zone->desk_y_current;
633         if (zone->desk_x_current >= xx) nx = xx - 1;
634         if (zone->desk_y_current >= yy) ny = yy - 1;
635         e_desk_show(e_desk_at_xy_get(zone, nx, ny));
636      }
637
638    new_desks = malloc(xx * yy * sizeof(E_Desk *));
639    for (x = 0; x < xx; x++)
640      {
641         for (y = 0; y < yy; y++)
642           {
643              if ((x < zone->desk_x_count) && (y < zone->desk_y_count))
644                desk = zone->desks[x + (y * zone->desk_x_count)];
645              else
646                desk = e_desk_new(zone, x, y);
647              new_desks[x + (y * xx)] = desk;
648           }
649      }
650
651    /* catch windoes that have fallen off the end if we got smaller */
652    if (xx < zone->desk_x_count)
653      {
654         for (y = 0; y < zone->desk_y_count; y++)
655           {
656              new_desk = zone->desks[xx - 1 + (y * zone->desk_x_count)];
657              for (x = xx; x < zone->desk_x_count; x++)
658                {
659                   desk = zone->desks[x + (y * zone->desk_x_count)];
660
661                   bl = e_container_border_list_first(zone->container);
662                   while ((bd = e_container_border_list_next(bl)))
663                     {
664                        if (bd->desk == desk)
665                          e_border_desk_set(bd, new_desk);
666                     }
667                   e_container_border_list_free(bl);
668                   e_object_del(E_OBJECT(desk));
669                }
670           }
671      }
672    if (yy < zone->desk_y_count)
673      {
674         for (x = 0; x < zone->desk_x_count; x++)
675           {
676              new_desk = zone->desks[x + ((yy - 1) * zone->desk_x_count)];
677              for (y = yy; y < zone->desk_y_count; y++)
678                {
679                   desk = zone->desks[x + (y * zone->desk_x_count)];
680
681                   bl = e_container_border_list_first(zone->container);
682                   while ((bd = e_container_border_list_next(bl)))
683                     {
684                        if (bd->desk == desk)
685                          e_border_desk_set(bd, new_desk);
686                     }
687                   e_container_border_list_free(bl);
688                   e_object_del(E_OBJECT(desk));
689                }
690           }
691      }
692    if (zone->desks) free(zone->desks);
693    zone->desks = new_desks;
694
695    zone->desk_x_count = xx;
696    zone->desk_y_count = yy;
697    e_config->zone_desks_x_count = xx;
698    e_config->zone_desks_y_count = yy;
699    e_config_save_queue();
700
701    /* Cannot call desk_current_get until the zone desk counts have been set
702     * or else we end up with a "white background" because desk_current_get will
703     * return NULL.
704     */
705    desk = e_desk_current_get(zone);
706    if (desk)
707      {
708         desk->visible = 0;
709         e_desk_show(desk);
710      }
711
712    e_zone_edge_flip_eval(zone);
713
714    ev = E_NEW(E_Event_Zone_Desk_Count_Set, 1);
715    if (!ev) return;
716    ev->zone = zone;
717    e_object_ref(E_OBJECT(ev->zone));
718    ecore_event_add(E_EVENT_ZONE_DESK_COUNT_SET, ev,
719                    _e_zone_event_zone_desk_count_set_free, NULL);
720 }
721
722 EAPI void
723 e_zone_desk_count_get(E_Zone *zone,
724                       int    *x_count,
725                       int    *y_count)
726 {
727    E_OBJECT_CHECK(zone);
728    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
729
730    if (x_count) *x_count = zone->desk_x_count;
731    if (y_count) *y_count = zone->desk_y_count;
732 }
733
734 EAPI void
735 e_zone_desk_flip_by(E_Zone *zone,
736                     int     dx,
737                     int     dy)
738 {
739    E_OBJECT_CHECK(zone);
740    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
741
742    dx = zone->desk_x_current + dx;
743    dy = zone->desk_y_current + dy;
744    e_zone_desk_flip_to(zone, dx, dy);
745    e_zone_edge_flip_eval(zone);
746 }
747
748 EAPI void
749 e_zone_desk_flip_to(E_Zone *zone,
750                     int     x,
751                     int     y)
752 {
753    E_Desk *desk;
754
755    E_OBJECT_CHECK(zone);
756    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
757
758    if (e_config->desk_flip_wrap)
759      {
760         x = x % zone->desk_x_count;
761         y = y % zone->desk_y_count;
762         if (x < 0) x += zone->desk_x_count;
763         if (y < 0) y += zone->desk_y_count;
764      }
765    else
766      {
767         if (x < 0) x = 0;
768         else if (x >= zone->desk_x_count)
769           x = zone->desk_x_count - 1;
770         if (y < 0) y = 0;
771         else if (y >= zone->desk_y_count)
772           y = zone->desk_y_count - 1;
773      }
774    desk = e_desk_at_xy_get(zone, x, y);
775    if (desk) e_desk_show(desk);
776    e_zone_edge_flip_eval(zone);
777 }
778
779 EAPI void
780 e_zone_desk_linear_flip_by(E_Zone *zone,
781                            int     dx)
782 {
783    E_OBJECT_CHECK(zone);
784    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
785
786    dx = zone->desk_x_current +
787      (zone->desk_y_current * zone->desk_x_count) + dx;
788    dx = dx % (zone->desk_x_count * zone->desk_y_count);
789    while (dx < 0)
790      dx += (zone->desk_x_count * zone->desk_y_count);
791    e_zone_desk_linear_flip_to(zone, dx);
792    e_zone_edge_flip_eval(zone);
793 }
794
795 EAPI void
796 e_zone_desk_linear_flip_to(E_Zone *zone,
797                            int     x)
798 {
799    int y;
800
801    E_OBJECT_CHECK(zone);
802    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
803
804    y = x / zone->desk_x_count;
805    x = x - (y * zone->desk_x_count);
806    e_zone_desk_flip_to(zone, x, y);
807    e_zone_edge_flip_eval(zone);
808 }
809
810 EAPI void
811 e_zone_edge_enable(void)
812 {
813    Eina_List *l, *ll, *lll;
814    E_Manager *man;
815    E_Container *con;
816    E_Zone *zone;
817
818    EINA_LIST_FOREACH(e_manager_list(), l, man)
819      {
820         EINA_LIST_FOREACH(man->containers, ll, con)
821           {
822              EINA_LIST_FOREACH(con->zones, lll, zone)
823                {
824                   if (zone->edge.left) ecore_x_window_show(zone->edge.left);
825                   if (zone->edge.right) ecore_x_window_show(zone->edge.right);
826                   if (zone->edge.top) ecore_x_window_show(zone->edge.top);
827                   if (zone->edge.bottom) ecore_x_window_show(zone->edge.bottom);
828                   if (zone->corner.left_top) ecore_x_window_show(zone->corner.left_top);
829                   if (zone->corner.top_left) ecore_x_window_show(zone->corner.top_left);
830                   if (zone->corner.top_right) ecore_x_window_show(zone->corner.top_right);
831                   if (zone->corner.right_top) ecore_x_window_show(zone->corner.right_top);
832                   if (zone->corner.right_bottom) ecore_x_window_show(zone->corner.right_bottom);
833                   if (zone->corner.bottom_right) ecore_x_window_show(zone->corner.bottom_right);
834                   if (zone->corner.bottom_left) ecore_x_window_show(zone->corner.bottom_left);
835                   if (zone->corner.left_bottom) ecore_x_window_show(zone->corner.left_bottom);
836                   e_zone_edge_flip_eval(zone);
837                }
838           }
839      }
840 }
841
842 EAPI void
843 e_zone_edge_disable(void)
844 {
845    Eina_List *l, *ll, *lll;
846    E_Manager *man;
847    E_Container *con;
848    E_Zone *zone;
849
850    EINA_LIST_FOREACH(e_manager_list(), l, man)
851      {
852         EINA_LIST_FOREACH(man->containers, ll, con)
853           {
854              EINA_LIST_FOREACH(con->zones, lll, zone)
855                {
856                   if (zone->edge.left) ecore_x_window_hide(zone->edge.left);
857                   if (zone->edge.right) ecore_x_window_hide(zone->edge.right);
858                   if (zone->edge.top) ecore_x_window_hide(zone->edge.top);
859                   if (zone->edge.bottom) ecore_x_window_hide(zone->edge.bottom);
860                   if (zone->corner.left_top) ecore_x_window_hide(zone->corner.left_top);
861                   if (zone->corner.top_left) ecore_x_window_hide(zone->corner.top_left);
862                   if (zone->corner.top_right) ecore_x_window_hide(zone->corner.top_right);
863                   if (zone->corner.right_top) ecore_x_window_hide(zone->corner.right_top);
864                   if (zone->corner.right_bottom) ecore_x_window_hide(zone->corner.right_bottom);
865                   if (zone->corner.bottom_right) ecore_x_window_hide(zone->corner.bottom_right);
866                   if (zone->corner.bottom_left) ecore_x_window_hide(zone->corner.bottom_left);
867                   if (zone->corner.left_bottom) ecore_x_window_hide(zone->corner.left_bottom);
868                }
869           }
870      }
871 }
872
873 EAPI void
874 e_zone_edges_desk_flip_capable(E_Zone *zone, Eina_Bool l, Eina_Bool r, Eina_Bool t, Eina_Bool b)
875 {
876 #define NEED_FLIP_EDGE(x) \
877    (e_bindings_edge_flippable_get(x) || e_bindings_edge_non_flippable_get(x))
878 #define NEED_EDGE(x) \
879    (e_bindings_edge_non_flippable_get(x))
880 #define CHECK_EDGE(v, ed, win) \
881    do { \
882       if (v) { \
883          if (NEED_FLIP_EDGE(ed)) { if (zone->edge.win) ecore_x_window_show(zone->edge.win); } \
884          else if (zone->edge.win) ecore_x_window_hide(zone->edge.win); \
885       } \
886       else { \
887          if (NEED_EDGE(ed)) { if (zone->edge.win) ecore_x_window_show(zone->edge.win); } \
888          else if (zone->edge.win) ecore_x_window_hide(zone->edge.win); \
889       } \
890    } while (0)
891
892    CHECK_EDGE(l, E_ZONE_EDGE_LEFT, left);
893    CHECK_EDGE(r, E_ZONE_EDGE_RIGHT, right);
894    CHECK_EDGE(t, E_ZONE_EDGE_TOP, top);
895    CHECK_EDGE(b, E_ZONE_EDGE_BOTTOM, bottom);
896
897 #define CHECK_CORNER(v1, v2, ed, win1, win2) \
898    if ((!v1) && (!v2)) { \
899       if (NEED_EDGE(ed)) { \
900          if (zone->corner.win1) ecore_x_window_show(zone->corner.win1); \
901          if (zone->corner.win2) ecore_x_window_show(zone->corner.win2); \
902       } \
903       else { \
904          if (zone->corner.win1) ecore_x_window_hide(zone->corner.win1); \
905          if (zone->corner.win2) ecore_x_window_hide(zone->corner.win2); \
906       } \
907    } \
908    else { \
909       if (NEED_FLIP_EDGE(ed)) { \
910          if (zone->corner.win1) ecore_x_window_show(zone->corner.win1); \
911          if (zone->corner.win2) ecore_x_window_show(zone->corner.win2); \
912       } \
913       else { \
914          if (zone->corner.win1) ecore_x_window_hide(zone->corner.win1); \
915          if (zone->corner.win2) ecore_x_window_hide(zone->corner.win2); \
916       } \
917    }
918
919    CHECK_CORNER(l, t, E_ZONE_EDGE_TOP_LEFT, left_top, top_left);
920    CHECK_CORNER(r, t, E_ZONE_EDGE_TOP_RIGHT, right_top, top_right);
921    CHECK_CORNER(l, b, E_ZONE_EDGE_BOTTOM_LEFT, left_bottom, bottom_left);
922    CHECK_CORNER(r, b, E_ZONE_EDGE_BOTTOM_RIGHT, right_bottom, bottom_right);
923 }
924
925 EAPI Eina_Bool
926 e_zone_exists_direction(E_Zone *zone, E_Zone_Edge edge)
927 {
928    Eina_List *l;
929    E_Zone *z2;
930
931    EINA_LIST_FOREACH(zone->container->zones, l, z2)
932      {
933         if (zone == z2) continue;
934
935         switch (edge)
936           {
937            case E_ZONE_EDGE_TOP_LEFT:
938              if (((E_SPANS_COMMON(0, zone->x + zone->w, z2->x, z2->w)) &&
939                   (z2->y < zone->y)) ||
940                  ((E_SPANS_COMMON(0, zone->y + zone->h, z2->y, z2->h)) &&
941                   (z2->x < zone->x)))
942                 return EINA_TRUE;
943              break;
944            case E_ZONE_EDGE_TOP:
945              if ((E_SPANS_COMMON(zone->x, zone->w, z2->x, z2->w)) &&
946                  (z2->y < zone->y))
947                 return EINA_TRUE;
948              break;
949            case E_ZONE_EDGE_TOP_RIGHT:
950              if (((E_SPANS_COMMON(zone->x, 99999, z2->x, z2->w)) &&
951                   (z2->y < zone->y)) ||
952                  ((E_SPANS_COMMON(0, zone->y + zone->h, z2->y, z2->h)) &&
953                   (z2->x >= (zone->x + zone->w))))
954                 return EINA_TRUE;
955              break;
956
957            case E_ZONE_EDGE_LEFT:
958              if ((E_SPANS_COMMON(zone->y, zone->h, z2->y, z2->h)) &&
959                  (z2->x < zone->x))
960                 return EINA_TRUE;
961              break;
962
963            case E_ZONE_EDGE_RIGHT:
964              if ((E_SPANS_COMMON(zone->y, zone->h, z2->y, z2->h)) &&
965                  (z2->x >= (zone->x + zone->w)))
966                 return EINA_TRUE;
967              break;
968
969            case E_ZONE_EDGE_BOTTOM_LEFT:
970              if (((E_SPANS_COMMON(0, zone->x + zone->w, z2->x, z2->w)) &&
971                   (z2->y >= (zone->y + zone->h))) ||
972                  ((E_SPANS_COMMON(zone->y, 99999, z2->y, z2->h)) &&
973                   (z2->x < zone->x)))
974                 return EINA_TRUE;
975              break;
976            case E_ZONE_EDGE_BOTTOM:
977              if ((E_SPANS_COMMON(zone->x, zone->w, z2->x, z2->w)) &&
978                  (z2->y >= (zone->y + zone->h)))
979                 return EINA_TRUE;
980              break;
981            case E_ZONE_EDGE_BOTTOM_RIGHT:
982              if (((E_SPANS_COMMON(zone->x, 99999, z2->x, z2->w)) &&
983                   (z2->y >= (zone->y + zone->h))) ||
984                  ((E_SPANS_COMMON(zone->y, 99999, z2->y, z2->h)) &&
985                   (z2->x < zone->x)))
986                 return EINA_TRUE;
987              break;
988
989            default:
990              break;
991           }
992      }
993
994    return EINA_FALSE;
995 }
996
997
998 EAPI void
999 e_zone_edge_flip_eval(E_Zone *zone)
1000 {
1001    Eina_Bool lf, rf, tf, bf;
1002
1003    lf = rf = tf = bf = EINA_TRUE;
1004    if (zone->desk_x_count <= 1) lf = rf = EINA_FALSE;
1005    else if (!e_config->desk_flip_wrap)
1006      {
1007         if (zone->desk_x_current == 0) lf = EINA_FALSE;
1008         if (zone->desk_x_current == (zone->desk_x_count - 1)) rf = EINA_FALSE;
1009      }
1010    if (zone->desk_y_count <= 1) tf = bf = EINA_FALSE;
1011    else if (!e_config->desk_flip_wrap)
1012      {
1013         if (zone->desk_y_current == 0) tf = EINA_FALSE;
1014         if (zone->desk_y_current == (zone->desk_y_count - 1)) bf = EINA_FALSE;
1015      }
1016    e_zone_edges_desk_flip_capable(zone, lf, rf, tf, bf);
1017 }
1018
1019 EAPI void
1020 e_zone_edge_new(E_Zone_Edge edge)
1021 {
1022    Eina_List *l, *ll, *lll;
1023    E_Manager *man;
1024    E_Container *con;
1025    E_Zone *zone;
1026    int cw, ch;
1027
1028    // configurably disallow edge bindings when we have more than 1 root
1029    // window (ie pure old multihead) since we don't know which direction
1030    // other root windows are in
1031    if ((!e_config->multiscreen_flip) && (eina_list_count(e_manager_list()) > 1)) return;
1032    EINA_LIST_FOREACH(e_manager_list(), l, man)
1033      {
1034         EINA_LIST_FOREACH(man->containers, ll, con)
1035           {
1036              EINA_LIST_FOREACH(con->zones, lll, zone)
1037                {
1038                   // don't allow bindings on edges that are on the boundary
1039                   // between zones
1040                   if (e_zone_exists_direction(zone, edge)) continue;
1041                   cw = zone->w * E_ZONE_CORNER_RATIO;
1042                   ch = zone->h * E_ZONE_CORNER_RATIO;
1043                   switch (edge)
1044                     {
1045                      case E_ZONE_EDGE_NONE:
1046                        /* noop */
1047                        break;
1048
1049                      case E_ZONE_EDGE_LEFT:
1050                        if (!zone->edge.left)
1051                          {
1052                             zone->edge.left = ecore_x_window_input_new(con->win,
1053                                                                        zone->x, zone->y + ch, 1,
1054                                                                        zone->h - 2 * ch);
1055                             ecore_x_window_show(zone->edge.left);
1056                          }
1057                        break;
1058
1059                      case E_ZONE_EDGE_RIGHT:
1060                        if (!zone->edge.right)
1061                          {
1062                             zone->edge.right = ecore_x_window_input_new(con->win,
1063                                                                         zone->x + zone->w - 1,
1064                                                                         zone->y + ch, 1, zone->h - 2 * ch);
1065                             ecore_x_window_show(zone->edge.right);
1066                          }
1067                        break;
1068
1069                      case E_ZONE_EDGE_TOP:
1070                        if (!zone->edge.top)
1071                          {
1072                             zone->edge.top = ecore_x_window_input_new(con->win,
1073                                                                       zone->x + 1 + cw, zone->y,
1074                                                                       zone->w - 2 * cw - 2, 1);
1075                             ecore_x_window_show(zone->edge.top);
1076                          }
1077                        break;
1078
1079                      case E_ZONE_EDGE_BOTTOM:
1080                        if (!zone->edge.bottom)
1081                          {
1082                             zone->edge.bottom = ecore_x_window_input_new(con->win,
1083                                                                          zone->x + 1 + cw, zone->y + zone->h - 1,
1084                                                                          zone->w - 2 - 2 * cw, 1);
1085                             ecore_x_window_show(zone->edge.bottom);
1086                          }
1087                        break;
1088
1089                      case E_ZONE_EDGE_TOP_LEFT:
1090                        if (!zone->corner.left_top)
1091                          {
1092                             zone->corner.left_top = ecore_x_window_input_new(con->win,
1093                                                                              zone->x, zone->y, 1, ch);
1094                             ecore_x_window_show(zone->corner.left_top);
1095                          }
1096                        if (!zone->corner.top_left)
1097                          {
1098                             zone->corner.top_left = ecore_x_window_input_new(con->win,
1099                                                                              zone->x + 1, zone->y, cw, 1);
1100                             ecore_x_window_show(zone->corner.top_left);
1101                          }
1102                        break;
1103
1104                      case E_ZONE_EDGE_TOP_RIGHT:
1105                        if (!zone->corner.top_right)
1106                          {
1107                             zone->corner.top_right = ecore_x_window_input_new(con->win,
1108                                                                               zone->x + zone->w - cw - 2,
1109                                                                               zone->y, cw, 1);
1110                             ecore_x_window_show(zone->corner.top_right);
1111                          }
1112                        if (!zone->corner.right_top)
1113                          {
1114                             zone->corner.right_top = ecore_x_window_input_new(con->win,
1115                                                                               zone->x + zone->w - 1,
1116                                                                               zone->y, 1, ch);
1117                             ecore_x_window_show(zone->corner.right_top);
1118                          }
1119                        break;
1120
1121                      case E_ZONE_EDGE_BOTTOM_RIGHT:
1122                        if (!zone->corner.right_bottom)
1123                          {
1124                             zone->corner.right_bottom = ecore_x_window_input_new(con->win,
1125                                                                                  zone->x + zone->w - 1,
1126                                                                                  zone->y + zone->h - ch, 1, ch);
1127                             ecore_x_window_show(zone->corner.right_bottom);
1128                          }
1129                        if (!zone->corner.bottom_right)
1130                          {
1131                             zone->corner.bottom_right = ecore_x_window_input_new(con->win,
1132                                                                                  zone->x + zone->w - cw - 2,
1133                                                                                  zone->y + zone->h - 1, cw, 1);
1134
1135                             ecore_x_window_show(zone->corner.bottom_right);
1136                          }
1137                        break;
1138
1139                      case E_ZONE_EDGE_BOTTOM_LEFT:
1140                        if (!zone->corner.bottom_left)
1141                          {
1142                             zone->corner.bottom_left = ecore_x_window_input_new(con->win,
1143                                                                                 zone->x + 1,
1144                                                                                 zone->y + zone->h - 1, cw, 1);
1145                             ecore_x_window_show(zone->corner.bottom_left);
1146                          }
1147                        if (!zone->corner.left_bottom)
1148                          {
1149                             zone->corner.left_bottom = ecore_x_window_input_new(con->win,
1150                                                                                 zone->x, zone->y + zone->h - ch,
1151                                                                                 1, ch);
1152                             ecore_x_window_show(zone->corner.left_bottom);
1153                          }
1154                        break;
1155                     }
1156                   if (e_config->fullscreen_flip)
1157                     e_zone_edge_win_layer_set(zone, 250);
1158                   else
1159                     e_zone_edge_win_layer_set(zone, 200);
1160                }
1161           }
1162      }
1163 }
1164
1165 EAPI void
1166 e_zone_edge_free(E_Zone_Edge edge)
1167 {
1168    Eina_List *l, *ll, *lll;
1169    E_Manager *man;
1170    E_Container *con;
1171    E_Zone *zone;
1172
1173    EINA_LIST_FOREACH(e_manager_list(), l, man)
1174      {
1175         EINA_LIST_FOREACH(man->containers, ll, con)
1176           {
1177              EINA_LIST_FOREACH(con->zones, lll, zone)
1178                {
1179                   switch (edge)
1180                     {
1181                      case E_ZONE_EDGE_NONE:
1182                        /* noop */
1183                        break;
1184
1185                      case E_ZONE_EDGE_LEFT:
1186                        if (zone->edge.left) ecore_x_window_free(zone->edge.left);
1187                        zone->edge.left = 0;
1188                        break;
1189
1190                      case E_ZONE_EDGE_RIGHT:
1191                        if (zone->edge.right) ecore_x_window_free(zone->edge.right);
1192                        zone->edge.right = 0;
1193                        break;
1194
1195                      case E_ZONE_EDGE_TOP:
1196                        if (zone->edge.top) ecore_x_window_free(zone->edge.top);
1197                        zone->edge.top = 0;
1198                        break;
1199
1200                      case E_ZONE_EDGE_BOTTOM:
1201                        if (zone->edge.bottom) ecore_x_window_free(zone->edge.bottom);
1202                        zone->edge.bottom = 0;
1203                        break;
1204
1205                      case E_ZONE_EDGE_TOP_LEFT:
1206                        if (zone->corner.left_top) ecore_x_window_free(zone->corner.left_top);
1207                        if (zone->corner.top_left) ecore_x_window_free(zone->corner.top_left);
1208                        zone->corner.left_top = 0;
1209                        zone->corner.top_left = 0;
1210                        break;
1211
1212                      case E_ZONE_EDGE_TOP_RIGHT:
1213                        if (zone->corner.top_right) ecore_x_window_free(zone->corner.top_right);
1214                        if (zone->corner.right_top) ecore_x_window_free(zone->corner.right_top);
1215                        zone->corner.top_right = 0;
1216                        zone->corner.right_top = 0;
1217                        break;
1218
1219                      case E_ZONE_EDGE_BOTTOM_RIGHT:
1220                        if (zone->corner.right_bottom) ecore_x_window_free(zone->corner.right_bottom);
1221                        if (zone->corner.bottom_right) ecore_x_window_free(zone->corner.bottom_right);
1222                        zone->corner.right_bottom = 0;
1223                        zone->corner.bottom_right = 0;
1224                        break;
1225
1226                      case E_ZONE_EDGE_BOTTOM_LEFT:
1227                        if (zone->corner.bottom_left) ecore_x_window_free(zone->corner.bottom_left);
1228                        if (zone->corner.left_bottom) ecore_x_window_free(zone->corner.left_bottom);
1229                        zone->corner.bottom_left = 0;
1230                        zone->corner.left_bottom = 0;
1231                        break;
1232                     }
1233                }
1234           }
1235      }
1236 }
1237
1238 EAPI void
1239 e_zone_edge_win_layer_set(E_Zone *zone,
1240                           int     layer)
1241 {
1242    if (zone->corner.left_bottom) e_container_window_raise(zone->container, zone->corner.left_bottom, layer);
1243    if (zone->corner.left_top) e_container_window_raise(zone->container, zone->corner.left_top, layer);
1244    if (zone->corner.top_left) e_container_window_raise(zone->container, zone->corner.top_left, layer);
1245    if (zone->corner.top_right) e_container_window_raise(zone->container, zone->corner.top_right, layer);
1246    if (zone->corner.right_top) e_container_window_raise(zone->container, zone->corner.right_top, layer);
1247    if (zone->corner.right_bottom) e_container_window_raise(zone->container, zone->corner.right_bottom, layer);
1248    if (zone->corner.bottom_right) e_container_window_raise(zone->container, zone->corner.bottom_right, layer);
1249    if (zone->corner.bottom_left) e_container_window_raise(zone->container, zone->corner.bottom_left, layer);
1250
1251    if (zone->edge.left) e_container_window_raise(zone->container, zone->edge.left, layer);
1252    if (zone->edge.right) e_container_window_raise(zone->container, zone->edge.right, layer);
1253    if (zone->edge.top) e_container_window_raise(zone->container, zone->edge.top, layer);
1254    if (zone->edge.bottom) e_container_window_raise(zone->container, zone->edge.bottom, layer);
1255 }
1256
1257 static void
1258 _e_zone_useful_geometry_calc(E_Zone *zone)
1259 {
1260    const E_Shelf *shelf;
1261    Eina_List *shelves;
1262    int x0, x1, yy0, yy1;
1263
1264    x0 = 0;
1265    yy0 = 0;
1266    x1 = zone->w;
1267    yy1 = zone->h;
1268    shelves = e_shelf_list_all();
1269    EINA_LIST_FREE(shelves, shelf)
1270      {
1271         E_Config_Shelf_Desk *sd;
1272         E_Gadcon_Orient orient;
1273         Eina_List *ll;
1274         int skip_shelf = 0;
1275
1276         if (shelf->zone != zone)
1277           continue;
1278
1279         if (shelf->cfg)
1280           {
1281              if (shelf->cfg->overlap)
1282                continue;
1283
1284              if (shelf->cfg->autohide)
1285                continue;
1286              orient = shelf->cfg->orient;
1287
1288              if (shelf->cfg->desk_show_mode)
1289                {
1290                   skip_shelf = 1;
1291                   EINA_LIST_FOREACH(shelf->cfg->desk_list, ll, sd)
1292                     {
1293                        if (!sd) continue;
1294                        if ((sd->x == zone->desk_x_current) && (sd->y == zone->desk_y_current))
1295                          {
1296                             skip_shelf = 0;
1297                             break;
1298                          }
1299                     }
1300                   if (skip_shelf)
1301                     continue;
1302                }
1303           }
1304         else
1305           orient = shelf->gadcon->orient;
1306
1307         switch (orient)
1308           {
1309             /* these are non-edje orientations */
1310             case E_GADCON_ORIENT_FLOAT:
1311             case E_GADCON_ORIENT_HORIZ:
1312             case E_GADCON_ORIENT_VERT:
1313               break;
1314
1315             case E_GADCON_ORIENT_TOP:
1316             case E_GADCON_ORIENT_CORNER_TL:
1317             case E_GADCON_ORIENT_CORNER_TR:
1318               if (yy0 < shelf->h)
1319                 yy0 = shelf->h;
1320               break;
1321
1322             case E_GADCON_ORIENT_BOTTOM:
1323             case E_GADCON_ORIENT_CORNER_BL:
1324             case E_GADCON_ORIENT_CORNER_BR:
1325               if (yy1 > zone->h - shelf->h)
1326                 yy1 = zone->h - shelf->h;
1327               break;
1328               break;
1329
1330             case E_GADCON_ORIENT_LEFT:
1331             case E_GADCON_ORIENT_CORNER_LT:
1332             case E_GADCON_ORIENT_CORNER_LB:
1333               if (x0 < shelf->w)
1334                 x0 = shelf->w;
1335               break;
1336
1337             case E_GADCON_ORIENT_RIGHT:
1338             case E_GADCON_ORIENT_CORNER_RT:
1339             case E_GADCON_ORIENT_CORNER_RB:
1340               if (x1 > zone->w - shelf->w)
1341                 x1 = zone->w - shelf->w;
1342               break;
1343             default:
1344               break;
1345           }
1346      }
1347
1348    zone->useful_geometry.x = zone->x + x0;
1349    zone->useful_geometry.y = zone->y + yy0;
1350    zone->useful_geometry.w = x1 - x0;
1351    zone->useful_geometry.h = yy1 - yy0;
1352    zone->useful_geometry.dirty = 0;
1353 }
1354
1355 /**
1356  * Get (or calculate) the useful (or free, without any shelves) area.
1357  */
1358 EAPI void
1359 e_zone_useful_geometry_get(E_Zone *zone,
1360                            int    *x,
1361                            int    *y,
1362                            int    *w,
1363                            int    *h)
1364 {
1365    Eina_List *l;
1366    E_Shelf *shelf;
1367
1368    E_OBJECT_CHECK(zone);
1369    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1370
1371    if (!zone->useful_geometry.dirty)
1372      {
1373         EINA_LIST_FOREACH(e_shelf_list(), l, shelf)
1374           {
1375              if (!shelf->cfg) continue;
1376              if (shelf->cfg->desk_show_mode)
1377                {
1378                   _e_zone_useful_geometry_calc(zone);
1379                   break;
1380                }
1381           }
1382      }
1383    else
1384      _e_zone_useful_geometry_calc(zone);
1385
1386    if (x) *x = zone->useful_geometry.x;
1387    if (y) *y = zone->useful_geometry.y;
1388    if (w) *w = zone->useful_geometry.w;
1389    if (h) *h = zone->useful_geometry.h;
1390 }
1391
1392 /**
1393  * Mark as dirty so e_zone_useful_geometry_get() will need to recalculate.
1394  *
1395  * Call this function when shelves are added or important properties changed.
1396  */
1397 EAPI void
1398 e_zone_useful_geometry_dirty(E_Zone *zone)
1399 {
1400    E_Event_Zone_Move_Resize *ev;
1401
1402    E_OBJECT_CHECK(zone);
1403    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1404
1405    ev = E_NEW(E_Event_Zone_Move_Resize, 1);
1406    ev->zone = zone;
1407    e_object_ref(E_OBJECT(ev->zone));
1408    ecore_event_add(E_EVENT_ZONE_MOVE_RESIZE, ev, _e_zone_event_move_resize_free, NULL);
1409
1410    zone->useful_geometry.dirty = 1;
1411    zone->useful_geometry.x = -1;
1412    zone->useful_geometry.y = -1;
1413    zone->useful_geometry.w = -1;
1414    zone->useful_geometry.h = -1;
1415 }
1416
1417 #ifdef _F_ZONE_WINDOW_ROTATION_
1418 EAPI void
1419 e_zone_rotation_set(E_Zone *zone,
1420                     int     rot)
1421 {
1422    E_Event_Zone_Rotation_Change *ev;
1423
1424    E_OBJECT_CHECK(zone);
1425    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1426    if (!e_config->wm_win_rotation) return;
1427
1428    ELBF(ELBT_ROT, 0, zone->num, "SET ROT a%d", rot);
1429
1430    if ((zone->rot.wait_for_done) ||
1431        (zone->rot.block_count > 0))
1432      {
1433         zone->rot.next = rot;
1434         zone->rot.pending = EINA_TRUE;
1435         return;
1436      }
1437    if (zone->rot.curr == rot) return;
1438
1439    zone->rot.prev = zone->rot.curr;
1440    zone->rot.curr = rot;
1441    zone->rot.wait_for_done = EINA_TRUE;
1442
1443    ev = E_NEW(E_Event_Zone_Rotation_Change, 1);
1444    ev->zone = zone;
1445    e_object_ref(E_OBJECT(ev->zone));
1446    ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE, ev, _e_zone_event_rotation_change_free, NULL);
1447
1448    ELBF(ELBT_ROT, 0, zone->num, "CHANGE ROT a%d", zone->rot.curr);
1449 }
1450
1451 EAPI int
1452 e_zone_rotation_get(E_Zone *zone)
1453 {
1454    E_OBJECT_CHECK(zone);
1455    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1456    return zone->rot.curr;
1457 }
1458
1459 EAPI Eina_Bool
1460 e_zone_rotation_block_set(E_Zone *zone, const char *name_hint, Eina_Bool set)
1461 {
1462    E_Event_Zone_Rotation_Change *ev;
1463
1464    E_OBJECT_CHECK_RETURN(zone, EINA_FALSE);
1465    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE);
1466
1467    if (set) zone->rot.block_count++;
1468    else     zone->rot.block_count--;
1469
1470    ELBF(ELBT_ROT, 0, zone->num, "[%s ROT] count: %d, from %s",
1471         set ? "PAUSE" : "RESUME", zone->rot.block_count, name_hint);
1472
1473    if (zone->rot.block_count <= 0)
1474      {
1475         zone->rot.block_count = 0;
1476         if (zone->rot.pending)
1477           {
1478              zone->rot.prev = zone->rot.curr;
1479              zone->rot.curr = zone->rot.next;
1480              zone->rot.pending = EINA_FALSE;
1481
1482              ev = E_NEW(E_Event_Zone_Rotation_Change, 1);
1483              ev->zone = zone;
1484              e_object_ref(E_OBJECT(ev->zone));
1485              ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE, ev, _e_zone_event_rotation_change_free, NULL);
1486
1487              ELBF(ELBT_ROT, 0, zone->num, "CHANGE ROT(pending) a%d", zone->rot.curr);
1488           }
1489      }
1490
1491    return EINA_TRUE;
1492 }
1493
1494 EAPI void
1495 e_zone_rotation_update_done(E_Zone *zone)
1496 {
1497    E_Event_Zone_Rotation_Change *ev;
1498
1499    E_OBJECT_CHECK(zone);
1500    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1501    if (!e_config->wm_win_rotation) return;
1502
1503    ELBF(ELBT_ROT, 0, zone->num, "DONE ROT a%d", zone->rot.curr);
1504
1505    zone->rot.wait_for_done = EINA_FALSE;
1506    if ((zone->rot.pending) &&
1507        (zone->rot.block_count == 0))
1508      {
1509         zone->rot.prev = zone->rot.curr;
1510         zone->rot.curr = zone->rot.next;
1511         zone->rot.pending = EINA_FALSE;
1512
1513         ev = E_NEW(E_Event_Zone_Rotation_Change, 1);
1514         ev->zone = zone;
1515         e_object_ref(E_OBJECT(ev->zone));
1516         ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE, ev, _e_zone_event_rotation_change_free, NULL);
1517
1518         ELBF(ELBT_ROT, 0, zone->num, "CHANGE ROT(pending) a%d", zone->rot.curr);
1519      }
1520 }
1521
1522 EAPI void
1523 e_zone_rotation_update_cancel(E_Zone *zone)
1524 {
1525    E_OBJECT_CHECK(zone);
1526    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1527    if (!e_config->wm_win_rotation) return;
1528
1529    zone->rot.wait_for_done = EINA_FALSE;
1530    if (zone->rot.pending)
1531      {
1532         zone->rot.prev = zone->rot.curr;
1533         zone->rot.curr = zone->rot.next;
1534         zone->rot.pending = EINA_FALSE;
1535      }
1536
1537    ELBF(ELBT_ROT, 0, zone->num, "CANCEL ROT a%d", zone->rot.curr);
1538 }
1539 #endif
1540
1541 /* local subsystem functions */
1542 static void
1543 _e_zone_free(E_Zone *zone)
1544 {
1545    E_Container *con;
1546    int x, y;
1547
1548    //printf("@@@@@@@@@@ e_zone_free: %i %i | %i %i %ix%i = %p\n", zone->num, zone->id, zone->x, zone->y, zone->w, zone->h, zone);
1549    /* Delete the edge windows if they exist */
1550    if (zone->edge.top) ecore_x_window_free(zone->edge.top);
1551    if (zone->edge.bottom) ecore_x_window_free(zone->edge.bottom);
1552    if (zone->edge.left) ecore_x_window_free(zone->edge.left);
1553    if (zone->edge.right) ecore_x_window_free(zone->edge.right);
1554    if (zone->corner.left_bottom) ecore_x_window_free(zone->corner.left_bottom);
1555    if (zone->corner.left_top) ecore_x_window_free(zone->corner.left_top);
1556    if (zone->corner.top_left) ecore_x_window_free(zone->corner.top_left);
1557    if (zone->corner.top_right) ecore_x_window_free(zone->corner.top_right);
1558    if (zone->corner.right_top) ecore_x_window_free(zone->corner.right_top);
1559    if (zone->corner.right_bottom) ecore_x_window_free(zone->corner.right_bottom);
1560    if (zone->corner.bottom_right) ecore_x_window_free(zone->corner.bottom_right);
1561    if (zone->corner.bottom_left) ecore_x_window_free(zone->corner.bottom_left);
1562
1563    /* Delete the object event callbacks */
1564    evas_object_event_callback_del(zone->bg_event_object,
1565                                   EVAS_CALLBACK_MOUSE_DOWN,
1566                                   _e_zone_cb_bg_mouse_down);
1567    evas_object_event_callback_del(zone->bg_event_object,
1568                                   EVAS_CALLBACK_MOUSE_UP,
1569                                   _e_zone_cb_bg_mouse_up);
1570
1571    if (zone->black_ecore_evas)
1572      {
1573         e_canvas_del(zone->black_ecore_evas);
1574         ecore_evas_free(zone->black_ecore_evas);
1575         zone->black_ecore_evas = NULL;
1576      }
1577    if (zone->cur_mouse_action)
1578      {
1579         e_object_unref(E_OBJECT(zone->cur_mouse_action));
1580         zone->cur_mouse_action = NULL;
1581      }
1582
1583    /* remove handlers */
1584    E_FREE_LIST(zone->handlers, ecore_event_handler_del);
1585
1586    con = zone->container;
1587    if (zone->name) eina_stringshare_del(zone->name);
1588    con->zones = eina_list_remove(con->zones, zone);
1589    evas_object_del(zone->bg_event_object);
1590    evas_object_del(zone->bg_clip_object);
1591    evas_object_del(zone->bg_object);
1592    if (zone->prev_bg_object) evas_object_del(zone->prev_bg_object);
1593    if (zone->transition_object) evas_object_del(zone->transition_object);
1594
1595    /* free desks */
1596    for (x = 0; x < zone->desk_x_count; x++)
1597      {
1598         for (y = 0; y < zone->desk_y_count; y++)
1599           e_object_del(E_OBJECT(zone->desks[x + (y * zone->desk_x_count)]));
1600      }
1601    free(zone->desks);
1602
1603    _e_zone_black_free(zone);
1604
1605    free(zone);
1606 }
1607
1608 static void
1609 _e_zone_cb_bg_mouse_down(void            *data,
1610                          Evas *evas       __UNUSED__,
1611                          Evas_Object *obj __UNUSED__,
1612                          void *event_info __UNUSED__)
1613 {
1614    E_Zone *zone;
1615
1616    zone = data;
1617    if (e_menu_grab_window_get()) return;
1618
1619    if (!zone->cur_mouse_action)
1620      {
1621         if (ecore_event_current_type_get() == ECORE_EVENT_MOUSE_BUTTON_DOWN)
1622           {
1623              Ecore_Event_Mouse_Button *ev2;
1624
1625              ev2 = ecore_event_current_event_get();
1626              zone->cur_mouse_action =
1627                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_ZONE,
1628                                                   E_OBJECT(zone), ev2);
1629              if (zone->cur_mouse_action)
1630                {
1631                   if ((!zone->cur_mouse_action->func.end_mouse) &&
1632                       (!zone->cur_mouse_action->func.end))
1633                     zone->cur_mouse_action = NULL;
1634                   if (zone->cur_mouse_action)
1635                     e_object_ref(E_OBJECT(zone->cur_mouse_action));
1636                }
1637           }
1638      }
1639 }
1640
1641 static void
1642 _e_zone_cb_bg_mouse_up(void            *data,
1643                        Evas *evas       __UNUSED__,
1644                        Evas_Object *obj __UNUSED__,
1645                        void *event_info __UNUSED__)
1646 {
1647    E_Zone *zone;
1648
1649    zone = data;
1650    if (zone->cur_mouse_action)
1651      {
1652         if (ecore_event_current_type_get() == ECORE_EVENT_MOUSE_BUTTON_UP)
1653           {
1654              Ecore_Event_Mouse_Button *ev2;
1655
1656              ev2 = ecore_event_current_event_get();
1657              if (zone->cur_mouse_action->func.end_mouse)
1658                zone->cur_mouse_action->func.end_mouse(E_OBJECT(zone), "", ev2);
1659              else if (zone->cur_mouse_action->func.end)
1660                zone->cur_mouse_action->func.end(E_OBJECT(zone), "");
1661           }
1662         e_object_unref(E_OBJECT(zone->cur_mouse_action));
1663         zone->cur_mouse_action = NULL;
1664      }
1665    else
1666      {
1667         if (ecore_event_current_type_get() == ECORE_EVENT_MOUSE_BUTTON_UP)
1668           {
1669              Ecore_Event_Mouse_Button *ev2;
1670
1671              ev2 = ecore_event_current_event_get();
1672              e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_ZONE,
1673                                               E_OBJECT(zone), ev2);
1674           }
1675      }
1676 }
1677
1678 static void
1679 _e_zone_event_zone_desk_count_set_free(void *data __UNUSED__,
1680                                        void      *ev)
1681 {
1682    E_Event_Zone_Desk_Count_Set *e;
1683
1684    e = ev;
1685    e_object_unref(E_OBJECT(e->zone));
1686    free(e);
1687 }
1688
1689 static Eina_Bool
1690 _e_zone_cb_mouse_in(void    *data,
1691                     int type __UNUSED__,
1692                     void    *event)
1693 {
1694    Ecore_X_Event_Mouse_In *ev;
1695    E_Event_Zone_Edge *zev;
1696    E_Zone_Edge edge;
1697    E_Zone *zone;
1698
1699    ev = event;
1700    zone = data;
1701
1702    edge = _e_zone_detect_edge(zone, ev->win);
1703    if (edge == E_ZONE_EDGE_NONE) return ECORE_CALLBACK_PASS_ON;
1704
1705    zev = E_NEW(E_Event_Zone_Edge, 1);
1706    zev->zone = zone;
1707    zev->edge = edge;
1708    zev->x = ev->root.x;
1709    zev->y = ev->root.y;
1710    zev->modifiers = ev->modifiers;
1711    ecore_event_add(E_EVENT_ZONE_EDGE_IN, zev, NULL, NULL);
1712    e_bindings_edge_in_event_handle(E_BINDING_CONTEXT_ZONE, E_OBJECT(zone), zev);
1713
1714    return ECORE_CALLBACK_PASS_ON;
1715 }
1716
1717 static Eina_Bool
1718 _e_zone_cb_mouse_out(void    *data,
1719                      int type __UNUSED__,
1720                      void    *event)
1721 {
1722    Ecore_X_Event_Mouse_Out *ev;
1723    E_Event_Zone_Edge *zev;
1724    E_Zone_Edge edge;
1725    E_Zone *zone;
1726
1727    ev = event;
1728    zone = data;
1729
1730    edge = _e_zone_detect_edge(zone, ev->win);
1731    if (edge == E_ZONE_EDGE_NONE) return ECORE_CALLBACK_PASS_ON;
1732
1733    zev = E_NEW(E_Event_Zone_Edge, 1);
1734    zev->zone = zone;
1735    zev->edge = edge;
1736    zev->x = ev->root.x;
1737    zev->y = ev->root.y;
1738    zev->modifiers = ev->modifiers;
1739    ecore_event_add(E_EVENT_ZONE_EDGE_OUT, zev, NULL, NULL);
1740    e_bindings_edge_out_event_handle(E_BINDING_CONTEXT_ZONE, E_OBJECT(zone), zev);
1741    return ECORE_CALLBACK_PASS_ON;
1742 }
1743
1744 static Eina_Bool
1745 _e_zone_cb_mouse_down(void    *data,
1746                       int type __UNUSED__,
1747                       void    *event)
1748 {
1749    Ecore_Event_Mouse_Button *ev;
1750    E_Event_Zone_Edge *zev;
1751    E_Zone_Edge edge;
1752    E_Zone *zone;
1753
1754    ev = event;
1755    zone = data;
1756
1757    edge = _e_zone_detect_edge(zone, ev->window);
1758    if (edge == E_ZONE_EDGE_NONE) return ECORE_CALLBACK_PASS_ON;
1759
1760    zev = E_NEW(E_Event_Zone_Edge, 1);
1761    zev->zone = zone;
1762    zev->edge = edge;
1763    zev->x = ev->root.x;
1764    zev->y = ev->root.y;
1765    zev->button = ev->buttons;
1766    zev->modifiers = ev->modifiers;
1767    ecore_event_add(E_EVENT_ZONE_EDGE_OUT, zev, NULL, NULL);
1768    e_bindings_edge_down_event_handle(E_BINDING_CONTEXT_ZONE, E_OBJECT(zone), zev);
1769    return ECORE_CALLBACK_PASS_ON;
1770 }
1771
1772 static Eina_Bool
1773 _e_zone_cb_mouse_up(void    *data,
1774                     int type __UNUSED__,
1775                     void    *event)
1776 {
1777    Ecore_Event_Mouse_Button *ev;
1778    E_Event_Zone_Edge *zev;
1779    E_Zone_Edge edge;
1780    E_Zone *zone;
1781
1782    ev = event;
1783    zone = data;
1784
1785    edge = _e_zone_detect_edge(zone, ev->window);
1786    if (edge == E_ZONE_EDGE_NONE) return ECORE_CALLBACK_PASS_ON;
1787
1788    zev = E_NEW(E_Event_Zone_Edge, 1);
1789    zev->zone = zone;
1790    zev->edge = edge;
1791    zev->x = ev->root.x;
1792    zev->y = ev->root.y;
1793    zev->button = ev->buttons;
1794    zev->modifiers = ev->modifiers;
1795    ecore_event_add(E_EVENT_ZONE_EDGE_OUT, zev, NULL, NULL);
1796    e_bindings_edge_up_event_handle(E_BINDING_CONTEXT_ZONE, E_OBJECT(zone), zev);
1797    return ECORE_CALLBACK_PASS_ON;
1798 }
1799
1800 static Eina_Bool
1801 _e_zone_cb_mouse_move(void    *data,
1802                       int type __UNUSED__,
1803                       void    *event)
1804 {
1805    Ecore_Event_Mouse_Move *ev;
1806    E_Event_Zone_Edge *zev;
1807    E_Zone_Edge edge;
1808    E_Zone *zone;
1809
1810    ev = event;
1811    zone = data;
1812
1813    edge = _e_zone_detect_edge(zone, ev->window);
1814    if (edge == E_ZONE_EDGE_NONE) return ECORE_CALLBACK_PASS_ON;
1815
1816    zev = E_NEW(E_Event_Zone_Edge, 1);
1817    zev->zone = zone;
1818    zev->edge = edge;
1819    zev->x = ev->root.x;
1820    zev->y = ev->root.y;
1821    zev->modifiers = ev->modifiers;
1822    ecore_event_add(E_EVENT_ZONE_EDGE_MOVE, zev, NULL, NULL);
1823    return ECORE_CALLBACK_PASS_ON;
1824 }
1825
1826 static Eina_Bool
1827 _e_zone_cb_desk_after_show(void    *data,
1828                            int type __UNUSED__,
1829                            void    *event)
1830 {
1831    E_Event_Desk_Show *ev;
1832    E_Zone *zone;
1833
1834    ev = event;
1835    zone = data;
1836    if (ev->desk->zone != zone) return ECORE_CALLBACK_PASS_ON;
1837
1838    zone->flip.switching = 0;
1839    return ECORE_CALLBACK_PASS_ON;
1840 }
1841
1842 static Eina_Bool
1843 _e_zone_cb_edge_timer(void *data)
1844 {
1845    E_Zone *zone;
1846    E_Action *act;
1847
1848    zone = data;
1849    act = e_action_find(zone->flip.bind->action);
1850    if (!act)
1851      {
1852         E_FREE(zone->flip.ev);
1853         return ECORE_CALLBACK_CANCEL;
1854      }
1855
1856    if (act->func.go_edge)
1857      act->func.go_edge(E_OBJECT(zone), zone->flip.bind->params, zone->flip.ev);
1858    else if (act->func.go)
1859      act->func.go(E_OBJECT(zone), zone->flip.bind->params);
1860
1861    zone->flip.bind->timer = NULL;
1862
1863    E_FREE(zone->flip.ev);
1864    return ECORE_CALLBACK_CANCEL;
1865 }
1866
1867 static void
1868 _e_zone_event_move_resize_free(void *data __UNUSED__,
1869                                void      *ev)
1870 {
1871    E_Event_Zone_Move_Resize *e;
1872
1873    e = ev;
1874    e_object_unref(E_OBJECT(e->zone));
1875    free(e);
1876 }
1877
1878 static void
1879 _e_zone_event_add_free(void *data __UNUSED__,
1880                        void      *ev)
1881 {
1882    E_Event_Zone_Add *e;
1883
1884    e = ev;
1885    e_object_unref(E_OBJECT(e->zone));
1886    free(e);
1887 }
1888
1889 static void
1890 _e_zone_event_del_free(void *data __UNUSED__,
1891                        void      *ev)
1892 {
1893    E_Event_Zone_Del *e;
1894
1895    e = ev;
1896    e_object_unref(E_OBJECT(e->zone));
1897    free(e);
1898 }
1899
1900 static void
1901 _e_zone_object_del_attach(void *o)
1902 {
1903    E_Zone *zone;
1904    E_Event_Zone_Del *ev;
1905
1906    zone = o;
1907    ev = E_NEW(E_Event_Zone_Del, 1);
1908    ev->zone = zone;
1909    e_object_ref(E_OBJECT(ev->zone));
1910    ecore_event_add(E_EVENT_ZONE_DEL, ev, _e_zone_event_del_free, NULL);
1911 }
1912
1913 static E_Zone_Edge
1914 _e_zone_detect_edge(E_Zone        *zone,
1915                     Ecore_X_Window win)
1916 {
1917    E_Zone_Edge edge = E_ZONE_EDGE_NONE;
1918
1919    if (win == zone->edge.left)
1920      edge = E_ZONE_EDGE_LEFT;
1921    else if (win == zone->edge.top)
1922      edge = E_ZONE_EDGE_TOP;
1923    else if (win == zone->edge.right)
1924      edge = E_ZONE_EDGE_RIGHT;
1925    else if (win == zone->edge.bottom)
1926      edge = E_ZONE_EDGE_BOTTOM;
1927    else if ((win == zone->corner.left_top) ||
1928             (win == zone->corner.top_left))
1929      edge = E_ZONE_EDGE_TOP_LEFT;
1930    else if ((win == zone->corner.right_top) ||
1931             (win == zone->corner.top_right))
1932      edge = E_ZONE_EDGE_TOP_RIGHT;
1933    else if ((win == zone->corner.right_bottom) ||
1934             (win == zone->corner.bottom_right))
1935      edge = E_ZONE_EDGE_BOTTOM_RIGHT;
1936    else if ((win == zone->corner.left_bottom) ||
1937             (win == zone->corner.bottom_left))
1938      edge = E_ZONE_EDGE_BOTTOM_LEFT;
1939    return edge;
1940 }
1941
1942 static void
1943 _e_zone_edge_move_resize(E_Zone *zone)
1944 {
1945    int cw;
1946    int ch;
1947
1948    cw = zone->w * E_ZONE_CORNER_RATIO;
1949    ch = zone->h * E_ZONE_CORNER_RATIO;
1950
1951    if (zone->corner.left_bottom)
1952      ecore_x_window_move_resize(zone->corner.left_bottom,
1953                                 zone->x, zone->y + zone->h - ch, 1, ch);
1954    if (zone->edge.left)
1955      ecore_x_window_move_resize(zone->edge.left,
1956                                 zone->x, zone->y + ch, 1, zone->h - 2 * ch);
1957    if (zone->corner.left_top)
1958      ecore_x_window_move_resize(zone->corner.left_top,
1959                                 zone->x, zone->y, 1, ch);
1960
1961    if (zone->corner.top_left)
1962      ecore_x_window_move_resize(zone->corner.top_left,
1963                                 zone->x + 1, zone->y, cw, 1);
1964    if (zone->edge.top)
1965      ecore_x_window_move_resize(zone->edge.top,
1966                                 zone->x + 1 + cw, zone->y, zone->w - 2 * cw - 2, 1);
1967    if (zone->corner.top_right)
1968      ecore_x_window_move_resize(zone->corner.top_right,
1969                                 zone->x + zone->w - cw - 2, zone->y, cw, 1);
1970
1971    if (zone->corner.right_top)
1972      ecore_x_window_move_resize(zone->corner.right_top,
1973                                 zone->x + zone->w - 1, zone->y, 1, ch);
1974    if (zone->edge.right)
1975      ecore_x_window_move_resize(zone->edge.right,
1976                                 zone->x + zone->w - 1, zone->y + ch, 1, zone->h - 2 * ch);
1977    if (zone->corner.right_bottom)
1978      ecore_x_window_move_resize(zone->corner.right_bottom,
1979                                 zone->x + zone->w - 1, zone->y + zone->h - ch, 1, ch);
1980
1981    if (zone->corner.bottom_right)
1982      ecore_x_window_move_resize(zone->corner.bottom_right,
1983                                 zone->x + 1, zone->y + zone->h - 1, cw, 1);
1984    if (zone->edge.bottom)
1985      ecore_x_window_move_resize(zone->edge.bottom,
1986                                 zone->x + 1 + cw, zone->y + zone->h - 1, zone->w - 2 - 2 * cw, 1);
1987    if (zone->corner.bottom_left)
1988      ecore_x_window_move_resize(zone->corner.bottom_left,
1989                                 zone->x + zone->w - cw - 2, zone->y + zone->h - 1, cw, 1);
1990 }
1991
1992 static void
1993 _e_zone_border_geometry_update(E_Zone *zone)
1994 {
1995    Eina_List *borders, *l;
1996    E_Border *bd;
1997    unsigned int zgeom[4];
1998    
1999    zgeom[0] = zone->x;
2000    zgeom[1] = zone->y;
2001    zgeom[2] = zone->w;
2002    zgeom[3] = zone->h;
2003    borders = e_border_client_list();
2004    EINA_LIST_FOREACH(borders, l, bd)
2005      {
2006         if (bd->zone == zone)
2007           ecore_x_window_prop_card32_set(bd->client.win, 
2008                                          E_ATOM_ZONE_GEOMETRY, 
2009                                          zgeom, 4);
2010      }
2011 }
2012
2013 #ifdef _F_ZONE_WINDOW_ROTATION_
2014 static void
2015 _e_zone_event_rotation_change_free(void *data __UNUSED__,
2016                                    void      *ev)
2017 {
2018    E_Event_Zone_Rotation_Change *e = ev;
2019    e_object_unref(E_OBJECT(e->zone));
2020    E_FREE(e);
2021 }
2022 #endif