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