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