e8fb3f985d748968ceeaee8ec9a2ee0d508a1f1e
[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    /* return a fallback */
307    return EINA_FALSE;
308 }
309
310 /**
311  * Determine if a given border is a dialog.
312  * 
313  * @param bd The border to test.
314  * @return EINA_TRUE if it is a dialog, EINA_FALSE otherwise.
315  * 
316  * @note If @p bd is NULL then this function will return EINA_FALSE.
317  * 
318  * @ingroup E_Illume_Main_Group
319  */
320 EAPI Eina_Bool 
321 e_illume_border_is_dialog(E_Border *bd) 
322 {
323    /* make sure we have a border */
324    if (!bd) return EINA_FALSE;
325
326    /* check actual type */
327    if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG) return EINA_TRUE;
328
329    /* check for transient flag */
330    if (bd->client.icccm.transient_for != 0) return EINA_TRUE;
331
332    /* check for client leader */
333    /* NB: disabled currently as some GTK windows set this even tho they are 
334     * not a dialog. */
335 //   if (bd->client.icccm.client_leader) return EINA_TRUE;
336
337    /* NB: may or may not need to handle these. Needs Testing */
338    if (bd->client.netwm.extra_types) 
339      printf("\t\tBorder has extra types: %s\n", bd->client.icccm.class);
340
341    /* return a fallback */
342    return EINA_FALSE;
343 }
344
345 /**
346  * Determine if a given border is a QT VCLSalFrame.
347  * 
348  * @param bd The border to test.
349  * @return EINA_TRUE if it is a VCLSalFrame, EINA_FALSE otherwise.
350  * 
351  * @note If @p bd is NULL then this function will return EINA_FALSE.
352  * 
353  * @ingroup E_Illume_Main_Group
354  */
355 EAPI Eina_Bool 
356 e_illume_border_is_qt_frame(E_Border *bd) 
357 {
358    /* make sure we have a border */
359    if (!bd) return EINA_FALSE;
360
361    /* make sure we have the icccm name and compare it */
362    if ((bd->client.icccm.name) && 
363        (!strncmp(bd->client.icccm.name, "VCLSalFrame", 11)))
364      return EINA_TRUE;
365
366    /* return a fallback */
367    return EINA_FALSE;
368 }
369
370 /**
371  * Determine if a given border is a fullscreen window.
372  * 
373  * @param bd The border to test.
374  * @return EINA_TRUE if it is fullscreen, EINA_FALSE otherwise.
375  * 
376  * @note If @p bd is NULL then this function will return EINA_FALSE.
377  * 
378  * @ingroup E_Illume_Main_Group
379  */
380 EAPI Eina_Bool 
381 e_illume_border_is_fullscreen(E_Border *bd) 
382 {
383    /* make sure we have a border */
384    if (!bd) return EINA_FALSE;
385
386    /* check for fullscreen */
387    if ((bd->fullscreen) || (bd->need_fullscreen)) return EINA_TRUE;
388
389    /* return a fallback */
390    return EINA_FALSE;
391 }
392
393 /**
394  * Determine if a given border is an illume conformant window.
395  * 
396  * @param bd The border to test.
397  * @return EINA_TRUE if it is conformant, EINA_FALSE otherwise.
398  * 
399  * @note If @p bd is NULL then this function will return EINA_FALSE.
400  * 
401  * @ingroup E_Illume_Main_Group
402  */
403 EAPI Eina_Bool 
404 e_illume_border_is_conformant(E_Border *bd) 
405 {
406    /* make sure we have a border */
407    if (!bd) return EINA_FALSE;
408
409    /* return if it is conformant or not */
410    return bd->client.illume.conformant.conformant;
411 }
412
413 /**
414  * Determine if a given border is a quickpanel window.
415  * 
416  * @param bd The border to test.
417  * @return EINA_TRUE if it is a quickpanel, EINA_FALSE otherwise.
418  * 
419  * @note If @p bd is NULL then this function will return EINA_FALSE.
420  * 
421  * @ingroup E_Illume_Main_Group
422  */
423 EAPI Eina_Bool 
424 e_illume_border_is_quickpanel(E_Border *bd) 
425 {
426    /* make sure we have a border */
427    if (!bd) return EINA_FALSE;
428
429    /* return if it is a quickpanel or not */
430    return bd->client.illume.quickpanel.quickpanel;
431 }
432
433 /**
434  * Retrieves the minimum space required to display this border.
435  * 
436  * @param bd The border to get the minium space for.
437  * @param w Pointer to an integer into which the width is to be stored.
438  * @param h Pointer to an integer into which the height is to be stored.
439  * 
440  * @note if @p bd is NULL then @p w and @p h will return @c 0.
441  * 
442  * @ingroup E_Illume_Main_Group
443  */
444 EAPI void 
445 e_illume_border_min_get(E_Border *bd, int *w, int *h) 
446 {
447    if (w) *w = 0;
448    if (h) *h = 0;
449    if (!bd) return;
450
451    if (w) 
452      {
453         if (bd->client.icccm.base_w > bd->client.icccm.min_w) 
454           *w = bd->client.icccm.base_w;
455         else
456           *w = bd->client.icccm.min_w;
457      }
458    if (h) 
459      {
460         if (bd->client.icccm.base_h > bd->client.icccm.min_h)
461           *h = bd->client.icccm.base_h;
462         else
463           *h = bd->client.icccm.min_h;
464      }
465 }
466
467 /**
468  * Retrieves a border, given an x and y coordinate, from a zone.
469  * 
470  * @param zone The zone.
471  * @param x The X coordinate to check for border at.
472  * @param y The Y coordinate to check for border at.
473  * 
474  * @note if @p zone is NULL then this function will return NULL.
475  * 
476  * @warning Both X and Y coordinates are required to reliably detect a border.
477  * 
478  * @ingroup E_Illume_Main_Group
479  */
480 EAPI E_Border *
481 e_illume_border_at_xy_get(E_Zone *zone, int x, int y) 
482 {
483    Eina_List *l;
484    E_Border *bd;
485
486    /* make sure we have a zone */
487    if (!zone) return NULL;
488
489    /* loop the border client list */
490    /* NB: We use e_border_client_list here, rather than 
491     * e_container_border_list, because e_border_client_list is faster.
492     * This is done in reverse order so we get the most recent border first */
493    EINA_LIST_REVERSE_FOREACH(e_border_client_list(), l, bd) 
494      {
495         /* check zone and skip borders not on this zone */
496         if (bd->zone != zone) continue;
497
498         /* skip invisibles */
499         if (!bd->visible) continue;
500
501         /* check position against given coordinates */
502         if ((bd->x != x) || (bd->y != y)) continue;
503
504         /* filter out borders we don't want */
505         if (e_illume_border_is_indicator(bd)) continue;
506         if (e_illume_border_is_softkey(bd)) continue;
507         if (e_illume_border_is_keyboard(bd)) continue;
508         if (e_illume_border_is_quickpanel(bd)) continue;
509         if (e_illume_border_is_home(bd)) continue;
510
511         /* found one, return it */
512         return bd;
513      }
514
515    /* return a fallback */
516    return NULL;
517 }
518
519 /**
520  * Retrieve the parent of a given dialog.
521  * 
522  * @param bd The border to get the parent of.
523  * @return The border's parent, or NULL if no parent exists.
524  * 
525  * @note If @p bd is NULL then this function will return NULL.
526  * 
527  * @ingroup E_Illume_Main_Group
528  */
529 EAPI E_Border *
530 e_illume_border_parent_get(E_Border *bd) 
531 {
532    /* make sure we have a border */
533    if (!bd) return NULL;
534
535    /* check for border's parent */
536    if (bd->parent) return bd->parent;
537
538    /* NB: TEST CODE - may need to check bd->leader here */
539    if (bd->leader) 
540      printf("\tDialog Has Leader: %s\n", bd->client.icccm.name);
541
542    /* check for transient */
543    if (bd->client.icccm.transient_for) 
544      {
545         /* try to find this borders parent */
546         return e_border_find_by_client_window(bd->client.icccm.transient_for);
547      }
548    else if (bd->client.icccm.client_leader) 
549      {
550         /* NB: using client_leader as parent. THIS NEEDS THOROUGH TESTING !! */
551         return e_border_find_by_client_window(bd->client.icccm.client_leader);
552      }
553
554    /* return a fallback */
555    return NULL;
556 }
557
558 /**
559  * Show a given border.
560  * 
561  * @param bd The border to show.
562  * 
563  * @note If @p bd is NULL then this function will return.
564  * 
565  * @ingroup E_Illume_Main_Group
566  */
567 EAPI void 
568 e_illume_border_show(E_Border *bd) 
569 {
570    /* make sure we have a border */
571    if (!bd) return;
572
573    e_border_uniconify(bd);
574    e_border_raise(bd);
575    e_border_show(bd);
576    return;
577
578 #if 0   
579    unsigned int visible = 1;
580
581    /* NB: We handle shows this way so we don't get extra layout events from 
582     * the e_border calls */
583    e_container_border_lower(bd);
584    e_container_shape_show(bd->shape);
585    if (!bd->need_reparent) ecore_x_window_show(bd->client.win);
586    e_hints_window_visible_set(bd);
587    bd->visible = 1;
588    bd->changes.visible = 1;
589    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
590    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
591 #endif   
592 }
593
594 /**
595  * Hide a given border.
596  * 
597  * @param bd The border to hide.
598  * 
599  * @note If @p bd is NULL then this function will return.
600  * 
601  * @ingroup E_Illume_Main_Group
602  */
603 EAPI void 
604 e_illume_border_hide(E_Border *bd) 
605 {
606    /* make sure we have a border */
607    if (!bd) return;
608
609    e_border_iconify(bd);
610    return;
611
612 #if 0   
613    unsigned int visible = 0;
614
615    /* NB: We handle hides this way so we don't get extra layout events from 
616     * the e_border calls */
617    e_container_shape_hide(bd->shape);
618    if (!bd->iconic) e_hints_window_hidden_set(bd);
619    bd->visible = 0;
620    bd->changes.visible = 1;
621    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
622 #endif   
623 }
624
625 /**
626  * Retrieve the Indicator window on a given zone.
627  * 
628  * @param zone The zone.
629  * @return The Indicator border, or NULL if no Indicator exists.
630  * 
631  * @note If @p zone is NULL then this function will return NULL.
632  * 
633  * @ingroup E_Illume_Main_Group
634  */
635 EAPI E_Border *
636 e_illume_border_indicator_get(E_Zone *zone) 
637 {
638    Eina_List *l;
639    E_Border *bd;
640
641    /* make sure we have a zone */
642    if (!zone) return NULL;
643
644    /* loop the border client list */
645    /* NB: We use e_border_client_list here, rather than 
646     * e_container_border_list, because e_border_client_list is faster */
647    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
648      {
649         /* check zone and skip borders not on this zone */
650         if (bd->zone != zone) continue;
651
652         /* skip borders that are not indicators */
653         if (!e_illume_border_is_indicator(bd)) continue;
654
655         /* found one, return it */
656         return bd;
657      }
658
659    /* return a fallback */
660    return NULL;
661 }
662
663 /**
664  * Retrieves the current position of the Indicator window.
665  * 
666  * @param zone The zone on which to retrieve the Indicator position.
667  * @param x Pointer to an integer into which the left is to be stored.
668  * @param y Pointer to an integer into which the top is to be stored.
669  * 
670  * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0.
671  * 
672  * @ingroup E_Illume_Main_Group
673  */
674 EAPI void 
675 e_illume_border_indicator_pos_get(E_Zone *zone, int *x, int *y) 
676 {
677    E_Border *ind;
678
679    if (x) *x = 0;
680    if (y) *y = 0;
681
682    /* make sure we have a zone */
683    if (!zone) return;
684
685    /* set default values */
686    if (x) *x = zone->x;
687    if (y) *y = zone->y;
688
689    /* try and get the Indicator on this zone */
690    if (!(ind = e_illume_border_indicator_get(zone))) return;
691
692    /* return Indicator position(s) */
693    if (x) *x = ind->x;
694    if (y) *y = ind->y;
695 }
696
697 /**
698  * Retrieve the Softkey window on a given zone.
699  * 
700  * @param zone The zone.
701  * @return The Softkey border, or NULL if no Softkey exists.
702  * 
703  * @note If @p zone is NULL then this function will return NULL.
704  * 
705  * @ingroup E_Illume_Main_Group
706  */
707 EAPI E_Border *
708 e_illume_border_softkey_get(E_Zone *zone) 
709 {
710    Eina_List *l;
711    E_Border *bd;
712
713    /* make sure we have a zone */
714    if (!zone) return NULL;
715
716    /* loop the border client list */
717    /* NB: We use e_border_client_list here, rather than 
718     * e_container_border_list, because e_border_client_list is faster */
719    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
720      {
721         /* check zone and skip borders not on this zone */
722         if (bd->zone != zone) continue;
723
724         /* skip borders that are not indicators */
725         if (!e_illume_border_is_softkey(bd)) continue;
726
727         /* found one, return it */
728         return bd;
729      }
730
731    /* return a fallback */
732    return NULL;
733 }
734
735 /**
736  * Retrieves the current position of the Softkey window.
737  * 
738  * @param zone The zone on which to retrieve the Softkey position.
739  * @param x Pointer to an integer into which the left is to be stored.
740  * @param y Pointer to an integer into which the top is to be stored.
741  * 
742  * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0.
743  * 
744  * @ingroup E_Illume_Main_Group
745  */
746 EAPI void 
747 e_illume_border_softkey_pos_get(E_Zone *zone, int *x, int *y) 
748 {
749    E_Border *sft;
750
751    if (x) *x = 0;
752    if (y) *y = 0;
753
754    /* make sure we have a zone */
755    if (!zone) return;
756
757   /* set default values */
758    if (x) *x = zone->x;
759    if (y) *y = zone->y;
760
761    /* try and get the Softkey on this zone */
762    if (!(sft = e_illume_border_softkey_get(zone))) return;
763
764    /* return Indicator position(s) */
765    if (x) *x = sft->x;
766    if (y) *y = sft->y;
767 }
768
769 /**
770  * Retrieve the Keyboard.
771  * 
772  * @return The @ref E_Illume_Keyboard, or NULL if no keyboard exists.
773  * 
774  * @ingroup E_Illume_Keyboard_Group
775  */
776 EAPI E_Illume_Keyboard *
777 e_illume_keyboard_get(void) 
778 {
779    /* make sure we have a keyboard */
780    if (!_e_illume_kbd) return NULL;
781
782    /* return the keyboard */
783    return _e_illume_kbd;
784 }
785
786 /**
787  * Retrieves the available screen space not occupied by the virtual keyboard.
788  * 
789  * @param zone The zone on which to retrieve the available space.
790  * @param x Pointer to an integer into which the left is to be stored.
791  * @param y Pointer to an integer into which the top is to be stored.
792  * @param w Pointer to an integer into which the width is to be stored.
793  * @param h Pointer to an integer into which the height is to be stored.
794  * 
795  * @note if @p zone is NULL then @p x, @p y, @p w, and @p h will return @c 0.
796  * 
797  * @warning This function does not account for space or position of Indicator 
798  * or Softkey windows.
799  * 
800  * @ingroup E_Illume_Keyboard_Group
801  */
802 EAPI void 
803 e_illume_keyboard_safe_app_region_get(E_Zone *zone, int *x, int *y, int *w, int *h) 
804 {
805    if (x) *x = 0;
806    if (y) *y = 0;
807    if (w) *w = 0;
808    if (h) *h = 0;
809
810    /* make sure we have a zone */
811    if (!zone) return;
812
813    /* set default values */
814    if (x) *x = zone->x;
815    if (y) *y = zone->y;
816    if (w) *w = zone->w;
817    if (h) *h = zone->h;
818
819    /* if the keyboard is disabled, get out */
820    if ((!_e_illume_kbd->visible) || (_e_illume_kbd->disabled)) return;
821
822    /* if we don't have a border, get out */
823    /* NB: This basically means that we have the vkbd structure, but no 
824     * app or module present to act as the vkbd */
825    if (!_e_illume_kbd->border) return;
826
827    /* if the keyboard border is not on this zone, get out */
828    if (_e_illume_kbd->border->zone != zone) return;
829
830    if (!_e_illume_kbd->animator) 
831      {
832         if (h) 
833           {
834              *h -= _e_illume_kbd->border->h;
835              if (*h < 0) *h = 0;
836           }
837      }
838 }
839
840 /**
841  * Retrieve the Home window on a given zone.
842  * 
843  * @param zone The zone.
844  * @return The Home window, or NULL if no Home window exists.
845  * 
846  * @note If @p zone is NULL then this function will return NULL.
847  * 
848  * @ingroup E_Illume_Main_Group
849  */
850 EAPI E_Border *
851 e_illume_border_home_get(E_Zone *zone) 
852 {
853    E_Border *bd;
854    Eina_List *l;
855
856    /* make sure we have a zone */
857    if (!zone) return NULL;
858
859    /* loop the border client list */
860    /* NB: We use e_border_client_list here, rather than 
861     * e_container_border_list, because e_border_client_list is faster */
862    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
863      {
864         /* check zone and skip borders not on this zone */
865         if (bd->zone != zone) continue;
866
867         /* skip borders that are not home windows */
868         if (!e_illume_border_is_home(bd)) continue;
869
870         /* found one, return it */
871         return bd;
872      }
873
874    /* return a fallback */
875    return NULL;
876 }
877
878 /**
879  * Retrieve the list of Home windows on a given zone.
880  * 
881  * @param zone The zone.
882  * @return A list of existing Home windows, or NULL if none exist.
883  * 
884  * @note If @p zone is NULL then this function will return NULL.
885  * 
886  * @ingroup E_Illume_Main_Group
887  */
888 EAPI Eina_List *
889 e_illume_border_home_borders_get(E_Zone *zone) 
890 {
891    Eina_List *ret = NULL, *l;
892    E_Border *bd;
893
894    /* make sure we have a zone */
895    if (!zone) return NULL;
896
897    /* loop the border client list */
898    /* NB: We use e_border_client_list here, rather than 
899     * e_container_border_list, because e_border_client_list is faster */
900    EINA_LIST_FOREACH(e_border_client_list(), l, bd) 
901      {
902         /* check zone and skip borders not on this zone */
903         if (bd->zone != zone) continue;
904
905         /* skip borders that are not home windows */
906         if (!e_illume_border_is_home(bd)) continue;
907
908         /* found one, append it to the list */
909         ret = eina_list_append(ret, bd);
910      }
911
912    /* return the list */
913    return ret;
914 }
915
916 /**
917  * Retrieve the Illume Quickpanel on a given zone.
918  * 
919  * @param zone The zone on which to retrieve the Quickpanel.
920  * @return The @ref E_Illume_Quickpanel on this zone, or NULL if none exists.
921  * 
922  * @note If @p zone is NULL then this function will return NULL.
923  * 
924  * @ingroup E_Illume_Quickpanel_Group
925  */
926 EAPI E_Illume_Quickpanel *
927 e_illume_quickpanel_by_zone_get(E_Zone *zone) 
928 {
929    E_Illume_Quickpanel *qp;
930    Eina_List *l;
931
932    /* make sure we have a zone */
933    if (!zone) return NULL;
934
935    /* loop the list of quickpanels, looking for one on this zone */
936    EINA_LIST_FOREACH(_e_illume_qps, l, qp)
937      if (qp->zone == zone) return qp;
938
939    /* return a fallback */
940    return NULL;
941 }
942
943 /**
944  * Show the Illume Quickpanel on a given zone.
945  * 
946  * @param zone The zone on which to show the Quickpanel.
947  * 
948  * @note If @p zone is NULL then this function will return.
949  * 
950  * @ingroup E_Illume_Quickpanel_Group
951  */
952 EAPI void 
953 e_illume_quickpanel_show(E_Zone *zone) 
954 {
955    if (!zone) return;
956    ecore_x_e_illume_quickpanel_state_send(zone->black_win, 
957                                           ECORE_X_ILLUME_QUICKPANEL_STATE_ON);
958 }
959
960 /**
961  * Hide the Illume Quickpanel on a given zone.
962  * 
963  * @param zone The zone on which to hide the Quickpanel.
964  * 
965  * @note If @p zone is NULL then this function will return.
966  * 
967  * @ingroup E_Illume_Quickpanel_Group
968  */
969 EAPI void 
970 e_illume_quickpanel_hide(E_Zone *zone) 
971 {
972    if (!zone) return;
973    ecore_x_e_illume_quickpanel_state_send(zone->black_win, 
974                                           ECORE_X_ILLUME_QUICKPANEL_STATE_OFF);
975 }