update for beta release
[framework/uifw/e17.git] / src / modules / illume2 / policies / tablet / policy.c
1 #include "e_illume.h"
2 #include "policy.h"
3 #include "e.h"
4
5 /* local function prototypes */
6 static void _policy_border_set_focus(E_Border *bd);
7 static void _policy_border_move(E_Border *bd, int x, int y);
8 static void _policy_border_resize(E_Border *bd, int w, int h);
9 static void _policy_border_hide_below(E_Border *bd);
10 static void _policy_border_show_below(E_Border *bd);
11 static void _policy_zone_layout_update(E_Zone *zone);
12 static void _policy_zone_layout_indicator(E_Border *bd, E_Illume_Config_Zone *cz);
13 static void _policy_zone_layout_quickpanel(E_Border *bd);
14 static void _policy_zone_layout_softkey(E_Border *bd, E_Illume_Config_Zone *cz);
15 static void _policy_zone_layout_keyboard(E_Border *bd, E_Illume_Config_Zone *cz);
16 static void _policy_zone_layout_home_single(E_Border *bd, E_Illume_Config_Zone *cz);
17 static void _policy_zone_layout_fullscreen(E_Border *bd);
18 static void _policy_zone_layout_app_single(E_Border *bd, E_Illume_Config_Zone *cz);
19 static void _policy_zone_layout_app_dual_top(E_Border *bd, E_Illume_Config_Zone *cz);
20 static void _policy_zone_layout_app_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz);
21 static void _policy_zone_layout_app_dual_left(E_Border *bd, E_Illume_Config_Zone *cz, Eina_Bool force);
22 static void _policy_zone_layout_dialog(E_Border *bd, E_Illume_Config_Zone *cz);
23 static void _policy_zone_layout_splash(E_Border *bd, E_Illume_Config_Zone *cz);
24 static void _policy_zone_layout_conformant_single(E_Border *bd, E_Illume_Config_Zone *cz);
25 #if 0
26 static void _policy_zone_layout_conformant_dual_top(E_Border *bd, E_Illume_Config_Zone *cz);
27 static void _policy_zone_layout_conformant_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz);
28 static void _policy_zone_layout_conformant_dual_left(E_Border *bd, E_Illume_Config_Zone *cz);
29 #endif
30
31 static Eina_List *_pol_focus_stack;
32
33 /* local functions */
34 static void
35 _policy_border_set_focus(E_Border *bd)
36 {
37    if (!bd) return;
38    /* printf("_policy_border_set_focus %s\n", e_border_name_get(bd)); */
39
40    /* if focus is locked out then get out */
41    if (bd->lock_focus_out) return;
42
43    if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
44      {
45         /* check E's focus settings */
46         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
47             ((bd->parent) &&
48              ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
49               ((bd->parent->focused) &&
50                (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))))
51           {
52              /* if the border was hidden due to layout, we need to unhide */
53              if (!bd->visible) e_illume_border_show(bd);
54
55              if ((bd->iconic) && (!bd->lock_user_iconify))
56                e_border_uniconify(bd);
57
58              if (!bd->lock_user_stacking) e_border_raise(bd);
59
60              /* focus the border */
61              e_border_focus_set(bd, 1, 1);
62              /* e_border_raise(bd); */
63              /* hide the border below this one */
64              _policy_border_hide_below(bd);
65
66              /* NB: since we skip needless border evals when container layout
67               * is called (to save cpu cycles), we need to
68               * signal this border that it's focused so that the edj gets
69               * updated.
70               *
71               * This is potentially useless as THIS policy
72               * makes all windows borderless anyway, but it's in here for
73               * completeness
74               e_border_focus_latest_set(bd);
75               if (bd->bg_object)
76               edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
77               if (bd->icon_object)
78               edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
79               e_focus_event_focus_in(bd);
80              */
81           }
82      }
83 }
84
85 static void
86 _policy_border_move(E_Border *bd, int x, int y)
87 {
88    if (!bd) return;
89
90    bd->x = x;
91    bd->y = y;
92    bd->changes.pos = 1;
93    bd->changed = 1;
94 }
95
96 static void
97 _policy_border_resize(E_Border *bd, int w, int h)
98 {
99    if (!bd) return;
100
101    bd->w = w;
102    bd->h = h;
103    bd->client.w = (bd->w - (bd->client_inset.l + bd->client_inset.r));
104    bd->client.h = (bd->h - (bd->client_inset.t + bd->client_inset.b));
105    bd->changes.size = 1;
106    bd->changed = 1;
107 }
108
109 static void
110 _policy_border_hide_below(E_Border *bd)
111 {
112    int pos = 0, i;
113
114    return;
115
116    //   printf("Hide Borders Below: %s %d %d\n",
117    //          bd->client.icccm.name, bd->x, bd->y);
118
119    if (!bd) return;
120    /* printf("_policy_border_hide_below %s\n", e_border_name_get(bd)); */
121    /* determine layering position */
122    if (bd->layer <= 0) pos = 0;
123    else if ((bd->layer > 0) && (bd->layer <= 50)) pos = 1;
124    else if ((bd->layer > 50) && (bd->layer <= 100)) pos = 2;
125    else if ((bd->layer > 100) && (bd->layer <= 150)) pos = 3;
126    else if ((bd->layer > 150) && (bd->layer <= 200)) pos = 4;
127    else pos = 5;
128
129    /* Find the windows below this one */
130    for (i = pos; i >= 2; i--)
131      {
132         Eina_List *l;
133         E_Border *b;
134
135         EINA_LIST_FOREACH(bd->zone->container->layers[i].clients, l, b)
136           {
137              /* skip if it's the same border */
138              if (b == bd) continue;
139
140              /* skip if it's not on this zone */
141              if (b->zone != bd->zone) continue;
142
143              /* skip special borders */
144              if (e_illume_border_is_indicator(b)) continue;
145              if (e_illume_border_is_softkey(b)) continue;
146              if (e_illume_border_is_keyboard(b)) continue;
147              if (e_illume_border_is_quickpanel(b)) continue;
148              if (e_illume_border_is_home(b)) continue;
149
150              if ((bd->fullscreen) || (bd->need_fullscreen))
151                {
152                   if (b->visible) e_illume_border_hide(b);
153                }
154              else
155                {
156                   /* we need to check x/y position */
157                   if (E_CONTAINS(bd->x, bd->y, bd->w, bd->h,
158                                  b->x, b->y, b->w, b->h))
159                     {
160                        if (b->visible) e_illume_border_hide(b);
161                     }
162                }
163           }
164      }
165 }
166
167 static void
168 _policy_border_show_below(E_Border *bd)
169 {
170    Eina_List *l;
171    E_Border *prev;
172    int pos = 0, i;
173
174    //   printf("Show Borders Below: %s %d %d\n",
175    //          bd->client.icccm.class, bd->x, bd->y);
176
177    if (!bd) return;
178    /* printf("_policy_border_show_below %s\n", e_border_name_get(bd)); */
179    if (bd->client.icccm.transient_for)
180      {
181         if ((prev = e_border_find_by_client_window(bd->client.icccm.transient_for)))
182           {
183              _policy_border_set_focus(prev);
184              return;
185           }
186      }
187
188    /* determine layering position */
189    if (bd->layer <= 0) pos = 0;
190    else if ((bd->layer > 0) && (bd->layer <= 50)) pos = 1;
191    else if ((bd->layer > 50) && (bd->layer <= 100)) pos = 2;
192    else if ((bd->layer > 100) && (bd->layer <= 150)) pos = 3;
193    else if ((bd->layer > 150) && (bd->layer <= 200)) pos = 4;
194    else pos = 5;
195
196    /* Find the windows below this one */
197    for (i = pos; i >= 2; i--)
198      {
199         E_Border *b;
200
201         EINA_LIST_REVERSE_FOREACH(bd->zone->container->layers[i].clients, l, b)
202           {
203              /* skip if it's the same border */
204              if (b == bd) continue;
205
206              /* skip if it's not on this zone */
207              if (b->zone != bd->zone) continue;
208
209              /* skip special borders */
210              if (e_illume_border_is_indicator(b)) continue;
211              if (e_illume_border_is_softkey(b)) continue;
212              if (e_illume_border_is_keyboard(b)) continue;
213              if (e_illume_border_is_quickpanel(b)) continue;
214              if (e_illume_border_is_home(b)) continue;
215
216              if ((bd->fullscreen) || (bd->need_fullscreen))
217                {
218                   _policy_border_set_focus(b);
219                   return;
220                }
221              else
222                {
223                   /* need to check x/y position */
224                   if (E_CONTAINS(bd->x, bd->y, bd->w, bd->h,
225                                  b->x, b->y, b->w, b->h))
226                     {
227                        _policy_border_set_focus(b);
228                        return;
229                     }
230                }
231           }
232      }
233
234    /* if we reach here, then there is a problem with showing a window below
235     * this one, so show previous window in stack */
236    EINA_LIST_REVERSE_FOREACH(_pol_focus_stack, l, prev)
237      {
238         if (prev->zone != bd->zone) continue;
239         _policy_border_set_focus(prev);
240         return;
241      }
242
243    /* Fallback to focusing home if all above fails */
244    _policy_focus_home(bd->zone);
245 }
246
247 static void
248 _policy_zone_layout_update(E_Zone *zone)
249 {
250    Eina_List *l;
251    E_Border *bd;
252
253    if (!zone) return;
254
255    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
256      {
257         /* skip borders not on this zone */
258         if (bd->zone != zone) continue;
259
260         /* skip special windows */
261         if (e_illume_border_is_keyboard(bd)) continue;
262         if (e_illume_border_is_quickpanel(bd)) continue;
263
264         /* signal a changed pos here so layout gets updated */
265         bd->changes.pos = 1;
266         bd->changed = 1;
267      }
268 }
269
270 static void
271 _policy_zone_layout_indicator(E_Border *bd, E_Illume_Config_Zone *cz)
272 {
273    if ((!bd) || (!cz)) return;
274
275    /* grab minimum indicator size */
276    e_illume_border_min_get(bd, NULL, &cz->indicator.size);
277
278    /* no point in doing anything here if indicator is hidden */
279    if ((!bd->new_client) && (!bd->visible))
280      {
281         ecore_x_e_illume_indicator_geometry_set(bd->zone->black_win,
282                                                 0, 0, 0, 0);
283         return;
284      }
285
286    /* if we are dragging, then skip it for now */
287    if (bd->client.illume.drag.drag)
288      {
289         /* when dragging indicator, we need to trigger a layout update */
290         ecore_x_e_illume_indicator_geometry_set(bd->zone->black_win,
291                                                 0, 0, 0, 0);
292         _policy_zone_layout_update(bd->zone);
293         return;
294      }
295
296    //   printf("\tLayout Indicator: %d\n", bd->zone->id);
297
298    /* lock indicator window from dragging if we need to */
299    if ((cz->mode.dual == 1) && (cz->mode.side == 0))
300      ecore_x_e_illume_drag_locked_set(bd->client.win, 0);
301    else
302      ecore_x_e_illume_drag_locked_set(bd->client.win, 1);
303
304    if ((bd->w != bd->zone->w) || (bd->h != cz->indicator.size))
305      _policy_border_resize(bd, bd->zone->w, cz->indicator.size);
306
307    if (!cz->mode.dual)
308      {
309         /* move to 0, 0 (relative to zone) if needed */
310         if ((bd->x != bd->zone->x) || (bd->y != bd->zone->y))
311           {
312              _policy_border_move(bd, bd->zone->x, bd->zone->y);
313              ecore_x_e_illume_quickpanel_position_update_send(bd->client.win);
314           }
315      }
316    else
317      {
318         if (cz->mode.side == 0)
319           {
320              /* top mode...indicator is draggable so just set X.
321               * in this case, the indicator itself should be responsible for
322               * sending the quickpanel position update message when it is
323               * finished dragging */
324              if (bd->x != bd->zone->x)
325                _policy_border_move(bd, bd->zone->x, bd->y);
326           }
327         else
328           {
329              /* move to 0, 0 (relative to zone) if needed */
330              if ((bd->x != bd->zone->x) || (bd->y != bd->zone->y))
331                {
332                   _policy_border_move(bd, bd->zone->x, bd->zone->y);
333                   ecore_x_e_illume_quickpanel_position_update_send(bd->client.win);
334                }
335           }
336      }
337    ecore_x_e_illume_indicator_geometry_set(bd->zone->black_win,
338                                            bd->x, bd->y,
339                                            bd->w, bd->h);
340
341    if (bd->layer != POL_INDICATOR_LAYER)
342      e_border_layer_set(bd, POL_INDICATOR_LAYER);
343 }
344
345 #define ZONE_GEOMETRY                                   \
346   int x, y, w, h;                                       \
347   e_zone_useful_geometry_get(bd->zone, &x, &y, &w, &h); \
348   x += bd->zone->x;                                     \
349   y += bd->zone->y;                                     \
350
351 static void
352 _border_geometry_set(E_Border *bd, int x, int y, int w, int h, int layer)
353 {
354    if ((bd->w != w) || (bd->h != h))
355      _policy_border_resize(bd, w, h);
356
357    if ((bd->x != x) || (bd->y != y))
358      _policy_border_move(bd, x, y);
359
360    if ((int)bd->layer != layer) e_border_layer_set(bd, layer);
361 }
362
363 static void
364 _policy_zone_layout_quickpanel(E_Border *bd)
365 {
366    int mh;
367
368    if (!bd) return;
369
370    e_illume_border_min_get(bd, NULL, &mh);
371
372    if ((bd->w != bd->zone->w) || (bd->h != mh))
373      _policy_border_resize(bd, bd->zone->w, mh);
374
375    if (bd->layer != POL_QUICKPANEL_LAYER)
376      e_border_layer_set(bd, POL_QUICKPANEL_LAYER);
377 }
378
379 static void
380 _policy_zone_layout_softkey(E_Border *bd, E_Illume_Config_Zone *cz)
381 {
382    int ny;
383
384    if ((!bd) || (!cz)) return;
385    if (!bd->visible)
386      {
387         ecore_x_e_illume_softkey_geometry_set(bd->zone->black_win, 0, 0, 0, 0);
388         return;
389      }
390
391    ZONE_GEOMETRY;
392
393    e_illume_border_min_get(bd, NULL, &cz->softkey.size);
394
395    /* if we are dragging, then skip it for now */
396    /* NB: Disabled currently until we confirm that softkey should be draggable */
397    //   if (bd->client.illume.drag.drag) return;
398
399    if ((bd->w != w) || (bd->h != cz->softkey.size))
400      _policy_border_resize(bd, w, cz->softkey.size);
401
402    ny = ((bd->zone->y + bd->zone->h) - cz->softkey.size);
403
404    /* NB: not sure why yet, but on startup the border->y is reporting
405     * that it is already in this position...but it's actually not.
406     * So for now, just disable the ny check until this gets sorted out */
407
408    if ((bd->x != x) || (bd->y != ny))
409      _policy_border_move(bd, x, ny);
410
411    /* _border_geometry_set(bd, x, ny, nw, nh, bd, POL_CONFORMANT_LAYER); */
412
413    ecore_x_e_illume_softkey_geometry_set(bd->zone->black_win,
414                                          bd->x, bd->y,
415                                          bd->w, bd->h);
416
417    if (bd->layer != POL_SOFTKEY_LAYER) e_border_layer_set(bd, POL_SOFTKEY_LAYER);
418 }
419
420
421
422 #define MIN_HEIGHT 100
423
424 static Eina_Bool
425 _policy_layout_app_check(E_Border *bd)
426 {
427    if (!bd)
428      return EINA_FALSE;
429
430    if (!bd->visible)
431      return EINA_FALSE;
432
433    if ((bd->desk != e_desk_current_get(bd->zone)) && (!bd->sticky))
434      return EINA_FALSE;
435
436    return EINA_TRUE;
437 }
438
439
440 static void
441 _policy_keyboard_restrict(E_Border *bd, int *h)
442 {
443    int kh;
444
445    if (bd->client.vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
446      {
447         e_illume_keyboard_safe_app_region_get(bd->zone, NULL, NULL, NULL, &kh);
448         kh -= bd->zone->h - *h;
449         if ((kh < *h) && (kh > MIN_HEIGHT))
450           *h = kh;
451      }
452 }
453
454 static void
455 _policy_indicator_restrict(E_Illume_Config_Zone *cz, int *y, int *h)
456 {
457    if ((cz->indicator.size) && (*y < cz->indicator.size))
458      {
459         *h -= cz->indicator.size;
460         *y = cz->indicator.size;
461      }
462 }
463
464 static void
465 _policy_softkey_restrict(E_Illume_Config_Zone *cz, int *y, int *h)
466 {
467    if ((cz->softkey.size) && ((*y + *h) > cz->softkey.size))
468      *h -= (*y + *h) - cz->softkey.size;
469 }
470
471 static void
472 _policy_zone_layout_keyboard(E_Border *bd, E_Illume_Config_Zone *cz)
473 {
474    int ny, layer;
475
476    if ((!bd) || (!cz) || (!bd->visible)) return;
477
478    ZONE_GEOMETRY;
479
480    e_illume_border_min_get(bd, NULL, &cz->vkbd.size);
481
482    ny = ((bd->zone->y + bd->zone->h) - cz->vkbd.size);
483
484    /* if ((bd->fullscreen) || (bd->need_fullscreen))
485     *   layer = POL_FULLSCREEN_LAYER;
486     * else */
487    layer = POL_KEYBOARD_LAYER;
488    
489    _border_geometry_set(bd, x, ny, w, cz->vkbd.size, layer);
490 }
491
492 static void
493 _policy_zone_layout_home_single(E_Border *bd, E_Illume_Config_Zone *cz)
494 {
495    if ((!bd) || (!cz) || (!bd->visible)) return;
496
497    ZONE_GEOMETRY;
498    _policy_indicator_restrict(cz, &y, &h);
499    _border_geometry_set(bd, x, y, w, h, POL_HOME_LAYER);
500 }
501
502 static void
503 _policy_zone_layout_fullscreen(E_Border *bd)
504 {
505    if (!_policy_layout_app_check(bd)) return;
506
507    ZONE_GEOMETRY;
508
509    _policy_keyboard_restrict(bd, &h);
510
511    _border_geometry_set(bd, x, y, w, h, POL_FULLSCREEN_LAYER);
512 }
513
514 static void
515 _policy_zone_layout_app_single(E_Border *bd, E_Illume_Config_Zone *cz)
516 {
517    if (!_policy_layout_app_check(bd)) return;
518
519    ZONE_GEOMETRY;
520
521    _policy_keyboard_restrict(bd, &h);
522    _policy_indicator_restrict(cz, &y, &h);
523    _policy_softkey_restrict(cz, &y, &h);
524
525    _border_geometry_set(bd, x, y, w, h, POL_APP_LAYER);
526 }
527
528 static void
529 _policy_zone_layout_app_dual_top(E_Border *bd, E_Illume_Config_Zone *cz)
530 {
531    E_Border *bd2;
532
533    if (!_policy_layout_app_check(bd)) return;
534
535    ZONE_GEOMETRY;
536
537    _policy_keyboard_restrict(bd, &h);
538    _policy_indicator_restrict(cz, &y, &h);
539    _policy_softkey_restrict(cz, &y, &h);
540
541    bd2 = e_illume_border_at_xy_get(bd->zone, x, y);
542    if ((bd2) && (bd2 != bd))
543      {
544         if ((bd->focused) && (bd->client.vkbd.state > ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF))
545           _border_geometry_set(bd2, x, h/2 + y, w, h/2, POL_APP_LAYER);
546         else
547           y += h/2;
548      }
549
550    _border_geometry_set(bd, x, y, w, h/2, POL_APP_LAYER);
551 }
552
553 static void
554 _policy_zone_layout_app_dual_custom(E_Border *bd, E_Illume_Config_Zone *cz)
555 {
556    E_Border *app;
557    int iy, ny, nh;
558
559    if (!_policy_layout_app_check(bd)) return;
560
561    ZONE_GEOMETRY;
562
563    e_illume_border_indicator_pos_get(bd->zone, NULL, &iy);
564
565    ny = bd->zone->y;
566    nh = iy;
567
568    app = e_illume_border_at_xy_get(bd->zone, bd->zone->x, bd->zone->y);
569    if ((app) && (bd != app))
570      {
571         ny = (iy + cz->indicator.size);
572         nh = ((bd->zone->y + bd->zone->h) - ny - cz->softkey.size);
573      }
574
575    _border_geometry_set(bd, x, ny, w, nh, POL_APP_LAYER);
576 }
577
578 static void
579 _policy_zone_layout_app_dual_left(E_Border *bd, E_Illume_Config_Zone *cz, Eina_Bool force)
580 {
581    E_Border *bd2;
582    int ky, kh, nx, nw;
583
584    if (!_policy_layout_app_check(bd)) return;
585
586    ZONE_GEOMETRY;
587
588    e_illume_keyboard_safe_app_region_get(bd->zone, NULL, &ky, NULL, &kh);
589
590    if (kh >= bd->zone->h)
591      kh = (kh - cz->indicator.size - cz->softkey.size);
592    else
593      kh = (kh - cz->indicator.size);
594
595    nx = x;
596    nw = w / 2;
597
598    if (!force)
599      {
600         /* see if there is a border already there. if so, place at right */
601         bd2 = e_illume_border_at_xy_get(bd->zone, nx, y);
602         if ((bd2) && (bd != bd2)) nx = x + nw;
603      }
604
605    _border_geometry_set(bd, nx, y, nw, kh, POL_APP_LAYER);
606 }
607
608 static void
609 _policy_zone_layout_dialog(E_Border *bd, E_Illume_Config_Zone *cz)
610 {
611    E_Border *parent;
612    int mw, mh, nx, ny;
613
614    /* if (!_policy_layout_app_check(bd)) return; */
615    if ((!bd) || (!cz)) return;
616    printf("place dialog %d - %dx%d\n", bd->placed, bd->w, bd->h);
617
618    if (bd->placed)
619      return;
620
621    ZONE_GEOMETRY;
622
623    mw = bd->w;
624    mh = bd->h;
625
626    if (e_illume_border_is_fixed_size(bd))
627      {
628         if (mw > w) mw = w;
629         if (mh > h) mh = h;
630      }
631    else
632      {
633         if (w * 2/3 > bd->w)
634           mw = w * 2/3;
635
636         if (h * 2/3 > bd->h)
637           mh = h * 2/3;
638      }
639
640    parent = e_illume_border_parent_get(bd);
641
642    if ((!parent) || (cz->mode.dual == 1))
643      {
644         nx = (x + ((w - mw) / 2));
645         ny = (y + ((h - mh) / 2));
646      }
647    else
648      {
649         if (mw > parent->w) mw = parent->w;
650         if (mh > parent->h) mh = parent->h;
651
652         nx = (parent->x + ((parent->w - mw) / 2));
653         ny = (parent->y + ((parent->h - mh) / 2));
654      }
655
656    bd->placed = 1;
657    
658    _border_geometry_set(bd, nx, ny, mw, mh, POL_DIALOG_LAYER);
659    printf("set geom %d %d\n", mw, mh);
660 }
661
662 static void
663 _policy_zone_layout_splash(E_Border *bd, E_Illume_Config_Zone *cz)
664 {
665    _policy_zone_layout_dialog(bd, cz);
666
667    if (bd->layer != POL_SPLASH_LAYER) e_border_layer_set(bd, POL_SPLASH_LAYER);
668 }
669
670 static void
671 _policy_zone_layout_conformant_single(E_Border *bd, E_Illume_Config_Zone *cz __UNUSED__)
672 {
673    if (!_policy_layout_app_check(bd)) return;
674
675    _border_geometry_set(bd, bd->zone->x, bd->zone->y,
676                         bd->zone->w, bd->zone->h,
677                         POL_CONFORMANT_LAYER);
678 }
679
680 #if 0
681 typedef struct _App_Desk App_Desk;
682
683 struct _App_Desk
684 {
685   E_Desk *desk;
686   const char *class;
687   Eina_List *borders;
688 };
689
690 static Eina_List *desks = NULL;
691
692 #define EINA_LIST_FIND(_list, _item, _match)    \
693   {                                             \
694      Eina_List *_l;                             \
695      EINA_LIST_FOREACH(_list, _l, _item)        \
696        if (_match) break;                       \
697   }
698 #endif
699
700
701 /* policy functions */
702 void
703 _policy_border_add(E_Border *bd)
704 {
705    //   printf("Border added: %s\n", bd->client.icccm.class);
706
707    if (!bd) return;
708
709    /* NB: this call sets an atom on the window that specifices the zone.
710     * the logic here is that any new windows created can access the zone
711     * window by a 'get' call. This is useful for elementary apps as they
712     * normally would not have access to the zone window. Typical use case
713     * is for indicator & softkey windows so that they can send messages
714     * that apply to their respective zone only. Example: softkey sends close
715     * messages (or back messages to cycle focus) that should pertain just
716     * to it's current zone */
717    ecore_x_e_illume_zone_set(bd->client.win, bd->zone->black_win);
718
719    if (e_illume_border_is_keyboard(bd))
720      {
721         bd->sticky = 1;
722         e_hints_window_sticky_set(bd, 1);
723      }
724    
725    if (e_illume_border_is_home(bd))
726      {
727         bd->sticky = 1;
728         e_hints_window_sticky_set(bd, 1);
729      }
730
731    if (e_illume_border_is_indicator(bd))
732      {
733         bd->sticky = 1;
734         e_hints_window_sticky_set(bd, 1);
735      }
736
737    if (e_illume_border_is_softkey(bd))
738      {
739         bd->sticky = 1;
740         e_hints_window_sticky_set(bd, 1);
741      }
742
743    /* ignore stolen borders. These are typically quickpanel or keyboards */
744    if (bd->stolen) return;
745
746    /* if this is a fullscreen window, than we need to hide indicator window */
747    /* NB: we could use the e_illume_border_is_fullscreen function here
748     * but we save ourselves a function call this way */
749    if ((bd->fullscreen) || (bd->need_fullscreen))
750      {
751         E_Border *ind, *sft;
752
753         if ((ind = e_illume_border_indicator_get(bd->zone)))
754           {
755              if (ind->visible) e_illume_border_hide(ind);
756           }
757         if ((sft = e_illume_border_softkey_get(bd->zone)))
758           {
759              if (e_illume_border_is_conformant(bd))
760                {
761                   if (sft->visible)
762                     e_illume_border_hide(sft);
763                   else if (!sft->visible)
764                     e_illume_border_show(sft);
765                }
766           }
767      }
768
769
770 #if 0
771    if (bd->client.icccm.class)
772      {
773         Eina_List *l;
774         App_Desk *d;
775
776         EINA_LIST_FIND(desks, d, (d->class == bd->client.icccm.class));
777
778         if (!d)
779           {
780              d = E_NEW(App_Desk, 1);
781              d->desk
782           }
783
784         d->borders = eina_list_append(d->borders, bd);
785         e_border_desk_set(bd, d->desk);
786      }
787 #endif
788
789    /* Add this border to our focus stack if it can accept or take focus */
790    if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
791      _pol_focus_stack = eina_list_append(_pol_focus_stack, bd);
792
793    if ((e_illume_border_is_softkey(bd)) || (e_illume_border_is_indicator(bd)))
794      _policy_zone_layout_update(bd->zone);
795    else
796      {
797         /* set focus on new border if we can */
798         _policy_border_set_focus(bd);
799      }
800 }
801
802 void
803 _policy_border_del(E_Border *bd)
804 {
805    //   printf("Policy Border deleted: %s\n", bd->client.icccm.class);
806
807    if (!bd) return;
808
809    /* if this is a fullscreen window, than we need to show indicator window */
810    /* NB: we could use the e_illume_border_is_fullscreen function here
811     * but we save ourselves a function call this way */
812    if ((bd->fullscreen) || (bd->need_fullscreen))
813      {
814         E_Border *ind;
815
816         /* try to get the Indicator on this zone */
817         if ((ind = e_illume_border_indicator_get(bd->zone)))
818           {
819              if (!ind->visible) e_illume_border_show(ind);
820           }
821         _policy_zone_layout_update(bd->zone);
822      }
823
824    /* remove from focus stack */
825    if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
826      _pol_focus_stack = eina_list_remove(_pol_focus_stack, bd);
827
828    if (e_illume_border_is_softkey(bd))
829      {
830         E_Illume_Config_Zone *cz;
831
832         cz = e_illume_zone_config_get(bd->zone->id);
833         cz->softkey.size = 0;
834         _policy_zone_layout_update(bd->zone);
835      }
836    else if (e_illume_border_is_indicator(bd))
837      {
838         E_Illume_Config_Zone *cz;
839
840         cz = e_illume_zone_config_get(bd->zone->id);
841         cz->indicator.size = 0;
842         _policy_zone_layout_update(bd->zone);
843      }
844    /* else
845     *   {
846     *   _policy_border_show_below(bd);
847     *   } */
848 }
849
850 void
851 _policy_border_focus_in(E_Border *bd __UNUSED__)
852 {
853    E_Border *ind;
854
855    //   printf("Border focus in: %s\n", bd->client.icccm.name);
856    if ((bd->fullscreen) || (bd->need_fullscreen))
857      {
858         /* try to get the Indicator on this zone */
859         if ((ind = e_illume_border_indicator_get(bd->zone)))
860           {
861              /* we have the indicator, show it if needed */
862              if (ind->visible) e_illume_border_hide(ind);
863           }
864      }
865    else
866      {
867         /* try to get the Indicator on this zone */
868         if ((ind = e_illume_border_indicator_get(bd->zone)))
869           {
870              /* we have the indicator, show it if needed */
871              if (!ind->visible) e_illume_border_show(ind);
872           }
873      }
874    _policy_zone_layout_update(bd->zone);
875 }
876
877 void
878 _policy_border_focus_out(E_Border *bd)
879 {
880    //   printf("Border focus out: %s\n", bd->client.icccm.name);
881
882    if (!bd) return;
883
884    /* NB: if we got this focus_out event on a deleted border, we check if
885     * it is a transient (child) of another window. If it is, then we
886     * transfer focus back to the parent window */
887    if (e_object_is_del(E_OBJECT(bd)))
888      {
889         if (e_illume_border_is_dialog(bd))
890           {
891              E_Border *parent;
892
893              if ((parent = e_illume_border_parent_get(bd)))
894                _policy_border_set_focus(parent);
895           }
896      }
897 }
898
899 void
900 _policy_border_activate(E_Border *bd)
901 {
902    E_Border *sft;
903
904    //   printf("Border Activate: %s\n", bd->client.icccm.name);
905
906    if (!bd) return;
907
908    /* NB: stolen borders may or may not need focus call...have to test */
909    if (bd->stolen) return;
910
911    /* conformant windows hide the softkey */
912    if ((sft = e_illume_border_softkey_get(bd->zone)))
913      {
914         if (e_illume_border_is_conformant(bd))
915           {
916              if (sft->visible) e_illume_border_hide(sft);
917           }
918         else
919           {
920              if (!sft->visible) e_illume_border_show(sft);
921           }
922      }
923
924    /* NB: We cannot use our set_focus function here because it does,
925     * occasionally fall through wrt E's focus policy, so cherry pick the good
926     * parts and use here :) */
927    if (bd->desk != e_desk_current_get(bd->zone))
928      e_desk_show(bd->desk);
929
930    /* if the border is iconified then uniconify if allowed */
931    if ((bd->iconic) && (!bd->lock_user_iconify))
932      e_border_uniconify(bd);
933
934    /* set very high layer for this window as it needs attention and thus
935     * should show above everything */
936    e_border_layer_set(bd, POL_ACTIVATE_LAYER);
937
938    /* if we can raise the border do it */
939    if (!bd->lock_user_stacking) e_border_raise(bd);
940
941    /* focus the border */
942    e_border_focus_set(bd, 1, 1);
943
944    /* NB: since we skip needless border evals when container layout
945     * is called (to save cpu cycles), we need to
946     * signal this border that it's focused so that the edj gets
947     * updated.
948     *
949     * This is potentially useless as THIS policy
950     * makes all windows borderless anyway, but it's in here for
951     * completeness
952     e_border_focus_latest_set(bd);
953     if (bd->bg_object)
954     edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
955     if (bd->icon_object)
956     edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
957     e_focus_event_focus_in(bd);
958    */
959 }
960 static Eina_Bool
961 _policy_border_is_dialog(E_Border *bd)
962 {
963    if (e_illume_border_is_dialog(bd))
964      return EINA_TRUE;
965
966    if (bd->client.e.state.centered)
967      return EINA_TRUE;
968
969    if (bd->internal)
970      {
971         if (bd->client.icccm.class)
972           {
973              if (!strncmp(bd->client.icccm.class, "Illume", 6))
974                return EINA_FALSE;
975              if (!strncmp(bd->client.icccm.class, "e_fwin", 6))
976                return EINA_FALSE;
977              if (!strncmp(bd->client.icccm.class, "every", 5))
978                return EINA_FALSE;
979
980           }
981         return EINA_TRUE;
982      }
983
984    return EINA_FALSE;
985 }
986
987 void
988 _policy_border_post_fetch(E_Border *bd)
989 {
990    if (!bd) return;
991
992    /* NB: for this policy we disable all remembers set on a border */
993    if (bd->remember) e_remember_del(bd->remember);
994    bd->remember = NULL;
995
996    if (_policy_border_is_dialog(bd))
997      {
998         return;
999      }
1000    else if (e_illume_border_is_fixed_size(bd))
1001      {
1002         return;
1003      }
1004    else if (!bd->borderless)
1005      {
1006         bd->borderless = 1;
1007         bd->client.border.changed = 1;
1008      }
1009 }
1010
1011 void
1012 _policy_border_post_assign(E_Border *bd)
1013 {
1014    if (!bd) return;
1015
1016    bd->internal_no_remember = 1;
1017
1018    if (_policy_border_is_dialog(bd) ||
1019        e_illume_border_is_fixed_size(bd))
1020      return;
1021
1022    /* do not allow client to change these properties */
1023    bd->lock_client_size = 1;
1024    bd->lock_client_shade = 1;
1025    bd->lock_client_maximize = 1;
1026    bd->lock_client_location = 1;
1027    bd->lock_client_stacking = 1;
1028
1029    /* do not allow the user to change these properties */
1030    /* bd->lock_user_location = 1;
1031     * bd->lock_user_size = 1;
1032     * bd->lock_user_shade = 1; */
1033
1034    /* clear any centered states */
1035    /* NB: this is mainly needed for E's main config dialog */
1036    bd->client.e.state.centered = 0;
1037
1038    /* lock the border type so user/client cannot change */
1039    bd->lock_border = 1;
1040
1041    /* disable e's placement (and honoring of icccm.request_pos) */
1042    bd->placed = 1;
1043 }
1044
1045 void
1046 _policy_border_show(E_Border *bd)
1047 {
1048    if (!bd) return;
1049
1050    /* printf("_policy_border_show %s\n", e_border_name_get(bd)); */
1051
1052    if (!bd->client.icccm.name) return;
1053
1054    //   printf("Border Show: %s\n", bd->client.icccm.class);
1055
1056    /* trap for special windows so we can ignore hides below them */
1057    if (e_illume_border_is_indicator(bd)) return;
1058    if (e_illume_border_is_softkey(bd)) return;
1059    if (e_illume_border_is_quickpanel(bd)) return;
1060    if (e_illume_border_is_keyboard(bd)) return;
1061
1062    _policy_border_hide_below(bd);
1063 }
1064
1065 /* called on E_BORDER_HOOK_CONTAINER_LAYOUT (after e_border/eval0) */
1066 void
1067 _policy_zone_layout(E_Zone *zone)
1068 {
1069    E_Illume_Config_Zone *cz;
1070    Eina_List *l;
1071    E_Border *bd;
1072
1073    if (!zone) return;
1074
1075    cz = e_illume_zone_config_get(zone->id);
1076
1077    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
1078      {
1079         if (e_object_is_del(E_OBJECT(bd))) continue;
1080
1081         if (bd->zone != zone) continue;
1082
1083         if ((!bd->new_client) && (!bd->changes.pos) && (!bd->changes.size) &&
1084             (!bd->changes.visible) && (!bd->pending_move_resize) &&
1085             (!bd->need_shape_export) && (!bd->need_shape_merge)) continue;
1086
1087         if (e_illume_border_is_indicator(bd))
1088           _policy_zone_layout_indicator(bd, cz);
1089
1090         else if (e_illume_border_is_quickpanel(bd))
1091           _policy_zone_layout_quickpanel(bd);
1092
1093         else if (e_illume_border_is_softkey(bd))
1094           _policy_zone_layout_softkey(bd, cz);
1095
1096         else if (e_illume_border_is_keyboard(bd))
1097           _policy_zone_layout_keyboard(bd, cz);
1098
1099         else if (e_illume_border_is_home(bd))
1100           _policy_zone_layout_home_single(bd, cz);
1101
1102         else if ((bd->fullscreen) || (bd->need_fullscreen))
1103           _policy_zone_layout_fullscreen(bd);
1104
1105         else if (e_illume_border_is_splash(bd))
1106           _policy_zone_layout_splash(bd, cz);
1107
1108         else if (_policy_border_is_dialog(bd))
1109           _policy_zone_layout_dialog(bd, cz);
1110
1111         else if (e_illume_border_is_conformant(bd))
1112           _policy_zone_layout_conformant_single(bd, cz);
1113
1114         else if (e_illume_border_is_fixed_size(bd))
1115           _policy_zone_layout_dialog(bd, cz);
1116
1117         else if (bd->internal && bd->client.icccm.class &&
1118                  (!strcmp(bd->client.icccm.class, "everything-window")))
1119           {
1120              if (bd->client.vkbd.state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
1121                _policy_zone_layout_app_single(bd, cz);
1122              /* else
1123               *   _policy_zone_layout_app_dual_left(bd, cz, EINA_TRUE); */
1124              if (bd->layer != POL_ACTIVATE_LAYER)
1125                e_border_layer_set(bd, POL_ACTIVATE_LAYER);
1126              
1127              /* if (bd->layer != POL_SPLASH_LAYER)
1128               *   e_border_layer_set(bd, POL_SPLASH_LAYER); */
1129           }
1130         else if (bd->client.e.state.centered)
1131           _policy_zone_layout_dialog(bd, cz);
1132         else if (!cz->mode.dual)
1133           _policy_zone_layout_app_single(bd, cz);
1134         else
1135           {
1136              if (cz->mode.side == 0)
1137                {
1138                   int ty;
1139
1140                   /* grab the indicator position so we can tell if it
1141                    * is in a custom position or not (user dragged it) */
1142                   e_illume_border_indicator_pos_get(bd->zone, NULL, &ty);
1143                   if (ty <= bd->zone->y)
1144                     _policy_zone_layout_app_dual_top(bd, cz);
1145                   else
1146                     _policy_zone_layout_app_dual_custom(bd, cz);
1147                }
1148              else
1149                _policy_zone_layout_app_dual_left(bd, cz, EINA_FALSE);
1150           }
1151      }
1152 }
1153
1154 void
1155 _policy_zone_move_resize(E_Zone *zone)
1156 {
1157    Eina_List *l;
1158    E_Border *bd;
1159
1160    if (!zone) return;
1161
1162    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
1163      {
1164         if (bd->zone != zone) continue;
1165
1166         bd->changes.pos = 1;
1167         bd->changed = 1;
1168      }
1169 }
1170
1171 void
1172 _policy_zone_mode_change(E_Zone *zone, Ecore_X_Atom mode)
1173 {
1174    E_Illume_Config_Zone *cz;
1175    /* Eina_List *homes = NULL; */
1176    E_Border *bd;
1177    /* int count; */
1178
1179    if (!zone) return;
1180
1181    cz = e_illume_zone_config_get(zone->id);
1182
1183    if (mode == ECORE_X_ATOM_E_ILLUME_MODE_SINGLE)
1184      cz->mode.dual = 0;
1185    else
1186      {
1187         cz->mode.dual = 1;
1188         if (mode == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP)
1189           cz->mode.side = 0;
1190         else if (mode == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT)
1191           cz->mode.side = 1;
1192      }
1193    e_config_save_queue();
1194
1195    /* lock indicator window from dragging if we need to */
1196    bd = e_illume_border_indicator_get(zone);
1197    if (bd)
1198      {
1199         /* only dual-top mode can drag */
1200         if ((cz->mode.dual == 1) && (cz->mode.side == 0))
1201           {
1202              /* only set locked if we need to */
1203              if (bd->client.illume.drag.locked != 0)
1204                ecore_x_e_illume_drag_locked_set(bd->client.win, 0);
1205           }
1206         else
1207           {
1208              /* only set locked if we need to */
1209              if (bd->client.illume.drag.locked != 1)
1210                ecore_x_e_illume_drag_locked_set(bd->client.win, 1);
1211           }
1212      }
1213 #if 0 /* split home window? wtf?! go home! */
1214    if (!(homes = e_illume_border_home_borders_get(zone))) return;
1215
1216    count = eina_list_count(homes);
1217
1218    /* create a new home window (if needed) for dual mode */
1219    if (cz->mode.dual == 1)
1220      {
1221         if (count < 2)
1222           ecore_x_e_illume_home_new_send(zone->black_win);
1223      }
1224    else if (cz->mode.dual == 0)
1225      {
1226         /* if we went to single mode, delete any extra home windows */
1227         if (count >= 2)
1228           {
1229              E_Border *home;
1230
1231              /* try to get a home window on this zone and remove it */
1232              if ((home = e_illume_border_home_get(zone)))
1233                ecore_x_e_illume_home_del_send(home->client.win);
1234           }
1235      }
1236 #endif
1237
1238    _policy_zone_layout_update(zone);
1239 }
1240
1241 void
1242 _policy_zone_close(E_Zone *zone)
1243 {
1244    E_Border *bd;
1245
1246    if (!zone) return;
1247
1248    if (!(bd = e_border_focused_get())) return;
1249
1250    if (bd->zone != zone) return;
1251
1252    /* close this border */
1253    e_border_act_close_begin(bd);
1254 }
1255
1256 void
1257 _policy_drag_start(E_Border *bd)
1258 {
1259    if (!bd) return;
1260
1261    if (bd->stolen) return;
1262
1263    ecore_x_e_illume_drag_set(bd->client.win, 1);
1264    ecore_x_e_illume_drag_set(bd->zone->black_win, 1);
1265 }
1266
1267 void
1268 _policy_drag_end(E_Border *bd)
1269 {
1270    //   printf("Drag end\n");
1271
1272    if (!bd) return;
1273
1274    if (bd->stolen) return;
1275
1276    /* set property on this border to say we are done dragging */
1277    ecore_x_e_illume_drag_set(bd->client.win, 0);
1278
1279    /* set property on zone window that a drag is finished */
1280    ecore_x_e_illume_drag_set(bd->zone->black_win, 0);
1281 }
1282
1283 void
1284 _policy_focus_back(E_Zone *zone)
1285 {
1286    Eina_List *l, *fl = NULL;
1287    E_Border *bd, *fbd;
1288
1289    if (!zone) return;
1290    if (eina_list_count(_pol_focus_stack) < 1) return;
1291
1292    //   printf("Focus back\n");
1293
1294    EINA_LIST_REVERSE_FOREACH(_pol_focus_stack, l, bd)
1295      {
1296         if (bd->zone != zone) continue;
1297         fl = eina_list_append(fl, bd);
1298      }
1299
1300    if (!(fbd = e_border_focused_get())) return;
1301    if (fbd->parent) return;
1302
1303    EINA_LIST_REVERSE_FOREACH(fl, l, bd)
1304      {
1305         if ((fbd) && (bd == fbd))
1306           {
1307              E_Border *b;
1308
1309              if ((l->next) && (b = l->next->data))
1310                {
1311                   _policy_border_set_focus(b);
1312                   break;
1313                }
1314              else
1315                {
1316                   /* we've reached the end of the list. Set focus to first */
1317                   if ((b = eina_list_nth(fl, 0)))
1318                     {
1319                        _policy_border_set_focus(b);
1320                        break;
1321                     }
1322                }
1323           }
1324      }
1325    eina_list_free(fl);
1326 }
1327
1328 void
1329 _policy_focus_forward(E_Zone *zone)
1330 {
1331    Eina_List *l, *fl = NULL;
1332    E_Border *bd, *fbd;
1333
1334    if (!zone) return;
1335    if (eina_list_count(_pol_focus_stack) < 1) return;
1336
1337    //   printf("Focus forward\n");
1338
1339    EINA_LIST_FOREACH(_pol_focus_stack, l, bd)
1340      {
1341         if (bd->zone != zone) continue;
1342         fl = eina_list_append(fl, bd);
1343      }
1344
1345    if (!(fbd = e_border_focused_get())) return;
1346    if (fbd->parent) return;
1347
1348    EINA_LIST_FOREACH(fl, l, bd)
1349      {
1350         if ((fbd) && (bd == fbd))
1351           {
1352              E_Border *b;
1353
1354              if ((l->next) && (b = l->next->data))
1355                {
1356                   _policy_border_set_focus(b);
1357                   break;
1358                }
1359              else
1360                {
1361                   /* we've reached the end of the list. Set focus to first */
1362                   if ((b = eina_list_nth(fl, 0)))
1363                     {
1364                        _policy_border_set_focus(b);
1365                        break;
1366                     }
1367                }
1368           }
1369      }
1370    eina_list_free(fl);
1371 }
1372
1373 void
1374 _policy_focus_home(E_Zone *zone)
1375 {
1376    E_Border *bd;
1377
1378    if (!zone) return;
1379    if (!(bd = e_illume_border_home_get(zone))) return;
1380    _policy_border_set_focus(bd);
1381 }
1382
1383 void
1384 _policy_property_change(Ecore_X_Event_Window_Property *event)
1385 {
1386    if (event->atom == ECORE_X_ATOM_NET_WM_STATE)
1387      {
1388         E_Border *bd, *ind;
1389
1390         if (!(bd = e_border_find_by_client_window(event->win))) return;
1391
1392         /* not interested in stolen or invisible borders */
1393         if ((bd->stolen) || (!bd->visible)) return;
1394
1395         /* make sure the border has a name or class */
1396         /* NB: this check is here because some E borders get State Changes
1397          * but do not have a name/class associated with them. Not entirely sure
1398          * which ones they are, but I would guess Managers, Containers, or Zones.
1399          * At any rate, we're not interested in those types of borders */
1400         if ((!bd->client.icccm.name) || (!bd->client.icccm.class)) return;
1401
1402         /* NB: If we have reached this point, then it should be a fullscreen
1403          * border that has toggled fullscreen on/off */
1404
1405         /* try to get the Indicator on this zone */
1406         if (!(ind = e_illume_border_indicator_get(bd->zone))) return;
1407
1408         /* if we are fullscreen, hide the indicator...else we show it */
1409         /* NB: we could use the e_illume_border_is_fullscreen function here
1410          * but we save ourselves a function call this way */
1411         if ((bd->fullscreen) || (bd->need_fullscreen))
1412           {
1413              if (ind->visible)
1414                {
1415                   e_illume_border_hide(ind);
1416                   _policy_zone_layout_update(bd->zone);
1417                }
1418           }
1419         else
1420           {
1421              if (!ind->visible)
1422                {
1423                   e_illume_border_show(ind);
1424                   _policy_zone_layout_update(bd->zone);
1425                }
1426           }
1427      }
1428    else if (event->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
1429      {
1430         Eina_List *l;
1431         E_Zone *zone;
1432         E_Border *bd;
1433         int x, y, w, h;
1434
1435         if (!(zone = e_util_zone_window_find(event->win))) return;
1436
1437         if (!(bd = e_illume_border_indicator_get(zone))) return;
1438         x = bd->x;
1439         y = bd->y;
1440         w = bd->w;
1441         h = bd->h;
1442
1443         EINA_LIST_FOREACH(e_border_client_list(), l, bd)
1444           {
1445              if (bd->zone != zone) continue;
1446              if (!e_illume_border_is_conformant(bd)) continue;
1447              /* set indicator geometry on conformant window */
1448              /* NB: This is needed so that conformant apps get told about
1449               * the indicator size/position...else they have no way of
1450               * knowing that the geometry has been updated */
1451              ecore_x_e_illume_indicator_geometry_set(bd->client.win, x, y, w, h);
1452           }
1453      }
1454    else if (event->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
1455      {
1456         Eina_List *l;
1457         E_Zone *zone;
1458         E_Border *bd;
1459         int x, y, w, h;
1460
1461         if (!(zone = e_util_zone_window_find(event->win))) return;
1462
1463         if (!(bd = e_illume_border_softkey_get(zone))) return;
1464         x = bd->x;
1465         y = bd->y;
1466         w = bd->w;
1467         h = bd->h;
1468
1469         EINA_LIST_FOREACH(e_border_client_list(), l, bd)
1470           {
1471              if (bd->zone != zone) continue;
1472              if (!e_illume_border_is_conformant(bd)) continue;
1473              /* set softkey geometry on conformant window */
1474              /* NB: This is needed so that conformant apps get told about
1475               * the softkey size/position...else they have no way of
1476               * knowing that the geometry has been updated */
1477              ecore_x_e_illume_softkey_geometry_set(bd->client.win, x, y, w, h);
1478           }
1479      }
1480    else if (event->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
1481      {
1482         Eina_List *l;
1483         E_Zone *zone;
1484         E_Illume_Keyboard *kbd;
1485         E_Border *bd;
1486         int x, y, w, h;
1487
1488         if (!(zone = e_util_zone_window_find(event->win))) return;
1489
1490         if (!(kbd = e_illume_keyboard_get())) return;
1491         if (!kbd->border) return;
1492
1493         x = kbd->border->x;
1494         w = kbd->border->w;
1495         h = kbd->border->h;
1496
1497         /* adjust Y for keyboard visibility because keyboard uses fx_offset */
1498         y = 0;
1499         if (kbd->border->fx.y <= 0) y = kbd->border->y;
1500
1501         /* look for conformant borders */
1502         EINA_LIST_FOREACH(e_border_client_list(), l, bd)
1503           {
1504              if (bd->zone != zone) continue;
1505              if (!e_illume_border_is_conformant(bd)) continue;
1506              /* set keyboard geometry on conformant window */
1507              /* NB: This is needed so that conformant apps get told about
1508               * the keyboard size/position...else they have no way of
1509               * knowing that the geometry has been updated */
1510              ecore_x_e_illume_keyboard_geometry_set(bd->client.win, x, y, w, h);
1511           }
1512      }
1513    else if (event->atom == ATM_ENLIGHTENMENT_SCALE)
1514      {
1515         Eina_List *ml;
1516         E_Manager *man;
1517
1518         EINA_LIST_FOREACH(e_manager_list(), ml, man)
1519           {
1520              Eina_List *cl;
1521              E_Container *con;
1522
1523              if (event->win != man->root) continue;
1524              EINA_LIST_FOREACH(man->containers, cl, con)
1525                {
1526                   Eina_List *zl;
1527                   E_Zone *zone;
1528
1529                   EINA_LIST_FOREACH(con->zones, zl, zone)
1530                     _policy_zone_layout_update(zone);
1531                }
1532           }
1533      }
1534 }