update for beta release
[framework/uifw/e17.git] / src / modules / illume2 / e_illume.c
1 #include "e_illume_private.h"
2 #include "e_mod_config.h"
3
4 /**
5  * @defgroup E_Illume_Main_Group Illume API Information
6  * 
7  * The following group defines variables, structures, and functions available 
8  * to a policy.
9  */
10
11 /**
12  * Returns the @ref E_Illume_Config_Zone structure for a specific zone.
13  * 
14  * @param id The id of the E_Zone.
15  * @return The @ref E_Illume_Config_Zone structure for this zone.
16  * 
17  * @note This function will return a new @ref E_Illume_Config_Zone structure 
18  * if none exists. This new @ref E_Illume_Config_Zone will be added to the 
19  * existing list of @ref E_Illume_Config_Zone structures automatically.
20  * 
21  * @ingroup E_Illume_Config_Group
22  */
23 EAPI E_Illume_Config_Zone *
24 e_illume_zone_config_get(int id) 
25 {
26    Eina_List *l;
27    E_Illume_Config_Zone *cz = NULL;
28
29    /* loop existing zone configs and look for this id */
30    EINA_LIST_FOREACH(_e_illume_cfg->policy.zones, l, cz) 
31      {
32         if (cz->id != id) continue;
33         return cz;
34      }
35
36    /* we did not find an existing one for this zone, so create a new one */
37    cz = E_NEW(E_Illume_Config_Zone, 1);
38    cz->id = id;
39    cz->mode.dual = 0;
40    cz->mode.side = 0;
41
42    /* add it to the list */
43    _e_illume_cfg->policy.zones = 
44      eina_list_append(_e_illume_cfg->policy.zones, cz);
45
46    /* save it in config */
47    e_mod_illume_config_save();
48
49    /* return a fallback */
50    return cz;
51 }
52
53 /**
54  * Determine if a given border is an Indicator window.
55  * 
56  * @param bd The border to test.
57  * @return EINA_TRUE if it is an Indicator window, EINA_FALSE otherwise.
58  * 
59  * @note If @p bd is NULL then this function will return EINA_FALSE.
60  * 
61  * @note It is assumed that Indicator windows are of type 
62  * ECORE_X_WINDOW_TYPE_DOCK.
63  * 
64  * @ingroup E_Illume_Main_Group
65  */
66 EAPI Eina_Bool 
67 e_illume_border_is_indicator(E_Border *bd) 
68 {
69    /* make sure we have a border */
70    if (!bd) return EINA_FALSE;
71
72    /* indicator windows should be set to dock type, so check for that */
73    if (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) return EINA_FALSE;
74
75    /* we have a dock window, check against any matches in config */
76
77    /* check if we are matching on name */
78    if (_e_illume_cfg->policy.indicator.match.name) 
79      {
80         if ((bd->client.icccm.name) && 
81             (!strcmp(bd->client.icccm.name, 
82                      _e_illume_cfg->policy.indicator.name)))
83           return EINA_TRUE;
84      }
85
86    /* check if we are matching on class */
87    if (_e_illume_cfg->policy.indicator.match.class) 
88      {
89         if ((bd->client.icccm.class) && 
90             (!strcmp(bd->client.icccm.class, 
91                      _e_illume_cfg->policy.indicator.class)))
92           return EINA_TRUE;
93      }
94
95    /* check if we are matching on title */
96    if (_e_illume_cfg->policy.indicator.match.title) 
97      {
98         const char *title;
99
100         if ((title = e_border_name_get(bd)))
101           if (!strcmp(title, _e_illume_cfg->policy.indicator.title))
102             return EINA_TRUE;
103      }
104
105    /* return a fallback */
106    return EINA_FALSE;
107 }
108
109 /**
110  * Determine if a given border is a Softkey window.
111  * 
112  * @param bd The border to test.
113  * @return EINA_TRUE if it is a Softkey window, EINA_FALSE otherwise.
114  * 
115  * @note If @p bd is NULL then this function will return EINA_FALSE.
116  * 
117  * @note It is assumed that Softkey windows are of type 
118  * ECORE_X_WINDOW_TYPE_DOCK.
119  * 
120  * @ingroup E_Illume_Main_Group
121  */
122 EAPI Eina_Bool 
123 e_illume_border_is_softkey(E_Border *bd) 
124 {
125    /* make sure we have a border */
126    if (!bd) return EINA_FALSE;
127
128    /* legacy code from illume 1 */
129    if (bd->client.qtopia.soft_menu) return EINA_TRUE;
130
131    /* softkey windows should be set to dock type, so check for that */
132    if (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) return EINA_FALSE;
133
134    /* we have a softkey window, check against any matches in config */
135
136    /* check if we are matching on name */
137    if (_e_illume_cfg->policy.softkey.match.name) 
138      {
139         if ((bd->client.icccm.name) && 
140             (!strcmp(bd->client.icccm.name, 
141                      _e_illume_cfg->policy.softkey.name)))
142           return EINA_TRUE;
143      }
144
145    /* check if we are matching on class */
146    if (_e_illume_cfg->policy.softkey.match.class) 
147      {
148         if ((bd->client.icccm.class) && 
149             (!strcmp(bd->client.icccm.class, 
150                      _e_illume_cfg->policy.softkey.class)))
151           return EINA_TRUE;
152      }
153
154    /* check if we are matching on title */
155    if (_e_illume_cfg->policy.softkey.match.title) 
156      {
157         const char *title;
158
159         if ((title = e_border_name_get(bd)))
160           if (!strcmp(title, _e_illume_cfg->policy.softkey.title))
161             return EINA_TRUE;
162      }
163
164    /* return a fallback */
165    return EINA_FALSE;
166 }
167
168 /**
169  * Determine if a given border is a Keyboard window.
170  * 
171  * @param bd The border to test.
172  * @return EINA_TRUE if it is a Keyboard window, EINA_FALSE otherwise.
173  * 
174  * @note If @p bd is NULL then this function will return EINA_FALSE.
175  * 
176  * @ingroup E_Illume_Main_Group
177  */
178 EAPI Eina_Bool 
179 e_illume_border_is_keyboard(E_Border *bd) 
180 {
181    /* make sure we have a border */
182    if (!bd) return EINA_FALSE;
183
184    /* check for specific flag first */
185    if (bd->client.vkbd.vkbd) return EINA_TRUE;
186
187    /* legacy code from illume 1 */
188    if ((bd->client.icccm.name) && 
189        ((!strcmp(bd->client.icccm.name, "multitap-pad"))) && 
190        (bd->client.netwm.state.skip_taskbar) && 
191        (bd->client.netwm.state.skip_pager))
192      return EINA_TRUE;
193
194    /* check if we are matching on name */
195    if (_e_illume_cfg->policy.vkbd.match.name) 
196      {
197         if ((bd->client.icccm.name) && 
198             (!strcmp(bd->client.icccm.name, 
199                      _e_illume_cfg->policy.vkbd.name)))
200           return EINA_TRUE;
201      }
202
203    /* check if we are matching on class */
204    if (_e_illume_cfg->policy.vkbd.match.class) 
205      {
206         if ((bd->client.icccm.class) && 
207             (!strcmp(bd->client.icccm.class, 
208                      _e_illume_cfg->policy.vkbd.class)))
209           return EINA_TRUE;
210      }
211
212    /* check if we are matching on title */
213    if (_e_illume_cfg->policy.vkbd.match.title) 
214      {
215         const char *title;
216
217         if ((title = e_border_name_get(bd)))
218           if (!strcmp(title, _e_illume_cfg->policy.vkbd.title))
219             return EINA_TRUE;
220      }
221
222    /* return a fallback */
223    return EINA_FALSE;
224 }
225
226 /**
227  * Determine if a given border is a Home window.
228  * 
229  * @param bd The border to test.
230  * @return EINA_TRUE if it is a Home window, EINA_FALSE otherwise.
231  * 
232  * @note If @p bd is NULL then this function will return EINA_FALSE.
233  * 
234  * @ingroup E_Illume_Main_Group
235  */
236 EAPI Eina_Bool 
237 e_illume_border_is_home(E_Border *bd) 
238 {
239    /* make sure we have a border */
240    if (!bd) return EINA_FALSE;
241
242    /* skip windows which are not either 'normal' windows, or 'unknown' windows
243     * NB: Let 'unknown' windows pass through as a safety */
244    if ((bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL) && 
245        (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_UNKNOWN))
246      return EINA_FALSE;
247
248    /* check if we are matching on name */
249    if (_e_illume_cfg->policy.home.match.name) 
250      {
251         if ((bd->client.icccm.name) && 
252             (!strcmp(bd->client.icccm.name, 
253                      _e_illume_cfg->policy.home.name)))
254           return EINA_TRUE;
255      }
256
257    /* check if we are matching on class */
258    if (_e_illume_cfg->policy.home.match.class) 
259      {
260         if ((bd->client.icccm.class) && 
261             (!strcmp(bd->client.icccm.class, 
262                      _e_illume_cfg->policy.home.class)))
263           return EINA_TRUE;
264      }
265
266    /* check if we are matching on title */
267    if (_e_illume_cfg->policy.home.match.title) 
268      {
269         const char *title;
270
271         if ((title = e_border_name_get(bd)))
272           if (!strcmp(title, _e_illume_cfg->policy.home.title))
273             return EINA_TRUE;
274      }
275
276    /* return a fallback */
277    return EINA_FALSE;
278 }
279
280 /**
281  * Determine if a given border is a splash screen.
282  * 
283  * @param bd The border to test.
284  * @return EINA_TRUE if it is a splash screen, EINA_FALSE otherwise.
285  * 
286  * @note If @p bd is NULL then this function will return EINA_FALSE.
287  * 
288  * @ingroup E_Illume_Main_Group
289  */
290 EAPI Eina_Bool 
291 e_illume_border_is_splash(E_Border *bd) 
292 {
293    /* make sure we have a border */
294    if (!bd) return EINA_FALSE;
295
296    /* check actual type */
297    if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_SPLASH) return EINA_TRUE;
298
299    /* check for transient flag */
300 //   if (bd->client.icccm.transient_for != 0) return EINA_TRUE;
301
302    /* NB: may or may not need to handle these. Needs Testing
303    if (bd->client.netwm.extra_types) 
304      printf("\t\tBorder has extra types: %s\n", bd->client.icccm.class);
305    */
306
307    /* return a fallback */
308    return EINA_FALSE;
309 }
310
311 /**
312  * Determine if a given border is a dialog.
313  * 
314  * @param bd The border to test.
315  * @return EINA_TRUE if it is a dialog, EINA_FALSE otherwise.
316  * 
317  * @note If @p bd is NULL then this function will return EINA_FALSE.
318  * 
319  * @ingroup E_Illume_Main_Group
320  */
321 EAPI Eina_Bool 
322 e_illume_border_is_dialog(E_Border *bd) 
323 {
324    /* make sure we have a border */
325    if (!bd) return EINA_FALSE;
326
327    /* check actual type */
328    if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG) return EINA_TRUE;
329
330    /* check for transient flag */
331    if (bd->client.icccm.transient_for != 0) return EINA_TRUE;
332
333    /* check for client leader */
334    /* NB: disabled currently as some GTK windows set this even tho they are 
335     * not a dialog. */
336 //   if (bd->client.icccm.client_leader) return EINA_TRUE;
337
338    /* NB: may or may not need to handle these. Needs Testing
339    if (bd->client.netwm.extra_types) 
340      printf("\t\tBorder has extra types: %s\n", bd->client.icccm.class);
341    */
342
343    /* return a fallback */
344    return EINA_FALSE;
345 }
346
347 /**
348  * Determine if a given border is a QT VCLSalFrame.
349  * 
350  * @param bd The border to test.
351  * @return EINA_TRUE if it is a VCLSalFrame, EINA_FALSE otherwise.
352  * 
353  * @note If @p bd is NULL then this function will return EINA_FALSE.
354  * 
355  * @ingroup E_Illume_Main_Group
356  */
357 EAPI Eina_Bool 
358 e_illume_border_is_qt_frame(E_Border *bd) 
359 {
360    /* make sure we have a border */
361    if (!bd) return EINA_FALSE;
362
363    /* make sure we have the icccm name and compare it */
364    if ((bd->client.icccm.name) && 
365        (!strncmp(bd->client.icccm.name, "VCLSalFrame", 11)))
366      return EINA_TRUE;
367
368    /* return a fallback */
369    return EINA_FALSE;
370 }
371
372 /**
373  * Determine if a given border is a fullscreen window.
374  * 
375  * @param bd The border to test.
376  * @return EINA_TRUE if it is fullscreen, EINA_FALSE otherwise.
377  * 
378  * @note If @p bd is NULL then this function will return EINA_FALSE.
379  * 
380  * @ingroup E_Illume_Main_Group
381  */
382 EAPI Eina_Bool 
383 e_illume_border_is_fullscreen(E_Border *bd) 
384 {
385    /* make sure we have a border */
386    if (!bd) return EINA_FALSE;
387
388    /* check for fullscreen */
389    if ((bd->fullscreen) || (bd->need_fullscreen)) return EINA_TRUE;
390
391    /* return a fallback */
392    return EINA_FALSE;
393 }
394
395 /**
396  * Determine if a given border is an illume conformant window.
397  * 
398  * @param bd The border to test.
399  * @return EINA_TRUE if it is conformant, EINA_FALSE otherwise.
400  * 
401  * @note If @p bd is NULL then this function will return EINA_FALSE.
402  * 
403  * @ingroup E_Illume_Main_Group
404  */
405 EAPI Eina_Bool 
406 e_illume_border_is_conformant(E_Border *bd) 
407 {
408    /* make sure we have a border */
409    if (!bd) return EINA_FALSE;
410
411    /* return if it is conformant or not */
412    return bd->client.illume.conformant.conformant;
413 }
414
415 /**
416  * Determine if a given border is a quickpanel window.
417  * 
418  * @param bd The border to test.
419  * @return EINA_TRUE if it is a quickpanel, EINA_FALSE otherwise.
420  * 
421  * @note If @p bd is NULL then this function will return EINA_FALSE.
422  * 
423  * @ingroup E_Illume_Main_Group
424  */
425 EAPI Eina_Bool 
426 e_illume_border_is_quickpanel(E_Border *bd) 
427 {
428    /* make sure we have a border */
429    if (!bd) return EINA_FALSE;
430
431    /* return if it is a quickpanel or not */
432    return bd->client.illume.quickpanel.quickpanel;
433 }
434
435 /**
436  * Determine if the border request a fixed size.
437  * 
438  * @param bd The border to get the minium space for.
439  * @return EINA_TRUE if border requested fixed size, EINA_FALSE otherwise.
440  *
441  * @note If @p bd is NULL then this function will return EINA_FALSE.
442  *
443  * @ingroup E_Illume_Main_Group
444  */
445 EAPI Eina_Bool 
446 e_illume_border_is_fixed_size(E_Border *bd)
447 {
448    /* make sure we have a border */
449    if (!bd) return EINA_FALSE;
450
451    if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
452        (bd->client.icccm.min_h == bd->client.icccm.max_h))
453      return EINA_TRUE;
454    
455    if ((bd->client.mwm.exists) && 
456        !((bd->client.mwm.func & ECORE_X_MWM_HINT_FUNC_ALL) ||
457          (bd->client.mwm.func & ECORE_X_MWM_HINT_FUNC_MAXIMIZE) ||
458          (bd->client.mwm.func & ECORE_X_MWM_HINT_FUNC_RESIZE)))
459      return EINA_TRUE;
460
461    return EINA_FALSE;
462 }
463
464 /**
465  * Retrieves the minimum space required to display this border.
466  * 
467  * @param bd The border to get the minium space for.
468  * @param w Pointer to an integer into which the width is to be stored.
469  * @param h Pointer to an integer into which the height is to be stored.
470  * 
471  * @note if @p bd is NULL then @p w and @p h will return @c 0.
472  * 
473  * @ingroup E_Illume_Main_Group
474  */
475 EAPI void 
476 e_illume_border_min_get(E_Border *bd, int *w, int *h) 
477 {
478    if (w) *w = 0;
479    if (h) *h = 0;
480    if (!bd) return;
481
482    if (w) 
483      {
484         if (bd->client.icccm.base_w > bd->client.icccm.min_w) 
485           *w = bd->client.icccm.base_w;
486         else
487           *w = bd->client.icccm.min_w;
488      }
489    if (h) 
490      {
491         if (bd->client.icccm.base_h > bd->client.icccm.min_h)
492           *h = bd->client.icccm.base_h;
493         else
494           *h = bd->client.icccm.min_h;
495      }
496 }
497
498 /**
499  * Retrieves a border, given an x and y coordinate, from a zone.
500  * 
501  * @param zone The zone.
502  * @param x The X coordinate to check for border at.
503  * @param y The Y coordinate to check for border at.
504  * 
505  * @note if @p zone is NULL then this function will return NULL.
506  * 
507  * @warning Both X and Y coordinates are required to reliably detect a border.
508  * 
509  * @ingroup E_Illume_Main_Group
510  */
511 EAPI E_Border *
512 e_illume_border_at_xy_get(E_Zone *zone, int x, int y) 
513 {
514    Eina_List *l;
515    E_Border *bd;
516
517    /* make sure we have a zone */
518    if (!zone) return NULL;
519
520    /* loop the border client list */
521    /* NB: We use e_border_client_list here, rather than 
522     * e_container_border_list, because e_border_client_list is faster.
523     * This is done in reverse order so we get the most recent border first */
524    EINA_LIST_REVERSE_FOREACH(e_border_client_list(), l, bd) 
525      {
526         /* check zone and skip borders not on this zone */
527         if (bd->zone != zone) continue;
528
529         /* skip invisibles */
530         if (!bd->visible) continue;
531
532         /* check position against given coordinates */
533         if ((bd->x != x) || (bd->y != y)) continue;
534
535         /* filter out borders we don't want */
536         if (e_illume_border_is_indicator(bd)) continue;
537         if (e_illume_border_is_softkey(bd)) continue;
538         if (e_illume_border_is_keyboard(bd)) continue;
539         if (e_illume_border_is_quickpanel(bd)) continue;
540         if (e_illume_border_is_home(bd)) continue;
541
542         /* found one, return it */
543         return bd;
544      }
545
546    /* return a fallback */
547    return NULL;
548 }
549
550 /**
551  * Retrieve the parent of a given dialog.
552  * 
553  * @param bd The border to get the parent of.
554  * @return The border's parent, or NULL if no parent exists.
555  * 
556  * @note If @p bd is NULL then this function will return NULL.
557  * 
558  * @ingroup E_Illume_Main_Group
559  */
560 EAPI E_Border *
561 e_illume_border_parent_get(E_Border *bd) 
562 {
563    /* make sure we have a border */
564    if (!bd) return NULL;
565
566    /* check for border's parent */
567    if (bd->parent) return bd->parent;
568
569    /* NB: TEST CODE - may need to check bd->leader here */
570    if (bd->leader) 
571      printf("\tDialog Has Leader: %s\n", bd->client.icccm.name);
572
573    /* check for transient */
574    if (bd->client.icccm.transient_for) 
575      {
576         /* try to find this borders parent */
577         return e_border_find_by_client_window(bd->client.icccm.transient_for);
578      }
579    else if (bd->client.icccm.client_leader) 
580      {
581         /* NB: using client_leader as parent. THIS NEEDS THOROUGH TESTING !! */
582         return e_border_find_by_client_window(bd->client.icccm.client_leader);
583      }
584
585    /* return a fallback */
586    return NULL;
587 }
588
589 /**
590  * Show a given border.
591  * 
592  * @param bd The border to show.
593  * 
594  * @note If @p bd is NULL then this function will return.
595  * 
596  * @ingroup E_Illume_Main_Group
597  */
598 EAPI void 
599 e_illume_border_show(E_Border *bd) 
600 {
601    /* make sure we have a border */
602    if (!bd) return;
603
604    e_border_uniconify(bd);
605    e_border_raise(bd);
606    e_border_show(bd);
607    return;
608
609 #if 0   
610    unsigned int visible = 1;
611
612    /* NB: We handle shows this way so we don't get extra layout events from 
613     * the e_border calls */
614    e_container_border_lower(bd);
615    e_container_shape_show(bd->shape);
616    if (!bd->need_reparent) ecore_x_window_show(bd->client.win);
617    e_hints_window_visible_set(bd);
618    bd->visible = 1;
619    bd->changes.visible = 1;
620    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
621    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
622 #endif   
623 }
624
625 /**
626  * Hide a given border.
627  * 
628  * @param bd The border to hide.
629  * 
630  * @note If @p bd is NULL then this function will return.
631  * 
632  * @ingroup E_Illume_Main_Group
633  */
634 EAPI void 
635 e_illume_border_hide(E_Border *bd) 
636 {
637    /* make sure we have a border */
638    if (!bd) return;
639
640    e_border_iconify(bd);
641    return;
642
643 #if 0   
644    unsigned int visible = 0;
645
646    /* NB: We handle hides this way so we don't get extra layout events from 
647     * the e_border calls */
648    e_container_shape_hide(bd->shape);
649    if (!bd->iconic) e_hints_window_hidden_set(bd);
650    bd->visible = 0;
651    bd->changes.visible = 1;
652    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
653 #endif   
654 }
655
656 /**
657  * Retrieve the Indicator window on a given zone.
658  * 
659  * @param zone The zone.
660  * @return The Indicator border, or NULL if no Indicator exists.
661  * 
662  * @note If @p zone is NULL then this function will return NULL.
663  * 
664  * @ingroup E_Illume_Main_Group
665  */
666 EAPI E_Border *
667 e_illume_border_indicator_get(E_Zone *zone) 
668 {
669    Eina_List *l;
670    E_Border *bd;
671
672    /* make sure we have a zone */
673    if (!zone) return NULL;
674
675    /* loop the border client list */
676    /* NB: We use e_border_client_list here, rather than 
677     * e_container_border_list, because e_border_client_list is faster */
678    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
679      {
680         /* check zone and skip borders not on this zone */
681         if (bd->zone != zone) continue;
682
683         /* skip borders that are not indicators */
684         if (!e_illume_border_is_indicator(bd)) continue;
685
686         /* found one, return it */
687         return bd;
688      }
689
690    /* return a fallback */
691    return NULL;
692 }
693
694 /**
695  * Retrieves the current position of the Indicator window.
696  * 
697  * @param zone The zone on which to retrieve the Indicator position.
698  * @param x Pointer to an integer into which the left is to be stored.
699  * @param y Pointer to an integer into which the top is to be stored.
700  * 
701  * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0.
702  * 
703  * @ingroup E_Illume_Main_Group
704  */
705 EAPI void 
706 e_illume_border_indicator_pos_get(E_Zone *zone, int *x, int *y) 
707 {
708    E_Border *ind;
709
710    if (x) *x = 0;
711    if (y) *y = 0;
712
713    /* make sure we have a zone */
714    if (!zone) return;
715
716    /* set default values */
717    if (x) *x = zone->x;
718    if (y) *y = zone->y;
719
720    /* try and get the Indicator on this zone */
721    if (!(ind = e_illume_border_indicator_get(zone))) return;
722
723    /* return Indicator position(s) */
724    if (x) *x = ind->x;
725    if (y) *y = ind->y;
726 }
727
728 /**
729  * Retrieve the Softkey window on a given zone.
730  * 
731  * @param zone The zone.
732  * @return The Softkey border, or NULL if no Softkey exists.
733  * 
734  * @note If @p zone is NULL then this function will return NULL.
735  * 
736  * @ingroup E_Illume_Main_Group
737  */
738 EAPI E_Border *
739 e_illume_border_softkey_get(E_Zone *zone) 
740 {
741    Eina_List *l;
742    E_Border *bd;
743
744    /* make sure we have a zone */
745    if (!zone) return NULL;
746
747    /* loop the border client list */
748    /* NB: We use e_border_client_list here, rather than 
749     * e_container_border_list, because e_border_client_list is faster */
750    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
751      {
752         /* check zone and skip borders not on this zone */
753         if (bd->zone != zone) continue;
754
755         /* skip borders that are not indicators */
756         if (!e_illume_border_is_softkey(bd)) continue;
757
758         /* found one, return it */
759         return bd;
760      }
761
762    /* return a fallback */
763    return NULL;
764 }
765
766 /**
767  * Retrieves the current position of the Softkey window.
768  * 
769  * @param zone The zone on which to retrieve the Softkey position.
770  * @param x Pointer to an integer into which the left is to be stored.
771  * @param y Pointer to an integer into which the top is to be stored.
772  * 
773  * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0.
774  * 
775  * @ingroup E_Illume_Main_Group
776  */
777 EAPI void 
778 e_illume_border_softkey_pos_get(E_Zone *zone, int *x, int *y) 
779 {
780    E_Border *sft;
781
782    if (x) *x = 0;
783    if (y) *y = 0;
784
785    /* make sure we have a zone */
786    if (!zone) return;
787
788   /* set default values */
789    if (x) *x = zone->x;
790    if (y) *y = zone->y;
791
792    /* try and get the Softkey on this zone */
793    if (!(sft = e_illume_border_softkey_get(zone))) return;
794
795    /* return Indicator position(s) */
796    if (x) *x = sft->x;
797    if (y) *y = sft->y;
798 }
799
800 /**
801  * Retrieve the Keyboard.
802  * 
803  * @return The @ref E_Illume_Keyboard, or NULL if no keyboard exists.
804  * 
805  * @ingroup E_Illume_Keyboard_Group
806  */
807 EAPI E_Illume_Keyboard *
808 e_illume_keyboard_get(void) 
809 {
810    /* make sure we have a keyboard */
811    if (!_e_illume_kbd) return NULL;
812
813    /* return the keyboard */
814    return _e_illume_kbd;
815 }
816
817 /**
818  * Retrieves the available screen space not occupied by the virtual keyboard.
819  * 
820  * @param zone The zone on which to retrieve the available space.
821  * @param x Pointer to an integer into which the left is to be stored.
822  * @param y Pointer to an integer into which the top is to be stored.
823  * @param w Pointer to an integer into which the width is to be stored.
824  * @param h Pointer to an integer into which the height is to be stored.
825  * 
826  * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0.
827  * 
828  * @warning This function does not account for space or position of Indicator 
829  * or Softkey windows.
830  * 
831  * @ingroup E_Illume_Keyboard_Group
832  */
833 EAPI void 
834 e_illume_keyboard_safe_app_region_get(E_Zone *zone, int *x, int *y, int *w, int *h) 
835 {
836    if (x) *x = 0;
837    if (y) *y = 0;
838    if (w) *w = 0;
839    if (h) *h = 0;
840
841    /* make sure we have a zone */
842    if (!zone) return;
843
844    /* set default values */
845    if (x) *x = zone->x;
846    if (y) *y = zone->y;
847    if (w) *w = zone->w;
848    if (h) *h = zone->h;
849
850    /* if the keyboard is disabled, get out */
851    if ((!_e_illume_kbd->visible) || (_e_illume_kbd->disabled)) return;
852
853    /* if we don't have a border, get out */
854    /* NB: This basically means that we have the vkbd structure, but no 
855     * app or module present to act as the vkbd */
856    if (!_e_illume_kbd->border) return;
857
858    /* if the keyboard border is not on this zone, get out */
859    if (_e_illume_kbd->border->zone != zone) return;
860
861    if (!_e_illume_kbd->animator) 
862      {
863         if (h) 
864           {
865              *h -= _e_illume_kbd->border->h;
866              if (*h < 0) *h = 0;
867           }
868      }
869 }
870
871 /**
872  * Retrieve the Home window on a given zone.
873  * 
874  * @param zone The zone.
875  * @return The Home window, or NULL if no Home window exists.
876  * 
877  * @note If @p zone is NULL then this function will return NULL.
878  * 
879  * @ingroup E_Illume_Main_Group
880  */
881 EAPI E_Border *
882 e_illume_border_home_get(E_Zone *zone) 
883 {
884    E_Border *bd;
885    Eina_List *l;
886
887    /* make sure we have a zone */
888    if (!zone) return NULL;
889
890    /* loop the border client list */
891    /* NB: We use e_border_client_list here, rather than 
892     * e_container_border_list, because e_border_client_list is faster */
893    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
894      {
895         /* check zone and skip borders not on this zone */
896         if (bd->zone != zone) continue;
897
898         /* skip borders that are not home windows */
899         if (!e_illume_border_is_home(bd)) continue;
900
901         /* found one, return it */
902         return bd;
903      }
904
905    /* return a fallback */
906    return NULL;
907 }
908
909 /**
910  * Retrieve the list of Home windows on a given zone.
911  * 
912  * @param zone The zone.
913  * @return A list of existing Home windows, or NULL if none exist.
914  * 
915  * @note If @p zone is NULL then this function will return NULL.
916  * 
917  * @ingroup E_Illume_Main_Group
918  */
919 EAPI Eina_List *
920 e_illume_border_home_borders_get(E_Zone *zone) 
921 {
922    Eina_List *ret = NULL, *l;
923    E_Border *bd;
924
925    /* make sure we have a zone */
926    if (!zone) return NULL;
927
928    /* loop the border client list */
929    /* NB: We use e_border_client_list here, rather than 
930     * e_container_border_list, because e_border_client_list is faster */
931    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
932      {
933         /* check zone and skip borders not on this zone */
934         if (bd->zone != zone) continue;
935
936         /* skip borders that are not home windows */
937         if (!e_illume_border_is_home(bd)) continue;
938
939         /* found one, append it to the list */
940         ret = eina_list_append(ret, bd);
941      }
942
943    /* return the list */
944    return ret;
945 }
946
947 /**
948  * Retrieve the Illume Quickpanel on a given zone.
949  * 
950  * @param zone The zone on which to retrieve the Quickpanel.
951  * @return The @ref E_Illume_Quickpanel on this zone, or NULL if none exists.
952  * 
953  * @note If @p zone is NULL then this function will return NULL.
954  * 
955  * @ingroup E_Illume_Quickpanel_Group
956  */
957 EAPI E_Illume_Quickpanel *
958 e_illume_quickpanel_by_zone_get(E_Zone *zone) 
959 {
960    E_Illume_Quickpanel *qp;
961    Eina_List *l;
962
963    /* make sure we have a zone */
964    if (!zone) return NULL;
965
966    /* loop the list of quickpanels, looking for one on this zone */
967    EINA_LIST_FOREACH(_e_illume_qps, l, qp)
968      if (qp->zone == zone) return qp;
969
970    /* return a fallback */
971    return NULL;
972 }
973
974 /**
975  * Show the Illume Quickpanel on a given zone.
976  * 
977  * @param zone The zone on which to show the Quickpanel.
978  * 
979  * @note If @p zone is NULL then this function will return.
980  * 
981  * @ingroup E_Illume_Quickpanel_Group
982  */
983 EAPI void 
984 e_illume_quickpanel_show(E_Zone *zone) 
985 {
986    if (!zone) return;
987    ecore_x_e_illume_quickpanel_state_send(zone->black_win, 
988                                           ECORE_X_ILLUME_QUICKPANEL_STATE_ON);
989 }
990
991 /**
992  * Hide the Illume Quickpanel on a given zone.
993  * 
994  * @param zone The zone on which to hide the Quickpanel.
995  * 
996  * @note If @p zone is NULL then this function will return.
997  * 
998  * @ingroup E_Illume_Quickpanel_Group
999  */
1000 EAPI void 
1001 e_illume_quickpanel_hide(E_Zone *zone) 
1002 {
1003    if (!zone) return;
1004    ecore_x_e_illume_quickpanel_state_send(zone->black_win, 
1005                                           ECORE_X_ILLUME_QUICKPANEL_STATE_OFF);
1006 }