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