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