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