fix shutdown+init cycle with deferred win free
[framework/uifw/elementary.git] / src / lib / elm_win.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Win Win
6  *
7  * The window class of Elementary.  Contains functions to manipulate
8  * windows.
9  */
10
11 typedef struct _Elm_Win Elm_Win;
12
13 struct _Elm_Win
14 {
15    Ecore_Evas *ee;
16    Evas *evas;
17    Evas_Object *parent, *win_obj;
18    Eina_List *subobjs;
19 #ifdef HAVE_ELEMENTARY_X
20    Ecore_X_Window xwin;
21    Ecore_Event_Handler *client_message_handler;
22 #endif
23    Ecore_Job *deferred_resize_job;
24    Ecore_Job *deferred_child_eval_job;
25
26    Elm_Win_Type type;
27    Elm_Win_Keyboard_Mode kbdmode;
28    Eina_Bool autodel : 1;
29    int *autodel_clear, rot;
30    struct {
31       int x, y;
32    } screen;
33
34    struct {
35       Evas_Object *top;
36
37       struct {
38          Evas_Object *target;
39          Eina_Bool visible : 1;
40          Eina_Bool handled : 1;
41       } cur, prev;
42
43       const char *style;
44       Ecore_Job *reconf_job;
45
46       Eina_Bool enabled : 1;
47       Eina_Bool changed_theme : 1;
48       Eina_Bool top_animate : 1;
49       Eina_Bool geometry_changed : 1;
50    } focus_highlight;
51 };
52
53 static const char *widtype = NULL;
54 static void _elm_win_obj_callback_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
55 static void _elm_win_obj_callback_parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
56 static void _elm_win_obj_intercept_show(void *data, Evas_Object *obj);
57 static void _elm_win_move(Ecore_Evas *ee);
58 static void _elm_win_resize(Ecore_Evas *ee);
59 static void _elm_win_delete_request(Ecore_Evas *ee);
60 static void _elm_win_resize_job(void *data);
61 #ifdef HAVE_ELEMENTARY_X
62 static void _elm_win_xwin_update(Elm_Win *win);
63 #endif
64 static void _elm_win_eval_subobjs(Evas_Object *obj);
65 static void _elm_win_subobj_callback_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
66 static void _elm_win_subobj_callback_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
67 static void _elm_win_focus_highlight_init(Elm_Win *win);
68 static void _elm_win_focus_highlight_shutdown(Elm_Win *win);
69 static void _elm_win_focus_highlight_visible_set(Elm_Win *win, Eina_Bool visible);
70 static void _elm_win_focus_highlight_reconfigure_job_start(Elm_Win *win);
71 static void _elm_win_focus_highlight_reconfigure_job_stop(Elm_Win *win);
72 static void _elm_win_focus_highlight_anim_end(void *data, Evas_Object *obj, const char *emission, const char *source);
73 static void _elm_win_focus_highlight_reconfigure(Elm_Win *win);
74
75 Eina_List *_elm_win_list = NULL;
76 int _elm_win_deferred_free = 0;
77
78 static void
79 _elm_win_move(Ecore_Evas *ee)
80 {
81    Evas_Object *obj = ecore_evas_object_associate_get(ee);
82    Elm_Win *win;
83    int x, y;
84
85    if (!obj) return;
86    win = elm_widget_data_get(obj);
87    if (!win) return;
88    ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
89    win->screen.x = x;
90    win->screen.y = y;
91    evas_object_smart_callback_call(win->win_obj, "moved", NULL);
92 }
93
94 static void
95 _elm_win_resize(Ecore_Evas *ee)
96 {
97    Evas_Object *obj = ecore_evas_object_associate_get(ee);
98    Elm_Win *win;
99
100    if (!obj) return;
101    win = elm_widget_data_get(obj);
102    if (!win) return;
103    if (win->deferred_resize_job) ecore_job_del(win->deferred_resize_job);
104    win->deferred_resize_job = ecore_job_add(_elm_win_resize_job, win);
105 }
106
107 static void
108 _elm_win_focus_in(Ecore_Evas *ee)
109 {
110    Evas_Object *obj = ecore_evas_object_associate_get(ee);
111    Elm_Win *win;
112
113    if (!obj) return;
114    win = elm_widget_data_get(obj);
115    if (!win) return;
116    /*NB: Why two different "focus signals" here ??? */
117    evas_object_smart_callback_call(win->win_obj, "focus-in", NULL); // FIXME: remove me
118    evas_object_smart_callback_call(win->win_obj, "focus,in", NULL);
119    win->focus_highlight.cur.visible = EINA_TRUE;
120    _elm_win_focus_highlight_reconfigure_job_start(win);
121 }
122
123 static void
124 _elm_win_focus_out(Ecore_Evas *ee)
125 {
126    Evas_Object *obj = ecore_evas_object_associate_get(ee);
127    Elm_Win *win;
128
129    if (!obj) return;
130    win = elm_widget_data_get(obj);
131    if (!win) return;
132    evas_object_smart_callback_call(win->win_obj, "focus-out", NULL); // FIXME: remove me
133    evas_object_smart_callback_call(win->win_obj, "focus,out", NULL);
134    win->focus_highlight.cur.visible = EINA_FALSE;
135    _elm_win_focus_highlight_reconfigure_job_start(win);
136 }
137
138 static Eina_Bool
139 _elm_win_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
140 {
141    Elm_Win *wd = elm_widget_data_get(obj);
142    const Eina_List *items;
143    void *(*list_data_get) (const Eina_List *list);
144
145    if (!wd)
146      return EINA_FALSE;
147
148    /* Focus chain */
149    if (wd->subobjs)
150      {
151         if (!(items = elm_widget_focus_custom_chain_get(obj)))
152           {
153              items = wd->subobjs;
154              if (!items)
155                return EINA_FALSE;
156           }
157         list_data_get = eina_list_data_get;
158
159         elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
160
161         if (*next)
162           return EINA_TRUE;
163      }
164
165    *next = (Evas_Object *)obj;
166    return EINA_FALSE;
167 }
168
169 static void
170 _elm_win_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
171 {
172    if (elm_widget_focus_get(obj))
173      evas_object_focus_set(obj, EINA_TRUE);
174    else
175      evas_object_focus_set(obj, EINA_FALSE);
176 }
177
178 static Eina_Bool
179 _elm_win_event_cb(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
180 {
181    if (type == EVAS_CALLBACK_KEY_DOWN)
182      {
183         Evas_Event_Key_Down *ev = event_info;
184         if (!strcmp(ev->keyname, "Tab"))
185           {
186              if(evas_key_modifier_is_set(ev->modifiers, "Shift"))
187                elm_widget_focus_cycle(obj, ELM_FOCUS_PREVIOUS);
188              else
189                elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
190              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
191              return EINA_TRUE;
192           }
193      }
194
195    return EINA_FALSE;
196 }
197
198 static void
199 _deferred_ecore_evas_free(void *data)
200 {
201    ecore_evas_free(data);
202    _elm_win_deferred_free--;
203 }
204
205 static void
206 _elm_win_obj_callback_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
207 {
208    elm_object_focus(obj);
209 }
210
211 static void
212 _elm_win_obj_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
213 {
214    Elm_Win *win = data;
215    Evas_Object *child;
216
217    if (win->parent)
218      {
219         evas_object_event_callback_del_full(win->parent, EVAS_CALLBACK_DEL,
220                                             _elm_win_obj_callback_parent_del, win);
221         win->parent = NULL;
222      }
223    if (win->autodel_clear) *(win->autodel_clear) = -1;
224    _elm_win_list = eina_list_remove(_elm_win_list, win->win_obj);
225    while (win->subobjs) elm_win_resize_object_del(obj, win->subobjs->data);
226    ecore_evas_callback_delete_request_set(win->ee, NULL);
227    ecore_evas_callback_resize_set(win->ee, NULL);
228    if (win->deferred_resize_job) ecore_job_del(win->deferred_resize_job);
229    if (win->deferred_child_eval_job) ecore_job_del(win->deferred_child_eval_job);
230    while (((child = evas_object_bottom_get(win->evas))) &&
231           (child != obj))
232      {
233         evas_object_del(child);
234      }
235    while (((child = evas_object_top_get(win->evas))) &&
236           (child != obj))
237      {
238         evas_object_del(child);
239      }
240 #ifdef HAVE_ELEMENTARY_X
241    if (win->client_message_handler)
242      ecore_event_handler_del(win->client_message_handler);
243 #endif
244 // FIXME: Why are we flushing edje on every window destroy ??
245 //   edje_file_cache_flush();
246 //   edje_collection_cache_flush();
247 //   evas_image_cache_flush(win->evas);
248 //   evas_font_cache_flush(win->evas);
249 // FIXME: we are in the del handler for the object and delete the canvas
250 // that lives under it from the handler... nasty. deferring doesn't help either
251
252    ecore_job_add(_deferred_ecore_evas_free, win->ee);
253    _elm_win_deferred_free++;
254 //   ecore_evas_free(win->ee);
255
256    _elm_win_focus_highlight_shutdown(win);
257    eina_stringshare_del(win->focus_highlight.style);
258
259    free(win);
260
261    if ((!_elm_win_list) &&
262        (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_CLOSED))
263      {
264         edje_file_cache_flush();
265         edje_collection_cache_flush();
266         evas_image_cache_flush(e);
267         evas_font_cache_flush(e);
268         elm_exit();
269      }
270 }
271
272 static void
273 _elm_win_obj_callback_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
274 {
275    Elm_Win *win = data;
276    if (obj == win->parent) win->parent = NULL;
277 }
278
279 static void
280 _elm_win_obj_intercept_show(void *data __UNUSED__, Evas_Object *obj)
281 {
282    // this is called to make sure all smart containers have calculated their
283    // sizes BEFORE we show the window to make sure it initially appears at
284    // our desired size (ie min size is known first)
285    evas_smart_objects_calculate(evas_object_evas_get(obj));
286    evas_object_show(obj);
287 }
288
289 static void
290 _elm_win_delete_request(Ecore_Evas *ee)
291 {
292    Evas_Object *obj = ecore_evas_object_associate_get(ee);
293    Elm_Win *win;
294    if (strcmp(elm_widget_type_get(obj), "win")) return;
295
296    win = elm_widget_data_get(obj);
297    if (!win) return;
298    int autodel = win->autodel;
299    win->autodel_clear = &autodel;
300    evas_object_smart_callback_call(win->win_obj, "delete-request", NULL); // FIXME: remove me
301    evas_object_smart_callback_call(win->win_obj, "delete,request", NULL);
302    // FIXME: if above callback deletes - then the below will be invalid
303    if (autodel) evas_object_del(win->win_obj);
304    else win->autodel_clear = NULL;
305 }
306
307 static void
308 _elm_win_resize_job(void *data)
309 {
310    Elm_Win *win = data;
311    const Eina_List *l;
312    Evas_Object *obj;
313    int w, h;
314
315    win->deferred_resize_job = NULL;
316    ecore_evas_geometry_get(win->ee, NULL, NULL, &w, &h);
317    evas_object_resize(win->win_obj, w, h);
318    EINA_LIST_FOREACH(win->subobjs, l, obj)
319      {
320         evas_object_move(obj, 0, 0);
321         evas_object_resize(obj, w, h);
322      }
323 }
324
325 #ifdef HAVE_ELEMENTARY_X
326 static void
327 _elm_win_xwindow_get(Elm_Win *win)
328 {
329    win->xwin = 0;
330
331 #define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
332    if (ENGINE_COMPARE(ELM_SOFTWARE_X11))
333      {
334        if (win->ee) win->xwin = ecore_evas_software_x11_window_get(win->ee);
335      }
336    else if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
337             ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
338             ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE) ||
339             ENGINE_COMPARE(ELM_SOFTWARE_SDL) ||
340             ENGINE_COMPARE(ELM_SOFTWARE_16_SDL) ||
341             ENGINE_COMPARE(ELM_OPENGL_SDL))
342      {
343      }
344    else if (ENGINE_COMPARE(ELM_SOFTWARE_16_X11))
345      {
346         if (win->ee) win->xwin = ecore_evas_software_x11_16_window_get(win->ee);
347      }
348    else if (ENGINE_COMPARE(ELM_SOFTWARE_8_X11))
349      {
350         if (win->ee) win->xwin = ecore_evas_software_x11_8_window_get(win->ee);
351      }
352    else if (ENGINE_COMPARE(ELM_XRENDER_X11))
353      {
354         if (win->ee) win->xwin = ecore_evas_xrender_x11_window_get(win->ee);
355      }
356    else if (ENGINE_COMPARE(ELM_OPENGL_X11))
357      {
358         if (win->ee) win->xwin = ecore_evas_gl_x11_window_get(win->ee);
359      }
360    else if (ENGINE_COMPARE(ELM_SOFTWARE_WIN32))
361      {
362         if (win->ee) win->xwin = (long)ecore_evas_win32_window_get(win->ee);
363      }
364 #undef ENGINE_COMPARE
365 }
366 #endif
367
368 #ifdef HAVE_ELEMENTARY_X
369 static void
370 _elm_win_xwin_update(Elm_Win *win)
371 {
372    _elm_win_xwindow_get(win);
373    if (win->parent)
374      {
375         Elm_Win *win2;
376
377         win2 = elm_widget_data_get(win->parent);
378         if (win2)
379           {
380              if (win->xwin)
381                ecore_x_icccm_transient_for_set(win->xwin, win2->xwin);
382           }
383      }
384
385    if (!win->xwin) return; /* nothing more to do */
386
387    switch (win->type)
388      {
389       case ELM_WIN_BASIC:
390          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_NORMAL);
391          break;
392       case ELM_WIN_DIALOG_BASIC:
393          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DIALOG);
394          break;
395       case ELM_WIN_DESKTOP:
396          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DESKTOP);
397          break;
398       case ELM_WIN_DOCK:
399          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DOCK);
400          break;
401       case ELM_WIN_TOOLBAR:
402          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_TOOLBAR);
403          break;
404       case ELM_WIN_MENU:
405          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_MENU);
406          break;
407       case ELM_WIN_UTILITY:
408          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_UTILITY);
409          break;
410       case ELM_WIN_SPLASH:
411          ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_SPLASH);
412          break;
413       default:
414          break;
415      }
416    ecore_x_e_virtual_keyboard_state_set
417      (win->xwin, (Ecore_X_Virtual_Keyboard_State)win->kbdmode);
418 }
419 #endif
420
421 static void
422 _elm_win_eval_subobjs(Evas_Object *obj)
423 {
424    const Eina_List *l;
425    const Evas_Object *child;
426
427    Elm_Win *win = elm_widget_data_get(obj);
428    Evas_Coord w, h, minw = -1, minh = -1, maxw = -1, maxh = -1;
429    int xx = 1, xy = 1;
430    double wx, wy;
431
432    EINA_LIST_FOREACH(win->subobjs, l, child)
433      {
434         evas_object_size_hint_weight_get(child, &wx, &wy);
435         if (wx == 0.0) xx = 0;
436         if (wy == 0.0) xy = 0;
437
438         evas_object_size_hint_min_get(child, &w, &h);
439         if (w < 1) w = -1;
440         if (h < 1) h = -1;
441         if (w > minw) minw = w;
442         if (h > minh) minh = h;
443
444         evas_object_size_hint_max_get(child, &w, &h);
445         if (w < 1) w = -1;
446         if (h < 1) h = -1;
447         if (maxw == -1) maxw = w;
448         else if ((w > 0) && (w < maxw)) maxw = w;
449         if (maxh == -1) maxh = h;
450         else if ((h > 0) && (h < maxh)) maxh = h;
451      }
452    if (!xx) maxw = minw;
453    else maxw = 32767;
454    if (!xy) maxh = minh;
455    else maxh = 32767;
456    evas_object_size_hint_min_set(obj, minw, minh);
457    evas_object_size_hint_max_set(obj, maxw, maxh);
458    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
459    if (w < minw) w = minw;
460    if (h < minh) h = minh;
461    if ((maxw >= 0) && (w > maxw)) w = maxw;
462    if ((maxh >= 0) && (h > maxh)) h = maxh;
463    evas_object_resize(obj, w, h);
464 }
465
466 static void
467 _elm_win_subobj_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
468 {
469    Elm_Win *win = elm_widget_data_get(data);
470    win->subobjs = eina_list_remove(win->subobjs, obj);
471    _elm_win_eval_subobjs(win->win_obj);
472 }
473
474 static void
475 _elm_win_subobj_callback_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
476 {
477    _elm_win_eval_subobjs(data);
478 }
479
480 void
481 _elm_win_shutdown(void)
482 {
483    while (_elm_win_list)
484      evas_object_del(_elm_win_list->data);
485 }
486
487 void
488 _elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme)
489 {
490    const Eina_List *l;
491    Evas_Object *obj;
492
493    if (!use_theme)
494      {
495         EINA_LIST_FOREACH(_elm_win_list, l, obj)
496           elm_widget_theme(obj);
497      }
498    else
499      {
500         EINA_LIST_FOREACH(_elm_win_list, l, obj)
501           elm_widget_theme_specific(obj, th, EINA_FALSE);
502      }
503 }
504
505 #ifdef HAVE_ELEMENTARY_X
506 static Eina_Bool
507 _elm_win_client_message(void *data, int type __UNUSED__, void *event)
508 {
509    Elm_Win *win = data;
510    Ecore_X_Event_Client_Message *e = event;
511
512    if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
513    if (e->message_type == ECORE_X_ATOM_E_COMP_FLUSH)
514      {
515         if ((unsigned)e->data.l[0] == win->xwin)
516           {
517              Evas *evas = evas_object_evas_get(win->win_obj);
518              if (evas)
519                {
520                   edje_file_cache_flush();
521                   edje_collection_cache_flush();
522                   evas_image_cache_flush(evas);
523                   evas_font_cache_flush(evas);
524                }
525           }
526      }
527    else if (e->message_type == ECORE_X_ATOM_E_COMP_DUMP)
528      {
529         if ((unsigned)e->data.l[0] == win->xwin)
530           {
531              Evas *evas = evas_object_evas_get(win->win_obj);
532              if (evas)
533                {
534                   edje_file_cache_flush();
535                   edje_collection_cache_flush();
536                   evas_image_cache_flush(evas);
537                   evas_font_cache_flush(evas);
538                   evas_render_dump(evas);
539                }
540           }
541      }
542    return ECORE_CALLBACK_PASS_ON;
543 }
544 #endif
545
546 static void
547 _elm_win_focus_target_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
548 {
549    Elm_Win *win = data;
550
551    win->focus_highlight.geometry_changed = EINA_TRUE;
552    _elm_win_focus_highlight_reconfigure_job_start(win);
553 }
554
555 static void
556 _elm_win_focus_target_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
557 {
558    Elm_Win *win = data;
559
560    win->focus_highlight.geometry_changed = EINA_TRUE;
561    _elm_win_focus_highlight_reconfigure_job_start(win);
562 }
563
564 static void
565 _elm_win_focus_target_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
566 {
567    Elm_Win *win = data;
568
569    win->focus_highlight.cur.target = NULL;
570
571    _elm_win_focus_highlight_reconfigure_job_start(win);
572 }
573
574 static void
575 _elm_win_focus_target_callbacks_add(Elm_Win *win)
576 {
577    Evas_Object *obj = win->focus_highlight.cur.target;
578
579    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
580                                   _elm_win_focus_target_move, win);
581    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
582                                   _elm_win_focus_target_resize, win);
583    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
584                                   _elm_win_focus_target_del, win);
585 }
586
587 static void
588 _elm_win_focus_target_callbacks_del(Elm_Win *win)
589 {
590    Evas_Object *obj = win->focus_highlight.cur.target;
591
592    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
593                                        _elm_win_focus_target_move, win);
594    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
595                                        _elm_win_focus_target_resize, win);
596    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
597                                        _elm_win_focus_target_del, win);
598 }
599
600 static Evas_Object *
601 _elm_win_focus_target_get(Evas_Object *obj)
602 {
603    Evas_Object *o = obj;
604
605    do
606      {
607         if (elm_widget_is(o))
608           {
609              if (!elm_widget_highlight_ignore_get(o))
610                break;
611              o = elm_widget_parent_get(o);
612              if (!o)
613                o = evas_object_smart_parent_get(o);
614           }
615         else
616           {
617              o = elm_widget_parent_widget_get(o);
618              if (!o)
619                o = evas_object_smart_parent_get(o);
620           }
621      }
622    while (o);
623
624    return o;
625 }
626
627 static void
628 _elm_win_object_focus_in(void *data, Evas *e __UNUSED__, void *event_info)
629 {
630    Evas_Object *obj = event_info, *target;
631    Elm_Win *win = data;
632
633    if (win->focus_highlight.cur.target == obj)
634      return;
635
636    target = _elm_win_focus_target_get(obj);
637    win->focus_highlight.cur.target = target;
638    if (elm_widget_highlight_in_theme_get(target))
639      win->focus_highlight.cur.handled = EINA_TRUE;
640    else
641      _elm_win_focus_target_callbacks_add(win);
642
643    _elm_win_focus_highlight_reconfigure_job_start(win);
644 }
645
646 static void
647 _elm_win_object_focus_out(void *data, Evas *e __UNUSED__, void *event_info __UNUSED__)
648 {
649    Elm_Win *win = data;
650
651    if (!win->focus_highlight.cur.target)
652      return;
653
654    if (!win->focus_highlight.cur.handled)
655      _elm_win_focus_target_callbacks_del(win);
656    win->focus_highlight.cur.target = NULL;
657    win->focus_highlight.cur.handled = EINA_FALSE;
658
659    _elm_win_focus_highlight_reconfigure_job_start(win);
660 }
661
662 static void
663 _elm_win_focus_highlight_hide(void *data __UNUSED__, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
664 {
665    evas_object_hide(obj);
666 }
667
668 static void
669 _elm_win_focus_highlight_init(Elm_Win *win)
670 {
671    evas_event_callback_add(win->evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
672                            _elm_win_object_focus_in, win);
673    evas_event_callback_add(win->evas,
674                            EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
675                            _elm_win_object_focus_out, win);
676
677    win->focus_highlight.cur.target = evas_focus_get(win->evas);
678
679    win->focus_highlight.top = edje_object_add(win->evas);
680    win->focus_highlight.changed_theme = EINA_TRUE;
681    edje_object_signal_callback_add(win->focus_highlight.top,
682                                    "elm,action,focus,hide,end", "",
683                                    _elm_win_focus_highlight_hide, NULL);
684    edje_object_signal_callback_add(win->focus_highlight.top,
685                                    "elm,action,focus,anim,end", "",
686                                    _elm_win_focus_highlight_anim_end, win);
687    _elm_win_focus_highlight_reconfigure_job_start(win);
688 }
689
690 static void
691 _elm_win_focus_highlight_shutdown(Elm_Win *win)
692 {
693    _elm_win_focus_highlight_reconfigure_job_stop(win);
694    if (win->focus_highlight.cur.target)
695      {
696         _elm_win_focus_target_callbacks_del(win);
697         win->focus_highlight.cur.target = NULL;
698      }
699    if (win->focus_highlight.top)
700      {
701         evas_object_del(win->focus_highlight.top);
702         win->focus_highlight.top = NULL;
703      }
704
705      evas_event_callback_del_full(win->evas,
706                                   EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
707                                   _elm_win_object_focus_in, win);
708      evas_event_callback_del_full(win->evas,
709                                   EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
710                                   _elm_win_object_focus_out, win);
711 }
712
713 static void
714 _elm_win_focus_highlight_visible_set(Elm_Win *win, Eina_Bool visible)
715 {
716    Evas_Object *top;
717
718    top = win->focus_highlight.top;
719    if (visible)
720      {
721         if (top)
722           {
723              evas_object_show(top);
724              edje_object_signal_emit(top, "elm,action,focus,show", "elm");
725           }
726      }
727    else
728      {
729         if (top)
730           edje_object_signal_emit(top, "elm,action,focus,hide", "elm");
731      }
732 }
733
734 static void
735 _elm_win_focus_highlight_reconfigure_job(void *data)
736 {
737    _elm_win_focus_highlight_reconfigure((Elm_Win *)data);
738 }
739
740 static void
741 _elm_win_focus_highlight_reconfigure_job_start(Elm_Win *win)
742 {
743    if (win->focus_highlight.reconf_job)
744      ecore_job_del(win->focus_highlight.reconf_job);
745    win->focus_highlight.reconf_job = ecore_job_add(
746       _elm_win_focus_highlight_reconfigure_job, win);
747 }
748
749 static void
750 _elm_win_focus_highlight_reconfigure_job_stop(Elm_Win *win)
751 {
752    if (win->focus_highlight.reconf_job)
753      ecore_job_del(win->focus_highlight.reconf_job);
754    win->focus_highlight.reconf_job = NULL;
755 }
756
757 static void
758 _elm_win_focus_highlight_simple_setup(Elm_Win *win, Evas_Object *obj)
759 {
760    Evas_Object *clip, *target = win->focus_highlight.cur.target;
761    Evas_Coord x, y, w, h;
762
763    clip = evas_object_clip_get(target);
764    evas_object_geometry_get(target, &x, &y, &w, &h);
765
766    evas_object_move(obj, x, y);
767    evas_object_resize(obj, w, h);
768    evas_object_clip_set(obj, clip);
769 }
770
771 static void
772 _elm_win_focus_highlight_anim_setup(Elm_Win *win, Evas_Object *obj)
773 {
774    Evas_Coord tx, ty, tw, th;
775    Evas_Coord w, h, px, py, pw, ph;
776    Edje_Message_Int_Set *m;
777    Evas_Object *previous = win->focus_highlight.prev.target;
778    Evas_Object *target = win->focus_highlight.cur.target;
779
780    evas_object_geometry_get(win->win_obj, NULL, NULL, &w, &h);
781    evas_object_geometry_get(target, &tx, &ty, &tw, &th);
782    evas_object_geometry_get(previous, &px, &py, &pw, &ph);
783    evas_object_move(obj, 0, 0);
784    evas_object_resize(obj, tw, th);
785    evas_object_clip_unset(obj);
786
787    m = alloca(sizeof(*m) + (sizeof(int) * 8));
788    m->count = 8;
789    m->val[0] = px;
790    m->val[1] = py;
791    m->val[2] = pw;
792    m->val[3] = ph;
793    m->val[4] = tx;
794    m->val[5] = ty;
795    m->val[6] = tw;
796    m->val[7] = th;
797    edje_object_message_send(obj, EDJE_MESSAGE_INT_SET, 1, m);
798 }
799
800 static void
801 _elm_win_focus_highlight_anim_end(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
802 {
803    Elm_Win *win = data;
804    _elm_win_focus_highlight_simple_setup(win, obj);
805 }
806
807 static void
808 _elm_win_focus_highlight_reconfigure(Elm_Win *win)
809 {
810    Evas_Object *target = win->focus_highlight.cur.target;
811    Evas_Object *previous = win->focus_highlight.prev.target;
812    Evas_Object *top = win->focus_highlight.top;
813    Eina_Bool visible_changed;
814    Eina_Bool common_visible;
815    const char *sig = NULL;
816
817    _elm_win_focus_highlight_reconfigure_job_stop(win);
818
819    visible_changed = (win->focus_highlight.cur.visible !=
820                       win->focus_highlight.prev.visible);
821
822    if ((target == previous) && (!visible_changed) &&
823        (!win->focus_highlight.geometry_changed))
824      return;
825
826    if ((previous) && (win->focus_highlight.prev.handled))
827      elm_widget_signal_emit(previous, "elm,action,focus_highlight,hide", "elm");
828
829    if (!target)
830      common_visible = EINA_FALSE;
831    else if (win->focus_highlight.cur.handled)
832      {
833         common_visible = EINA_FALSE;
834         if (win->focus_highlight.cur.visible)
835           sig = "elm,action,focus_highlight,show";
836         else
837           sig = "elm,action,focus_highlight,hide";
838      }
839    else
840      common_visible = win->focus_highlight.cur.visible;
841
842    _elm_win_focus_highlight_visible_set(win, common_visible);
843    if (sig)
844      elm_widget_signal_emit(target, sig, "elm");
845
846    if ((!target) || (!common_visible) || (win->focus_highlight.cur.handled))
847      goto the_end;
848
849    if (win->focus_highlight.changed_theme)
850      {
851         const char *str;
852         if (win->focus_highlight.style)
853           str = win->focus_highlight.style;
854         else
855           str = "default";
856         _elm_theme_object_set(win->win_obj, top, "focus_highlight", "top",
857                               str);
858         win->focus_highlight.changed_theme = EINA_FALSE;
859
860         if (_elm_config->focus_highlight_animate)
861           {
862              str = edje_object_data_get(win->focus_highlight.top, "animate");
863              win->focus_highlight.top_animate = ((str) && (!strcmp(str, "on")));
864           }
865      }
866
867    if ((win->focus_highlight.top_animate) && (previous) &&
868        (!win->focus_highlight.prev.handled))
869      _elm_win_focus_highlight_anim_setup(win, top);
870    else
871      _elm_win_focus_highlight_simple_setup(win, top);
872    evas_object_raise(top);
873
874 the_end:
875    win->focus_highlight.geometry_changed = EINA_FALSE;
876    win->focus_highlight.prev = win->focus_highlight.cur;
877 }
878
879 #ifdef ELM_DEBUG
880 static void
881 _debug_key_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
882 {
883    Evas_Event_Key_Down *ev = event_info;
884
885    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
886       return;
887
888
889    if ((strcmp(ev->keyname, "F12")) ||
890        (!evas_key_modifier_is_set(ev->modifiers, "Control")))
891      return;
892
893    printf("Tree graph generated.\n");
894    elm_object_tree_dot_dump(obj, "./dump.dot");
895 }
896 #endif
897
898 /**
899  * Adds a window object. If this is the first window created, pass NULL as
900  * @p parent.
901  *
902  * @param parent Parent object to add the window to, or NULL
903  * @param name The name of the window
904  * @param type The window type, one of the following:
905  * ELM_WIN_BASIC
906  * ELM_WIN_DIALOG_BASIC
907  * ELM_WIN_DESKTOP
908  * ELM_WIN_DOCK
909  * ELM_WIN_TOOLBAR
910  * ELM_WIN_MENU
911  * ELM_WIN_UTILITY
912  * ELM_WIN_SPLASH
913  *
914  * @return The created object, or NULL on failure
915  *
916  * @ingroup Win
917  */
918 EAPI Evas_Object *
919 elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type)
920 {
921    Elm_Win *win;
922    const Eina_List *l;
923    const char *fontpath;
924
925    win = ELM_NEW(Elm_Win);
926
927 #define FALLBACK_TRY(engine)                                            \
928    if (!win->ee)                                                        \
929      do {                                                               \
930        CRITICAL(engine " engine creation failed. Trying software X11."); \
931        win->ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 1, 1);      \
932      } while (0)
933
934 #define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
935    if (ENGINE_COMPARE(ELM_SOFTWARE_X11))
936      {
937         win->ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 1, 1);
938 #ifdef HAVE_ELEMENTARY_X
939         win->client_message_handler = ecore_event_handler_add
940           (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
941 #endif
942      }
943    else if (ENGINE_COMPARE(ELM_SOFTWARE_FB))
944      {
945         win->ee = ecore_evas_fb_new(NULL, 0, 1, 1);
946         FALLBACK_TRY("Sofware FB");
947      }
948    else if (ENGINE_COMPARE(ELM_SOFTWARE_DIRECTFB))
949      {
950         win->ee = ecore_evas_directfb_new(NULL, 1, 0, 0, 1, 1);
951         FALLBACK_TRY("Sofware DirectFB");
952      }
953    else if (ENGINE_COMPARE(ELM_SOFTWARE_16_X11))
954      {
955         win->ee = ecore_evas_software_x11_16_new(NULL, 0, 0, 0, 1, 1);
956         FALLBACK_TRY("Sofware-16");
957 #ifdef HAVE_ELEMENTARY_X
958         win->client_message_handler = ecore_event_handler_add
959           (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
960 #endif
961      }
962    else if (ENGINE_COMPARE(ELM_SOFTWARE_8_X11))
963      {
964         win->ee = ecore_evas_software_x11_8_new(NULL, 0, 0, 0, 1, 1);
965         FALLBACK_TRY("Sofware-8");
966 #ifdef HAVE_ELEMENTARY_X
967         win->client_message_handler = ecore_event_handler_add
968           (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
969 #endif
970      }
971    else if (ENGINE_COMPARE(ELM_XRENDER_X11))
972      {
973         win->ee = ecore_evas_xrender_x11_new(NULL, 0, 0, 0, 1, 1);
974         FALLBACK_TRY("XRender");
975 #ifdef HAVE_ELEMENTARY_X
976         win->client_message_handler = ecore_event_handler_add
977           (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
978 #endif
979      }
980    else if (ENGINE_COMPARE(ELM_OPENGL_X11))
981      {
982         win->ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, 1, 1);
983         FALLBACK_TRY("OpenGL");
984 #ifdef HAVE_ELEMENTARY_X
985         win->client_message_handler = ecore_event_handler_add
986           (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
987 #endif
988      }
989    else if (ENGINE_COMPARE(ELM_SOFTWARE_WIN32))
990      {
991         win->ee = ecore_evas_software_gdi_new(NULL, 0, 0, 1, 1);
992         FALLBACK_TRY("Sofware Win32");
993      }
994    else if (ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
995      {
996         win->ee = ecore_evas_software_wince_gdi_new(NULL, 0, 0, 1, 1);
997         FALLBACK_TRY("Sofware-16-WinCE");
998      }
999    else if (ENGINE_COMPARE(ELM_SOFTWARE_SDL))
1000      {
1001         win->ee = ecore_evas_sdl_new(NULL, 0, 0, 0, 0, 0, 1);
1002         FALLBACK_TRY("Sofware SDL");
1003      }
1004    else if (ENGINE_COMPARE(ELM_SOFTWARE_16_SDL))
1005      {
1006         win->ee = ecore_evas_sdl16_new(NULL, 0, 0, 0, 0, 0, 1);
1007         FALLBACK_TRY("Sofware-16-SDL");
1008      }
1009    else if (ENGINE_COMPARE(ELM_OPENGL_SDL))
1010      {
1011         win->ee = ecore_evas_gl_sdl_new(NULL, 1, 1, 0, 0);
1012         FALLBACK_TRY("OpenGL SDL");
1013      }
1014 #undef FALLBACK_TRY
1015
1016    if (!win->ee)
1017      {
1018         ERR("Cannot create window.");
1019         free(win);
1020         return NULL;
1021      }
1022 #ifdef HAVE_ELEMENTARY_X
1023    _elm_win_xwindow_get(win);
1024 #endif
1025    if ((_elm_config->bgpixmap) && (!_elm_config->compositing))
1026      ecore_evas_avoid_damage_set(win->ee, ECORE_EVAS_AVOID_DAMAGE_EXPOSE);
1027 // bg pixmap done by x - has other issues like can be redrawn by x before it
1028 // is filled/ready by app
1029 //     ecore_evas_avoid_damage_set(win->ee, ECORE_EVAS_AVOID_DAMAGE_BUILT_IN);
1030
1031    win->type = type;
1032    win->parent = parent;
1033    if (win->parent)
1034      evas_object_event_callback_add(win->parent, EVAS_CALLBACK_DEL,
1035                                     _elm_win_obj_callback_parent_del, win);
1036
1037    win->evas = ecore_evas_get(win->ee);
1038    win->win_obj = elm_widget_add(win->evas);
1039    elm_widget_type_set(win->win_obj, "win");
1040    ELM_SET_WIDTYPE(widtype, "win");
1041    elm_widget_data_set(win->win_obj, win);
1042    elm_widget_event_hook_set(win->win_obj, _elm_win_event_cb);
1043    elm_widget_on_focus_hook_set(win->win_obj, _elm_win_on_focus_hook, NULL);
1044    elm_widget_can_focus_set(win->win_obj, EINA_TRUE);
1045    elm_widget_highlight_ignore_set(win->win_obj, EINA_TRUE);
1046    elm_widget_focus_next_hook_set(win->win_obj, _elm_win_focus_next_hook);
1047    evas_object_color_set(win->win_obj, 0, 0, 0, 0);
1048    evas_object_move(win->win_obj, 0, 0);
1049    evas_object_resize(win->win_obj, 1, 1);
1050    evas_object_layer_set(win->win_obj, 50);
1051    evas_object_pass_events_set(win->win_obj, EINA_TRUE);
1052
1053    evas_object_intercept_show_callback_add(win->win_obj,
1054                                            _elm_win_obj_intercept_show, win);
1055    ecore_evas_object_associate(win->ee, win->win_obj,
1056                                ECORE_EVAS_OBJECT_ASSOCIATE_BASE |
1057                                ECORE_EVAS_OBJECT_ASSOCIATE_STACK |
1058                                ECORE_EVAS_OBJECT_ASSOCIATE_LAYER);
1059    evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_SHOW,
1060                                   _elm_win_obj_callback_show, win);
1061    evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_DEL,
1062                                   _elm_win_obj_callback_del, win);
1063
1064    ecore_evas_name_class_set(win->ee, name, _elm_appname);
1065    ecore_evas_callback_delete_request_set(win->ee, _elm_win_delete_request);
1066    ecore_evas_callback_resize_set(win->ee, _elm_win_resize);
1067    ecore_evas_callback_focus_in_set(win->ee, _elm_win_focus_in);
1068    ecore_evas_callback_focus_out_set(win->ee, _elm_win_focus_out);
1069    ecore_evas_callback_move_set(win->ee, _elm_win_move);
1070    evas_image_cache_set(win->evas, (_elm_config->image_cache * 1024));
1071    evas_font_cache_set(win->evas, (_elm_config->font_cache * 1024));
1072    EINA_LIST_FOREACH(_elm_config->font_dirs, l, fontpath)
1073      evas_font_path_append(win->evas, fontpath);
1074    if (!_elm_config->font_hinting)
1075      evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_NONE);
1076    else if (_elm_config->font_hinting == 1)
1077      evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_AUTO);
1078    else if (_elm_config->font_hinting == 2)
1079      evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_BYTECODE);
1080
1081 #ifdef HAVE_ELEMENTARY_X
1082    _elm_win_xwin_update(win);
1083 #endif
1084
1085    _elm_win_list = eina_list_append(_elm_win_list, win->win_obj);
1086
1087    if (ENGINE_COMPARE(ELM_SOFTWARE_FB))
1088      {
1089         ecore_evas_fullscreen_set(win->ee, 1);
1090      }
1091 #undef ENGINE_COMPARE
1092
1093    if (_elm_config->focus_highlight_enable)
1094      elm_win_focus_highlight_enabled_set(win->win_obj, EINA_TRUE);
1095
1096 #ifdef ELM_DEBUG
1097    Evas_Modifier_Mask mask = evas_key_modifier_mask_get(win->evas, "Control");
1098    evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_KEY_DOWN,
1099                                   _debug_key_down, win);
1100    Eina_Bool ret = evas_object_key_grab(win->win_obj, "F12", mask, 0, EINA_TRUE);
1101    printf("Key F12 exclusive for dot tree generation. (%d)\n", ret);
1102 #endif
1103    return win->win_obj;
1104 }
1105
1106 /**
1107  * Add @p subobj as a resize object of window @p obj.
1108  *
1109  * @param obj The window object
1110  * @param subobj The resize object to add
1111  *
1112  * @ingroup Win
1113  */
1114 EAPI void
1115 elm_win_resize_object_add(Evas_Object *obj, Evas_Object *subobj)
1116 {
1117    Evas_Coord w, h;
1118    Elm_Win *win;
1119    ELM_CHECK_WIDTYPE(obj, widtype);
1120    win = elm_widget_data_get(obj);
1121    if (!win) return;
1122    win->subobjs = eina_list_append(win->subobjs, subobj);
1123    elm_widget_sub_object_add(obj, subobj);
1124    evas_object_event_callback_add(subobj, EVAS_CALLBACK_DEL,
1125                                   _elm_win_subobj_callback_del, obj);
1126    evas_object_event_callback_add(subobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1127                                   _elm_win_subobj_callback_changed_size_hints,
1128                                   obj);
1129    ecore_evas_geometry_get(win->ee, NULL, NULL, &w, &h);
1130    evas_object_move(subobj, 0, 0);
1131    evas_object_resize(subobj, w, h);
1132    _elm_win_eval_subobjs(obj);
1133 }
1134
1135 /**
1136  * Delete @p subobj as a resize object of window @p obj.
1137  *
1138  * @param obj The window object
1139  * @param subobj The resize object to add
1140  *
1141  * @ingroup Win
1142  */
1143 EAPI void
1144 elm_win_resize_object_del(Evas_Object *obj, Evas_Object *subobj)
1145 {
1146    Elm_Win *win;
1147    ELM_CHECK_WIDTYPE(obj, widtype);
1148    win = elm_widget_data_get(obj);
1149    if (!win) return;
1150    evas_object_event_callback_del_full(subobj,
1151                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1152                                        _elm_win_subobj_callback_changed_size_hints,
1153                                        obj);
1154    evas_object_event_callback_del_full(subobj, EVAS_CALLBACK_DEL,
1155                                        _elm_win_subobj_callback_del, obj);
1156    win->subobjs = eina_list_remove(win->subobjs, subobj);
1157    elm_widget_sub_object_del(obj, subobj);
1158    _elm_win_eval_subobjs(obj);
1159 }
1160
1161 /**
1162  * Set the title of the window
1163  *
1164  * @param obj The window object
1165  * @param title The title to set
1166  *
1167  * @ingroup Win
1168  */
1169 EAPI void
1170 elm_win_title_set(Evas_Object *obj, const char *title)
1171 {
1172    Elm_Win *win;
1173    ELM_CHECK_WIDTYPE(obj, widtype);
1174    win = elm_widget_data_get(obj);
1175    if (!win) return;
1176    ecore_evas_title_set(win->ee, title);
1177 }
1178
1179 /**
1180  * Get the title of the window
1181  *
1182  * @param obj The window object
1183  * @return The title
1184  *
1185  * @ingroup Win
1186  */
1187 EAPI const char *
1188 elm_win_title_get(const Evas_Object *obj)
1189 {
1190    Elm_Win *win;
1191    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1192    win = elm_widget_data_get(obj);
1193    if (!win) return NULL;
1194    return ecore_evas_title_get(win->ee);
1195 }
1196
1197 /**
1198  * Set the window's autodel state.
1199  *
1200  * @param obj The window object
1201  * @param autodel If true, the window will automatically delete itself when closed
1202  *
1203  * @ingroup Win
1204  */
1205 EAPI void
1206 elm_win_autodel_set(Evas_Object *obj, Eina_Bool autodel)
1207 {
1208    Elm_Win *win;
1209    ELM_CHECK_WIDTYPE(obj, widtype);
1210    win = elm_widget_data_get(obj);
1211    if (!win) return;
1212    win->autodel = autodel;
1213 }
1214
1215 /**
1216  * Get the window's autodel state.
1217  *
1218  * @param obj The window object
1219  * @return If the window will automatically delete itself when closed
1220  *
1221  * @ingroup Win
1222  */
1223 EAPI Eina_Bool
1224 elm_win_autodel_get(const Evas_Object *obj)
1225 {
1226    Elm_Win *win;
1227    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1228    win = elm_widget_data_get(obj);
1229    if (!win) return EINA_FALSE;
1230    return win->autodel;
1231 }
1232
1233 /**
1234  * Activate a window object.
1235  *
1236  * @param obj The window object
1237  *
1238  * @ingroup Win
1239  */
1240 EAPI void
1241 elm_win_activate(Evas_Object *obj)
1242 {
1243    Elm_Win *win;
1244    ELM_CHECK_WIDTYPE(obj, widtype);
1245    win = elm_widget_data_get(obj);
1246    if (!win) return;
1247    ecore_evas_activate(win->ee);
1248 }
1249
1250 /**
1251  * Lower a window object.
1252  *
1253  * @param obj The window object
1254  *
1255  * @ingroup Win
1256  */
1257 EAPI void
1258 elm_win_lower(Evas_Object *obj)
1259 {
1260    Elm_Win *win;
1261    ELM_CHECK_WIDTYPE(obj, widtype);
1262    win = elm_widget_data_get(obj);
1263    if (!win) return;
1264    ecore_evas_lower(win->ee);
1265 }
1266
1267 /**
1268  * Raise a window object.
1269  *
1270  * @param obj The window object
1271  *
1272  * @ingroup Win
1273  */
1274 EAPI void
1275 elm_win_raise(Evas_Object *obj)
1276 {
1277    Elm_Win *win;
1278    ELM_CHECK_WIDTYPE(obj, widtype);
1279    win = elm_widget_data_get(obj);
1280    if (!win) return;
1281    ecore_evas_raise(win->ee);
1282 }
1283
1284 /**
1285  * Set the borderless state of a window.
1286  *
1287  * @param obj The window object
1288  * @param borderless If true, the window is borderless
1289  *
1290  * @ingroup Win
1291  */
1292 EAPI void
1293 elm_win_borderless_set(Evas_Object *obj, Eina_Bool borderless)
1294 {
1295    Elm_Win *win;
1296    ELM_CHECK_WIDTYPE(obj, widtype);
1297    win = elm_widget_data_get(obj);
1298    if (!win) return;
1299    ecore_evas_borderless_set(win->ee, borderless);
1300 #ifdef HAVE_ELEMENTARY_X
1301    _elm_win_xwin_update(win);
1302 #endif
1303 }
1304
1305 /**
1306  * Get the borderless state of a window.
1307  *
1308  * @param obj The window object
1309  * @return If true, the window is borderless
1310  *
1311  * @ingroup Win
1312  */
1313 EAPI Eina_Bool
1314 elm_win_borderless_get(const Evas_Object *obj)
1315 {
1316    Elm_Win *win;
1317    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1318    win = elm_widget_data_get(obj);
1319    if (!win) return EINA_FALSE;
1320    return ecore_evas_borderless_get(win->ee);
1321 }
1322
1323 /**
1324  * Set the shaped state of a window.
1325  *
1326  * @param obj The window object
1327  * @param shaped If true, the window is shaped
1328  *
1329  * @ingroup Win
1330  */
1331 EAPI void
1332 elm_win_shaped_set(Evas_Object *obj, Eina_Bool shaped)
1333 {
1334    Elm_Win *win;
1335    ELM_CHECK_WIDTYPE(obj, widtype);
1336    win = elm_widget_data_get(obj);
1337    if (!win) return;
1338    ecore_evas_shaped_set(win->ee, shaped);
1339 #ifdef HAVE_ELEMENTARY_X
1340    _elm_win_xwin_update(win);
1341 #endif
1342 }
1343
1344 /**
1345  * Get the shaped state of a window.
1346  *
1347  * @param obj The window object
1348  * @return If true, the window is shaped
1349  *
1350  * @ingroup Win
1351  */
1352 EAPI Eina_Bool
1353 elm_win_shaped_get(const Evas_Object *obj)
1354 {
1355    Elm_Win *win;
1356    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1357    win = elm_widget_data_get(obj);
1358    if (!win) return EINA_FALSE;
1359    return ecore_evas_shaped_get(win->ee);
1360 }
1361
1362 /**
1363  * Set the alpha channel state of a window.
1364  *
1365  * @param obj The window object
1366  * @param alpha If true, the window has an alpha channel
1367  *
1368  * @ingroup Win
1369  */
1370 EAPI void
1371 elm_win_alpha_set(Evas_Object *obj, Eina_Bool alpha)
1372 {
1373    Elm_Win *win;
1374    ELM_CHECK_WIDTYPE(obj, widtype);
1375    win = elm_widget_data_get(obj);
1376    if (!win) return;
1377 #ifdef HAVE_ELEMENTARY_X
1378    if (win->xwin)
1379      {
1380         if (alpha)
1381           {
1382              if (!_elm_config->compositing)
1383                elm_win_shaped_set(obj, alpha);
1384              else
1385                ecore_evas_alpha_set(win->ee, alpha);
1386           }
1387         else
1388           ecore_evas_alpha_set(win->ee, alpha);
1389         _elm_win_xwin_update(win);
1390      }
1391    else
1392 #endif
1393      ecore_evas_alpha_set(win->ee, alpha);
1394 }
1395
1396 /**
1397  * Get the alpha channel state of a window.
1398  *
1399  * @param obj The window object
1400  * @return If true, the window has an alpha channel
1401  *
1402  * @ingroup Win
1403  */
1404 EAPI Eina_Bool
1405 elm_win_alpha_get(const Evas_Object *obj)
1406 {
1407    Elm_Win *win;
1408    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1409    win = elm_widget_data_get(obj);
1410    if (!win) return EINA_FALSE;
1411    return ecore_evas_alpha_get(win->ee);
1412 }
1413
1414 /**
1415  * Set the transparency state of a window.
1416  *
1417  * @param obj The window object
1418  * @param transparent If true, the window is transparent
1419  *
1420  * @ingroup Win
1421  */
1422 EAPI void
1423 elm_win_transparent_set(Evas_Object *obj, Eina_Bool transparent)
1424 {
1425    Elm_Win *win;
1426    ELM_CHECK_WIDTYPE(obj, widtype);
1427    win = elm_widget_data_get(obj);
1428    if (!win) return;
1429
1430 #ifdef HAVE_ELEMENTARY_X
1431    if (win->xwin)
1432      {
1433        ecore_evas_transparent_set(win->ee, transparent);
1434         _elm_win_xwin_update(win);
1435      }
1436    else
1437 #endif
1438      ecore_evas_transparent_set(win->ee, transparent);
1439 }
1440
1441 /**
1442  * Get the transparency state of a window.
1443  *
1444  * @param obj The window object
1445  * @return If true, the window is transparent
1446  *
1447  * @ingroup Win
1448  */
1449 EAPI Eina_Bool
1450 elm_win_transparent_get(const Evas_Object *obj)
1451 {
1452    Elm_Win *win;
1453    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1454    win = elm_widget_data_get(obj);
1455    if (!win) return EINA_FALSE;
1456
1457    return ecore_evas_transparent_get(win->ee);
1458 }
1459
1460 /**
1461  * Set the override state of a window.
1462  *
1463  * @param obj The window object
1464  * @param override If true, the window is overridden
1465  *
1466  * @ingroup Win
1467  */
1468 EAPI void
1469 elm_win_override_set(Evas_Object *obj, Eina_Bool override)
1470 {
1471    Elm_Win *win;
1472    ELM_CHECK_WIDTYPE(obj, widtype);
1473    win = elm_widget_data_get(obj);
1474    if (!win) return;
1475    ecore_evas_override_set(win->ee, override);
1476 #ifdef HAVE_ELEMENTARY_X
1477    _elm_win_xwin_update(win);
1478 #endif
1479 }
1480
1481 /**
1482  * Get the override state of a window.
1483  *
1484  * @param obj The window object
1485  * @return If true, the window is overridden
1486  *
1487  * @ingroup Win
1488  */
1489 EAPI Eina_Bool
1490 elm_win_override_get(const Evas_Object *obj)
1491 {
1492    Elm_Win *win;
1493    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1494    win = elm_widget_data_get(obj);
1495    if (!win) return EINA_FALSE;
1496    return ecore_evas_override_get(win->ee);
1497 }
1498
1499 /**
1500  * Set the fullscreen state of a window.
1501  *
1502  * @param obj The window object
1503  * @param fullscreen If true, the window is fullscreen
1504  *
1505  * @ingroup Win
1506  */
1507 EAPI void
1508 elm_win_fullscreen_set(Evas_Object *obj, Eina_Bool fullscreen)
1509 {
1510    Elm_Win *win;
1511    ELM_CHECK_WIDTYPE(obj, widtype);
1512    win = elm_widget_data_get(obj);
1513    if (!win) return;
1514
1515 #define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
1516    if (ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
1517        ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
1518      {
1519         // these engines... can ONLY be fullscreen
1520         return;
1521      }
1522    else
1523      {
1524         ecore_evas_fullscreen_set(win->ee, fullscreen);
1525 #ifdef HAVE_ELEMENTARY_X
1526         _elm_win_xwin_update(win);
1527 #endif
1528      }
1529 #undef ENGINE_COMPARE
1530 }
1531
1532 /**
1533  * Get the fullscreen state of a window.
1534  *
1535  * @param obj The window object
1536  * @return If true, the window is fullscreen
1537  *
1538  * @ingroup Win
1539  */
1540 EAPI Eina_Bool
1541 elm_win_fullscreen_get(const Evas_Object *obj)
1542 {
1543    Elm_Win *win;
1544    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1545    win = elm_widget_data_get(obj);
1546    if (!win) return EINA_FALSE;
1547
1548 #define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
1549    if (ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
1550        ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
1551      {
1552         // these engines... can ONLY be fullscreen
1553         return EINA_TRUE;
1554      }
1555    else
1556      {
1557         return ecore_evas_fullscreen_get(win->ee);
1558      }
1559 #undef ENGINE_COMPARE
1560 }
1561
1562 /**
1563  * Set the maximized state of a window.
1564  *
1565  * @param obj The window object
1566  * @param maximized If true, the window is maximized
1567  *
1568  * @ingroup Win
1569  */
1570 EAPI void
1571 elm_win_maximized_set(Evas_Object *obj, Eina_Bool maximized)
1572 {
1573    Elm_Win *win;
1574    ELM_CHECK_WIDTYPE(obj, widtype);
1575    win = elm_widget_data_get(obj);
1576    if (!win) return;
1577    ecore_evas_maximized_set(win->ee, maximized);
1578 #ifdef HAVE_ELEMENTARY_X
1579    _elm_win_xwin_update(win);
1580 #endif
1581 }
1582
1583 /**
1584  * Get the maximized state of a window.
1585  *
1586  * @param obj The window object
1587  * @return If true, the window is maximized
1588  *
1589  * @ingroup Win
1590  */
1591 EAPI Eina_Bool
1592 elm_win_maximized_get(const Evas_Object *obj)
1593 {
1594    Elm_Win *win;
1595    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1596    win = elm_widget_data_get(obj);
1597    if (!win) return EINA_FALSE;
1598    return ecore_evas_maximized_get(win->ee);
1599 }
1600
1601 /**
1602  * Set the iconified state of a window.
1603  *
1604  * @param obj The window object
1605  * @param iconified If true, the window is iconified
1606  *
1607  * @ingroup Win
1608  */
1609 EAPI void
1610 elm_win_iconified_set(Evas_Object *obj, Eina_Bool iconified)
1611 {
1612    Elm_Win *win;
1613    ELM_CHECK_WIDTYPE(obj, widtype);
1614    win = elm_widget_data_get(obj);
1615    if (!win) return;
1616    ecore_evas_iconified_set(win->ee, iconified);
1617 #ifdef HAVE_ELEMENTARY_X
1618    _elm_win_xwin_update(win);
1619 #endif
1620 }
1621
1622 /**
1623  * Get the iconified state of a window.
1624  *
1625  * @param obj The window object
1626  * @return If true, the window is iconified
1627  *
1628  * @ingroup Win
1629  */
1630 EAPI Eina_Bool
1631 elm_win_iconified_get(const Evas_Object *obj)
1632 {
1633    Elm_Win *win;
1634    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1635    win = elm_widget_data_get(obj);
1636    if (!win) return EINA_FALSE;
1637    return ecore_evas_iconified_get(win->ee);
1638 }
1639
1640 /**
1641  * Set the layer of the window.
1642  *
1643  * @param obj The window object
1644  * @param layer The layer of the window
1645  *
1646  * @ingroup Win
1647  */
1648 EAPI void
1649 elm_win_layer_set(Evas_Object *obj, int layer)
1650 {
1651    Elm_Win *win;
1652    ELM_CHECK_WIDTYPE(obj, widtype);
1653    win = elm_widget_data_get(obj);
1654    if (!win) return;
1655    ecore_evas_layer_set(win->ee, layer);
1656 #ifdef HAVE_ELEMENTARY_X
1657    _elm_win_xwin_update(win);
1658 #endif
1659 }
1660
1661 /**
1662  * Get the layer of the window.
1663  *
1664  * @param obj The window object
1665  * @return The layer of the window
1666  *
1667  * @ingroup Win
1668  */
1669 EAPI int
1670 elm_win_layer_get(const Evas_Object *obj)
1671 {
1672    Elm_Win *win;
1673    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1674    win = elm_widget_data_get(obj);
1675    if (!win) return -1;
1676    return ecore_evas_layer_get(win->ee);
1677 }
1678
1679 /**
1680  * Set the rotation of the window.
1681  *
1682  * @param obj The window object
1683  * @param rotation The rotation of the window, in degrees (0-360)
1684  *
1685  * @ingroup Win
1686  */
1687 EAPI void
1688 elm_win_rotation_set(Evas_Object *obj, int rotation)
1689 {
1690    Elm_Win *win;
1691    ELM_CHECK_WIDTYPE(obj, widtype);
1692    win = elm_widget_data_get(obj);
1693    if (!win) return;
1694    if (win->rot == rotation) return;
1695    win->rot = rotation;
1696    ecore_evas_rotation_set(win->ee, rotation);
1697    evas_object_size_hint_min_set(obj, -1, -1);
1698    evas_object_size_hint_max_set(obj, -1, -1);
1699    _elm_win_eval_subobjs(obj);
1700 #ifdef HAVE_ELEMENTARY_X
1701    _elm_win_xwin_update(win);
1702 #endif
1703 }
1704
1705 /**
1706  * Rotates the window and resizes it
1707  *
1708  * @param obj The window object
1709  * @param layer The rotation of the window in degrees (0-360)
1710  *
1711  * @ingroup Win
1712  */
1713 EAPI void
1714 elm_win_rotation_with_resize_set(Evas_Object *obj, int rotation)
1715 {
1716    Elm_Win *win;
1717    ELM_CHECK_WIDTYPE(obj, widtype);
1718    win = elm_widget_data_get(obj);
1719    if (!win) return;
1720    if (win->rot == rotation) return;
1721    win->rot = rotation;
1722    ecore_evas_rotation_with_resize_set(win->ee, rotation);
1723    evas_object_size_hint_min_set(obj, -1, -1);
1724    evas_object_size_hint_max_set(obj, -1, -1);
1725    _elm_win_eval_subobjs(obj);
1726 #ifdef HAVE_ELEMENTARY_X
1727    _elm_win_xwin_update(win);
1728 #endif
1729 }
1730
1731 /**
1732  * Get the rotation of the window.
1733  *
1734  * @param obj The window object
1735  * @return The rotation of the window in degrees (0-360)
1736  *
1737  * @ingroup Win
1738  */
1739 EAPI int
1740 elm_win_rotation_get(const Evas_Object *obj)
1741 {
1742    Elm_Win *win;
1743    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1744    win = elm_widget_data_get(obj);
1745    if (!win) return -1;
1746    return win->rot;
1747 }
1748
1749 /**
1750  * Set the sticky state of the window.
1751  *
1752  * @param obj The window object
1753  * @param sticky If true, the window's sticky state is enabled
1754  *
1755  * @ingroup Win
1756  */
1757 EAPI void
1758 elm_win_sticky_set(Evas_Object *obj, Eina_Bool sticky)
1759 {
1760    Elm_Win *win;
1761    ELM_CHECK_WIDTYPE(obj, widtype);
1762    win = elm_widget_data_get(obj);
1763    if (!win) return;
1764    ecore_evas_sticky_set(win->ee, sticky);
1765 #ifdef HAVE_ELEMENTARY_X
1766    _elm_win_xwin_update(win);
1767 #endif
1768 }
1769
1770 /**
1771  * Get the sticky state of the window.
1772  *
1773  * @param obj The window object
1774  * @return If true, the window's sticky state is enabled
1775  *
1776  * @ingroup Win
1777  */
1778 EAPI Eina_Bool
1779 elm_win_sticky_get(const Evas_Object *obj)
1780 {
1781    Elm_Win *win;
1782    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1783    win = elm_widget_data_get(obj);
1784    if (!win) return EINA_FALSE;
1785    return ecore_evas_sticky_get(win->ee);
1786 }
1787
1788 /**
1789  * Sets the keyboard mode of the window.
1790  *
1791  * @param obj The window object
1792  * @param mode The mode to set; one of:
1793  * ELM_WIN_KEYBOARD_UNKNOWN
1794  * ELM_WIN_KEYBOARD_OFF
1795  * ELM_WIN_KEYBOARD_ON
1796  * ELM_WIN_KEYBOARD_ALPHA
1797  * ELM_WIN_KEYBOARD_NUMERIC
1798  * ELM_WIN_KEYBOARD_PIN
1799  * ELM_WIN_KEYBOARD_PHONE_NUMBER
1800  * ELM_WIN_KEYBOARD_HEX
1801  * ELM_WIN_KEYBOARD_TERMINAL
1802  * ELM_WIN_KEYBOARD_PASSWORD
1803  * ELM_WIN_KEYBOARD_IP
1804  * ELM_WIN_KEYBOARD_HOST
1805  * ELM_WIN_KEYBOARD_FILE
1806  * ELM_WIN_KEYBOARD_URL
1807  * ELM_WIN_KEYBOARD_KEYPAD
1808  * ELM_WIN_KEYBOARD_J2ME
1809  *
1810  * @ingroup Win
1811  */
1812 EAPI void
1813 elm_win_keyboard_mode_set(Evas_Object *obj, Elm_Win_Keyboard_Mode mode)
1814 {
1815    Elm_Win *win;
1816    ELM_CHECK_WIDTYPE(obj, widtype);
1817    win = elm_widget_data_get(obj);
1818    if (!win) return;
1819    if (mode == win->kbdmode) return;
1820 #ifdef HAVE_ELEMENTARY_X
1821    _elm_win_xwindow_get(win);
1822 #endif
1823    win->kbdmode = mode;
1824 #ifdef HAVE_ELEMENTARY_X
1825    if (win->xwin)
1826      ecore_x_e_virtual_keyboard_state_set
1827      (win->xwin, (Ecore_X_Virtual_Keyboard_State)win->kbdmode);
1828 #endif
1829 }
1830
1831 /**
1832  * Gets the keyboard mode of the window.
1833  *
1834  * @param obj The window object
1835  * @return The mode; one of:
1836  * ELM_WIN_KEYBOARD_UNKNOWN
1837  * ELM_WIN_KEYBOARD_OFF
1838  * ELM_WIN_KEYBOARD_ON
1839  * ELM_WIN_KEYBOARD_ALPHA
1840  * ELM_WIN_KEYBOARD_NUMERIC
1841  * ELM_WIN_KEYBOARD_PIN
1842  * ELM_WIN_KEYBOARD_PHONE_NUMBER
1843  * ELM_WIN_KEYBOARD_HEX
1844  * ELM_WIN_KEYBOARD_TERMINAL
1845  * ELM_WIN_KEYBOARD_PASSWORD
1846  * ELM_WIN_KEYBOARD_IP
1847  * ELM_WIN_KEYBOARD_HOST
1848  * ELM_WIN_KEYBOARD_FILE
1849  * ELM_WIN_KEYBOARD_URL
1850  * ELM_WIN_KEYBOARD_KEYPAD
1851  * ELM_WIN_KEYBOARD_J2ME
1852  *
1853  * @ingroup Win
1854  */
1855 EAPI Elm_Win_Keyboard_Mode
1856 elm_win_keyboard_mode_get(const Evas_Object *obj)
1857 {
1858    Elm_Win *win;
1859    ELM_CHECK_WIDTYPE(obj, widtype) ELM_WIN_KEYBOARD_UNKNOWN;
1860    win = elm_widget_data_get(obj);
1861    if (!win) return ELM_WIN_KEYBOARD_UNKNOWN;
1862    return win->kbdmode;
1863 }
1864
1865 /**
1866  * Sets whether the window is a keyboard.
1867  *
1868  * @param obj The window object
1869  * @param is_keyboard If true, the window is a virtual keyboard
1870  *
1871  * @ingroup Win
1872  */
1873 EAPI void
1874 elm_win_keyboard_win_set(Evas_Object *obj, Eina_Bool is_keyboard)
1875 {
1876    Elm_Win *win;
1877    ELM_CHECK_WIDTYPE(obj, widtype);
1878    win = elm_widget_data_get(obj);
1879    if (!win) return;
1880 #ifdef HAVE_ELEMENTARY_X
1881    _elm_win_xwindow_get(win);
1882    if (win->xwin)
1883      ecore_x_e_virtual_keyboard_set(win->xwin, is_keyboard);
1884 #endif
1885 }
1886
1887 /**
1888  * Gets whether the window is a keyboard.
1889  *
1890  * @param obj The window object
1891  * @return If the window is a virtual keyboard
1892  *
1893  * @ingroup Win
1894  */
1895 EAPI Eina_Bool
1896 elm_win_keyboard_win_get(const Evas_Object *obj)
1897 {
1898    Elm_Win *win;
1899    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1900    win = elm_widget_data_get(obj);
1901    if (!win) return EINA_FALSE;
1902 #ifdef HAVE_ELEMENTARY_X
1903    _elm_win_xwindow_get(win);
1904    if (win->xwin)
1905      return ecore_x_e_virtual_keyboard_get(win->xwin);
1906 #endif
1907    return EINA_FALSE;
1908 }
1909
1910 /**
1911  * Get the screen position of a window.
1912  *
1913  * @param obj The window object
1914  * @param x The int to store the x coordinate to
1915  * @param y The int to store the y coordinate to
1916  *
1917  * @ingroup Win
1918  */
1919 EAPI void
1920 elm_win_screen_position_get(const Evas_Object *obj, int *x, int *y)
1921 {
1922    Elm_Win *win;
1923    ELM_CHECK_WIDTYPE(obj, widtype);
1924    win = elm_widget_data_get(obj);
1925    if (!win) return;
1926    if (x) *x = win->screen.x;
1927    if (y) *y = win->screen.y;
1928 }
1929
1930 /**
1931  * Set if this window is an illume conformant window
1932  *
1933  * @param obj The window object
1934  * @param conformant The conformant flag (1 = conformant, 0 = non-conformant)
1935  *
1936  * @ingroup Win
1937  */
1938 EAPI void
1939 elm_win_conformant_set(Evas_Object *obj, Eina_Bool conformant)
1940 {
1941    Elm_Win *win;
1942    ELM_CHECK_WIDTYPE(obj, widtype);
1943    win = elm_widget_data_get(obj);
1944    if (!win) return;
1945 #ifdef HAVE_ELEMENTARY_X
1946    _elm_win_xwindow_get(win);
1947    if (win->xwin)
1948      ecore_x_e_illume_conformant_set(win->xwin, conformant);
1949 #endif
1950 }
1951
1952 /**
1953  * Get if this window is an illume conformant window
1954  *
1955  * @param obj The window object
1956  * @return A boolean if this window is illume conformant or not
1957  *
1958  * @ingroup Win
1959  */
1960 EAPI Eina_Bool
1961 elm_win_conformant_get(const Evas_Object *obj)
1962 {
1963    Elm_Win *win;
1964    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1965    win = elm_widget_data_get(obj);
1966    if (!win) return EINA_FALSE;
1967 #ifdef HAVE_ELEMENTARY_X
1968    _elm_win_xwindow_get(win);
1969    if (win->xwin)
1970      return ecore_x_e_illume_conformant_get(win->xwin);
1971 #endif
1972    return EINA_FALSE;
1973 }
1974
1975 /**
1976  * Set a window to be an illume quickpanel window
1977  *
1978  * By default window objects are not quickpanel windows.
1979  *
1980  * @param obj The window object
1981  * @param quickpanel The quickpanel flag (1 = quickpanel, 0 = normal window)
1982  *
1983  * @ingroup Win
1984  */
1985 EAPI void
1986 elm_win_quickpanel_set(Evas_Object *obj, Eina_Bool quickpanel)
1987 {
1988    Elm_Win *win;
1989    ELM_CHECK_WIDTYPE(obj, widtype);
1990    win = elm_widget_data_get(obj);
1991    if (!win) return;
1992 #ifdef HAVE_ELEMENTARY_X
1993    _elm_win_xwindow_get(win);
1994    if (win->xwin)
1995      {
1996         ecore_x_e_illume_quickpanel_set(win->xwin, quickpanel);
1997         if (quickpanel)
1998           {
1999              Ecore_X_Window_State states[2];
2000
2001              states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
2002              states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
2003              ecore_x_netwm_window_state_set(win->xwin, states, 2);
2004              ecore_x_icccm_hints_set(win->xwin, 0, 0, 0, 0, 0, 0, 0);
2005           }
2006      }
2007 #endif
2008 }
2009
2010 /**
2011  * Get if this window is a quickpanel or not
2012  *
2013  * @param obj The window object
2014  * @return A boolean if this window is a quickpanel or not
2015  *
2016  * @ingroup Win
2017  */
2018 EAPI Eina_Bool
2019 elm_win_quickpanel_get(const Evas_Object *obj)
2020 {
2021    Elm_Win *win;
2022    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2023    win = elm_widget_data_get(obj);
2024    if (!win) return EINA_FALSE;
2025 #ifdef HAVE_ELEMENTARY_X
2026    _elm_win_xwindow_get(win);
2027    if (win->xwin)
2028      return ecore_x_e_illume_quickpanel_get(win->xwin);
2029 #endif
2030    return EINA_FALSE;
2031 }
2032
2033 /**
2034  * Set the major priority of a quickpanel window
2035  *
2036  * @param obj The window object
2037  * @param priority The major priority for this quickpanel
2038  *
2039  * @ingroup Win
2040  */
2041 EAPI void
2042 elm_win_quickpanel_priority_major_set(Evas_Object *obj, int priority)
2043 {
2044    Elm_Win *win;
2045    ELM_CHECK_WIDTYPE(obj, widtype);
2046    win = elm_widget_data_get(obj);
2047    if (!win) return;
2048 #ifdef HAVE_ELEMENTARY_X
2049    _elm_win_xwindow_get(win);
2050    if (win->xwin)
2051      ecore_x_e_illume_quickpanel_priority_major_set(win->xwin, priority);
2052 #endif
2053 }
2054
2055 /**
2056  * Get the major priority of a quickpanel window
2057  *
2058  * @param obj The window object
2059  * @return The major priority of this quickpanel
2060  *
2061  * @ingroup Win
2062  */
2063 EAPI int
2064 elm_win_quickpanel_priority_major_get(const Evas_Object *obj)
2065 {
2066    Elm_Win *win;
2067    ELM_CHECK_WIDTYPE(obj, widtype) -1;
2068    win = elm_widget_data_get(obj);
2069    if (!win) return -1;
2070 #ifdef HAVE_ELEMENTARY_X
2071    _elm_win_xwindow_get(win);
2072    if (win->xwin)
2073      return ecore_x_e_illume_quickpanel_priority_major_get(win->xwin);
2074 #endif
2075    return -1;
2076 }
2077
2078 /**
2079  * Set the minor priority of a quickpanel window
2080  *
2081  * @param obj The window object
2082  * @param priority The minor priority for this quickpanel
2083  *
2084  * @ingroup Win
2085  */
2086 EAPI void
2087 elm_win_quickpanel_priority_minor_set(Evas_Object *obj, int priority)
2088 {
2089    Elm_Win *win;
2090    ELM_CHECK_WIDTYPE(obj, widtype);
2091    win = elm_widget_data_get(obj);
2092    if (!win) return;
2093 #ifdef HAVE_ELEMENTARY_X
2094    _elm_win_xwindow_get(win);
2095    if (win->xwin)
2096      ecore_x_e_illume_quickpanel_priority_minor_set(win->xwin, priority);
2097 #endif
2098 }
2099
2100 /**
2101  * Get the minor priority of a quickpanel window
2102  *
2103  * @param obj The window object
2104  * @return The minor priority of this quickpanel
2105  *
2106  * @ingroup Win
2107  */
2108 EAPI int
2109 elm_win_quickpanel_priority_minor_get(const Evas_Object *obj)
2110 {
2111    Elm_Win *win;
2112    ELM_CHECK_WIDTYPE(obj, widtype) -1;
2113    win = elm_widget_data_get(obj);
2114    if (!win) return -1;
2115 #ifdef HAVE_ELEMENTARY_X
2116    _elm_win_xwindow_get(win);
2117    if (win->xwin)
2118      return ecore_x_e_illume_quickpanel_priority_minor_get(win->xwin);
2119 #endif
2120    return -1;
2121 }
2122
2123 /**
2124  * Set which zone this quickpanel should appear in
2125  *
2126  * @param obj The window object
2127  * @param zone The requested zone for this quickpanel
2128  *
2129  * @ingroup Win
2130  */
2131 EAPI void
2132 elm_win_quickpanel_zone_set(Evas_Object *obj, int zone)
2133 {
2134    Elm_Win *win;
2135    ELM_CHECK_WIDTYPE(obj, widtype);
2136    win = elm_widget_data_get(obj);
2137    if (!win) return;
2138 #ifdef HAVE_ELEMENTARY_X
2139    _elm_win_xwindow_get(win);
2140    if (win->xwin)
2141      ecore_x_e_illume_quickpanel_zone_set(win->xwin, zone);
2142 #endif
2143 }
2144
2145 /**
2146  * Get which zone this quickpanel should appear in
2147  *
2148  * @param obj The window object
2149  * @return The requested zone for this quickpanel
2150  *
2151  * @ingroup Win
2152  */
2153 EAPI int
2154 elm_win_quickpanel_zone_get(const Evas_Object *obj)
2155 {
2156    Elm_Win *win;
2157    ELM_CHECK_WIDTYPE(obj, widtype) 0;
2158    win = elm_widget_data_get(obj);
2159    if (!win) return 0;
2160 #ifdef HAVE_ELEMENTARY_X
2161    _elm_win_xwindow_get(win);
2162    if (win->xwin)
2163      return ecore_x_e_illume_quickpanel_zone_get(win->xwin);
2164 #endif
2165    return 0;
2166 }
2167
2168 /**
2169  * Set the window to be skipped by keyboard focus
2170  * 
2171  * This sets the window to be skipped by normal keyboard input. This means
2172  * a window manager will be asked to not focus this window as well as omit
2173  * it from things like the taskbar, pager, "alt-tab" list etc. etc.
2174  * 
2175  * Call this and enable it on a window BEFORE you show it for the first time,
2176  * otherwise it may have no effect.
2177  * 
2178  * Use this for windows that have only output information or might only be
2179  * interacted with by the mouse or fingers, and never for typing input.
2180  * Be careful that this may have side-effects like making the window
2181  * non-accessible in some cases unless the window is specially handled. Use
2182  * this with care.
2183  * 
2184  * @param obj The window object
2185  * @param skip The skip flag state (EINA_TRUE if it is to be skipped)
2186  * 
2187  * @ingroup Win
2188  */
2189 EAPI void
2190 elm_win_prop_focus_skip_set(Evas_Object *obj, Eina_Bool skip)
2191 {
2192    Elm_Win *win;
2193    ELM_CHECK_WIDTYPE(obj, widtype);
2194    win = elm_widget_data_get(obj);
2195    if (!win) return;
2196 #ifdef HAVE_ELEMENTARY_X
2197    _elm_win_xwindow_get(win);
2198    if (skip)
2199      {
2200         if (win->xwin)
2201           {
2202              Ecore_X_Window_State states[2];
2203              
2204              ecore_x_icccm_hints_set(win->xwin, 0, 0, 0, 0, 0, 0, 0);
2205              states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
2206              states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
2207              ecore_x_netwm_window_state_set(win->xwin, states, 2);
2208           }
2209      }
2210 #endif
2211 }
2212
2213 /**
2214  * Send a command to the windowing environment
2215  * 
2216  * This is intended to work in touchscreen or small screen device environments
2217  * where there is a more simplistic window management policy in place. This
2218  * uses the window object indicated to select which part of the environment
2219  * to control (the part that this window lives in), and provides a command
2220  * and an optional parameter structure (use NULL for this if not needed).
2221  * 
2222  * @param obj The window object that lives in the environment to control
2223  * @param command The command to send
2224  * @param params Optional parameters for the command
2225  * 
2226  * @ingroup Win
2227  */
2228 EAPI void
2229 elm_win_illume_command_send(Evas_Object *obj, Elm_Illume_Command command, void *params __UNUSED__)
2230 {
2231    Elm_Win *win;
2232    ELM_CHECK_WIDTYPE(obj, widtype);
2233    win = elm_widget_data_get(obj);
2234    if (!win) return;
2235 #ifdef HAVE_ELEMENTARY_X
2236    _elm_win_xwindow_get(win);
2237    if (win->xwin)
2238      {
2239         switch (command)
2240           {
2241            case ELM_ILLUME_COMMAND_FOCUS_BACK:
2242              ecore_x_e_illume_focus_back_send(win->xwin);
2243              break;
2244            case ELM_ILLUME_COMMAND_FOCUS_FORWARD:
2245              ecore_x_e_illume_focus_forward_send(win->xwin);
2246              break;
2247            case ELM_ILLUME_COMMAND_FOCUS_HOME:
2248              ecore_x_e_illume_focus_home_send(win->xwin);
2249              break;
2250            case ELM_ILLUME_COMMAND_CLOSE:
2251              ecore_x_e_illume_close_send(win->xwin);
2252              break;
2253            default:
2254              break;
2255           }
2256      }
2257 #endif
2258 }
2259
2260 /**
2261  * Set the enabled status for the focus highlight in a window
2262  *
2263  * This function will enable or disable the focus highlight only for the
2264  * given window, regardless of the global setting for it
2265  *
2266  * @param obj The window where to enable the highlight
2267  * @param enabled The enabled value for the highlight
2268  *
2269  * @ingroup Win
2270  */
2271 EAPI void
2272 elm_win_focus_highlight_enabled_set(Evas_Object *obj, Eina_Bool enabled)
2273 {
2274    Elm_Win *win;
2275
2276    ELM_CHECK_WIDTYPE(obj, widtype);
2277
2278    win = elm_widget_data_get(obj);
2279    enabled = !!enabled;
2280    if (win->focus_highlight.enabled == enabled)
2281      return;
2282
2283    win->focus_highlight.enabled = enabled;
2284
2285    if (win->focus_highlight.enabled)
2286      _elm_win_focus_highlight_init(win);
2287    else
2288      _elm_win_focus_highlight_shutdown(win);
2289 }
2290
2291 /**
2292  * Get the enabled value of the focus highlight for this window
2293  *
2294  * @param obj The window in which to check if the focus highlight is enabled
2295  *
2296  * @return EINA_TRUE if enabled, EINA_FALSE otherwise
2297  *
2298  * @ingroup Win
2299  */
2300 EAPI Eina_Bool
2301 elm_win_focus_highlight_enabled_get(const Evas_Object *obj)
2302 {
2303    Elm_Win *win;
2304
2305    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2306
2307    win = elm_widget_data_get(obj);
2308    return win->focus_highlight.enabled;
2309 }
2310
2311 /**
2312  * Set the style for the focus highlight on this window
2313  *
2314  * Sets the style to use for theming the highlight of focused objects on
2315  * the given window. If @p style is NULL, the default will be used.
2316  *
2317  * @param obj The window where to set the style
2318  * @param style The style to set
2319  *
2320  * @ingroup Win
2321  */
2322 EAPI void
2323 elm_win_focus_highlight_style_set(Evas_Object *obj, const char *style)
2324 {
2325    Elm_Win *win;
2326
2327    ELM_CHECK_WIDTYPE(obj, widtype);
2328
2329    win = elm_widget_data_get(obj);
2330    eina_stringshare_replace(&win->focus_highlight.style, style);
2331    win->focus_highlight.changed_theme = EINA_TRUE;
2332    _elm_win_focus_highlight_reconfigure_job_start(win);
2333 }
2334
2335 /**
2336  * Get the style set for the focus highlight object
2337  *
2338  * Gets the style set for this windows highilght object, or NULL if none
2339  * is set.
2340  *
2341  * @param obj The window to retrieve the highlights style from
2342  *
2343  * @return The style set or NULL if none was. Default is used in that case.
2344  *
2345  * @ingroup Win
2346  */
2347 EAPI const char *
2348 elm_win_focus_highlight_style_get(const Evas_Object *obj)
2349 {
2350    Elm_Win *win;
2351
2352    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2353
2354    win = elm_widget_data_get(obj);
2355    return win->focus_highlight.style;
2356 }
2357
2358 typedef struct _Widget_Data Widget_Data;
2359
2360 struct _Widget_Data
2361 {
2362    Evas_Object *frm;
2363    Evas_Object *content;
2364 };
2365
2366 static void _del_hook(Evas_Object *obj);
2367 static void _theme_hook(Evas_Object *obj);
2368 static void _sizing_eval(Evas_Object *obj);
2369 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
2370 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
2371
2372 static const char *widtype2 = NULL;
2373
2374 static void
2375 _del_hook(Evas_Object *obj)
2376 {
2377    Widget_Data *wd = elm_widget_data_get(obj);
2378    if (!wd) return;
2379    free(wd);
2380 }
2381
2382 static void
2383 _theme_hook(Evas_Object *obj)
2384 {
2385    Widget_Data *wd = elm_widget_data_get(obj);
2386    _elm_theme_object_set(obj, wd->frm, "win", "inwin", elm_widget_style_get(obj));
2387    if (wd->content)
2388      edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content);
2389    _sizing_eval(obj);
2390 }
2391
2392 static Eina_Bool
2393 _elm_inwin_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
2394 {
2395    Widget_Data *wd = elm_widget_data_get(obj);
2396
2397    if (!wd)
2398      return EINA_FALSE;
2399
2400    /* Try Focus cycle in subitem */
2401    if (wd->content)
2402      {
2403         elm_widget_focus_next_get(wd->content, dir, next);
2404         if (*next)
2405           return EINA_TRUE;
2406      }
2407
2408    *next = (Evas_Object *)obj;
2409    return EINA_FALSE;
2410 }
2411
2412 static void
2413 _sizing_eval(Evas_Object *obj)
2414 {
2415    Widget_Data *wd = elm_widget_data_get(obj);
2416    Evas_Coord minw = -1, minh = -1;
2417
2418    evas_object_size_hint_min_get(wd->content, &minw, &minh);
2419    edje_object_size_min_calc(wd->frm, &minw, &minh);
2420    evas_object_size_hint_min_set(obj, minw, minh);
2421    evas_object_size_hint_max_set(obj, -1, -1);
2422 }
2423
2424 static void
2425 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2426 {
2427    _sizing_eval(data);
2428 }
2429
2430 static void
2431 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
2432 {
2433    Widget_Data *wd = elm_widget_data_get(obj);
2434    Evas_Object *sub = event_info;
2435    if (sub == wd->content)
2436      {
2437         evas_object_event_callback_del_full
2438           (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
2439         wd->content = NULL;
2440         _sizing_eval(obj);
2441      }
2442 }
2443
2444 /**
2445  * @defgroup Inwin Inwin
2446  *
2447  * An inwin is a window inside a window that is useful for a quick popup.  It does not hover.
2448  */
2449 EAPI Evas_Object *
2450 elm_win_inwin_add(Evas_Object *obj)
2451 {
2452    Evas_Object *obj2;
2453    Widget_Data *wd;
2454    Elm_Win *win;
2455
2456    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2457    win = elm_widget_data_get(obj);
2458    if (!win) return NULL;
2459    wd = ELM_NEW(Widget_Data);
2460    obj2 = elm_widget_add(win->evas);
2461    elm_widget_type_set(obj2, "inwin");
2462    ELM_SET_WIDTYPE(widtype2, "inwin");
2463    elm_widget_sub_object_add(obj, obj2);
2464    evas_object_size_hint_weight_set(obj2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2465    evas_object_size_hint_align_set(obj2, EVAS_HINT_FILL, EVAS_HINT_FILL);
2466    elm_win_resize_object_add(obj, obj2);
2467
2468    elm_widget_data_set(obj2, wd);
2469    elm_widget_del_hook_set(obj2, _del_hook);
2470    elm_widget_theme_hook_set(obj2, _theme_hook);
2471    elm_widget_focus_next_hook_set(obj2, _elm_inwin_focus_next_hook);
2472    elm_widget_can_focus_set(obj2, EINA_TRUE);
2473    elm_widget_highlight_ignore_set(obj2, EINA_TRUE);
2474
2475    wd->frm = edje_object_add(win->evas);
2476    _elm_theme_object_set(obj, wd->frm, "win", "inwin", "default");
2477    elm_widget_resize_object_set(obj2, wd->frm);
2478
2479    evas_object_smart_callback_add(obj2, "sub-object-del", _sub_del, obj2);
2480
2481    _sizing_eval(obj2);
2482    return obj2;
2483 }
2484
2485 /**
2486  * Activates an inwin object
2487  *
2488  * @param obj The inwin to activate
2489  *
2490  * @ingroup Inwin
2491  */
2492 EAPI void
2493 elm_win_inwin_activate(Evas_Object *obj)
2494 {
2495    ELM_CHECK_WIDTYPE(obj, widtype2);
2496    Widget_Data *wd = elm_widget_data_get(obj);
2497    if (!wd) return;
2498    evas_object_raise(obj);
2499    evas_object_show(obj);
2500    edje_object_signal_emit(wd->frm, "elm,action,show", "elm");
2501    elm_object_focus(obj);
2502 }
2503
2504 /**
2505  * Set the content of an inwin object.
2506  *
2507  * Once the content object is set, a previously set one will be deleted.
2508  * If you want to keep that old content object, use the
2509  * elm_win_inwin_content_unset() function.
2510  *
2511  * @param obj The inwin object
2512  * @param content The object to set as content
2513  *
2514  * @ingroup Inwin
2515  */
2516 EAPI void
2517 elm_win_inwin_content_set(Evas_Object *obj, Evas_Object *content)
2518 {
2519    ELM_CHECK_WIDTYPE(obj, widtype2);
2520    Widget_Data *wd = elm_widget_data_get(obj);
2521    if (!wd) return;
2522    if (wd->content == content) return;
2523    if (wd->content) evas_object_del(wd->content);
2524    wd->content = content;
2525    if (content)
2526      {
2527         elm_widget_sub_object_add(obj, content);
2528         evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2529                                        _changed_size_hints, obj);
2530         edje_object_part_swallow(wd->frm, "elm.swallow.content", content);
2531      }
2532    _sizing_eval(obj);
2533 }
2534
2535 /**
2536  * Get the content of an inwin object.
2537  *
2538  * Return the content object which is set for this widget.
2539  *
2540  * @param obj The inwin object
2541  * @return The content that is being used
2542  *
2543  * @ingroup Inwin
2544  */
2545 EAPI Evas_Object *
2546 elm_win_inwin_content_get(const Evas_Object *obj)
2547 {
2548    ELM_CHECK_WIDTYPE(obj, widtype2) NULL;
2549    Widget_Data *wd = elm_widget_data_get(obj);
2550    if (!wd) return NULL;
2551    return wd->content;
2552 }
2553
2554 /**
2555  * Unset the content of an inwin object.
2556  *
2557  * Unparent and return the content object which was set for this widget.
2558  *
2559  * @param obj The inwin object
2560  * @return The content that was being used
2561  *
2562  * @ingroup Inwin
2563  */
2564 EAPI Evas_Object *
2565 elm_win_inwin_content_unset(Evas_Object *obj)
2566 {
2567    ELM_CHECK_WIDTYPE(obj, widtype2) NULL;
2568    Widget_Data *wd = elm_widget_data_get(obj);
2569    if (!wd) return NULL;
2570    if (!wd->content) return NULL;
2571    Evas_Object *content = wd->content;
2572    elm_widget_sub_object_del(obj, wd->content);
2573    edje_object_part_unswallow(wd->frm, wd->content);
2574    wd->content = NULL;
2575    return content;
2576 }
2577
2578 /* windowing spcific calls - shall we do this differently? */
2579 /**
2580  * Get the Ecore_X_Window of an Evas_Object
2581  *
2582  * @param obj The object
2583  *
2584  * @return The Ecore_X_Window of @p obj
2585  *
2586  * @ingroup Win
2587  */
2588 EAPI Ecore_X_Window
2589 elm_win_xwindow_get(const Evas_Object *obj)
2590 {
2591    Ecore_X_Window xwin = 0;
2592    Ecore_Evas *ee = NULL;
2593    if (!obj) return 0;
2594 #ifdef HAVE_ELEMENTARY_X
2595    ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
2596    if (ee) xwin = (Ecore_X_Window)ecore_evas_window_get(ee);
2597    return xwin;
2598 #else
2599    return 0;
2600 #endif
2601 }