elementary/elm_entry : Fix a bug in filter callback. There can be a
[framework/uifw/elementary.git] / src / lib / elm_conform.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #ifndef MIN
5 # define MIN(a,b) ((a) < (b)) ? (a) : (b)
6 #endif
7
8 #ifndef MAX
9 # define MAX(a,b) ((a) < (b)) ? (b) : (a)
10 #endif
11
12 typedef struct _Widget_Data Widget_Data;
13 struct _Widget_Data
14 {
15    Evas_Object *base;
16    Evas_Object *indicator;
17    Evas_Object *softkey;
18    Evas_Object *virtualkeypad;
19    Evas_Object *clipboard;
20    Evas_Object *content;
21    Evas_Object *scroller;
22 #ifdef HAVE_ELEMENTARY_X
23    Ecore_Event_Handler *prop_hdl;
24    Ecore_X_Virtual_Keyboard_State vkb_state;
25 #endif
26    struct
27    {
28       Ecore_Animator *animator; // animaton timer
29       double start; // time started
30       Evas_Coord auto_x, auto_y; // desired delta
31       Evas_Coord x, y; // current delta
32    } delta;
33    Ecore_Job *show_region_job;
34 };
35
36 /* Enum to identify conformant swallow parts */
37 typedef enum _Conformant_Part_Type Conformant_Part_Type;
38 enum _Conformant_Part_Type
39 {
40    ELM_CONFORM_INDICATOR_PART      = 1,
41    ELM_CONFORM_SOFTKEY_PART        = 2,
42    ELM_CONFORM_VIRTUAL_KEYPAD_PART = 4,
43    ELM_CONFORM_CLIPBOARD_PART    = 8
44 };
45
46 #ifdef HAVE_ELEMENTARY_X
47 #define SUB_TYPE_COUNT 2
48 static char *sub_type[SUB_TYPE_COUNT] = { "scroller", "genlist" };
49 #endif
50
51 /* local function prototypes */
52 static const char *widtype = NULL;
53 static void _del_pre_hook(Evas_Object *obj);
54 static void _del_hook(Evas_Object *obj);
55 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
56 static void _theme_hook(Evas_Object *obj);
57 static void _content_set_hook(Evas_Object *obj,
58                               const char *part,
59                               Evas_Object *content);
60 static Evas_Object *_content_get_hook(const Evas_Object *obj,
61                                       const char *part);
62 static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
63 static void _swallow_conformant_parts(Evas_Object *obj);
64 static void _conformant_part_size_set(Evas_Object *obj,
65                                       Evas_Object *sobj,
66                                       Evas_Coord sx,
67                                       Evas_Coord sy,
68                                       Evas_Coord sw,
69                                       Evas_Coord sh);
70 static void _conformant_part_sizing_eval(Evas_Object *obj,
71                                          Conformant_Part_Type part_type);
72 static void _conformant_move_resize_event_cb(void *data,
73                                              Evas *e,
74                                              Evas_Object *obj,
75                                              void *event_info);
76 static void _sizing_eval(Evas_Object *obj);
77 static void _show_region_job(void *data);
78 static void _changed_size_hints(void *data, Evas *e,
79                                 Evas_Object *obj,
80                                 void *event_info);
81
82 /* local functions */
83 static void
84 _del_pre_hook(Evas_Object *obj)
85 {
86    Widget_Data *wd = elm_widget_data_get(obj);
87    if (!wd) return;
88
89 #ifdef HAVE_ELEMENTARY_X
90    if (wd->prop_hdl) ecore_event_handler_del(wd->prop_hdl);
91 #endif
92 }
93
94 static void
95 _del_hook(Evas_Object *obj)
96 {
97    Widget_Data *wd = elm_widget_data_get(obj);
98    if (!wd) return;
99
100    if (wd->show_region_job) ecore_job_del(wd->show_region_job);
101    free(wd);
102 }
103
104 static void
105 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
106 {
107    Widget_Data *wd = elm_widget_data_get(obj);
108    if (!wd) return;
109
110    edje_object_mirrored_set(wd->base, rtl);
111 }
112
113 static void
114 _theme_hook(Evas_Object *obj)
115 {
116    Widget_Data *wd = elm_widget_data_get(obj);
117    if (!wd) return;
118
119    _elm_widget_mirrored_reload(obj);
120    _mirrored_set(obj, elm_widget_mirrored_get(obj));
121    _elm_theme_object_set(obj, wd->base, "conformant", "base",
122                          elm_widget_style_get(obj));
123    _swallow_conformant_parts(obj);
124
125    if (wd->content)
126      edje_object_part_swallow(wd->base, "elm.swallow.content", wd->content);
127    _sizing_eval(obj);
128 }
129
130 static void
131 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
132 {
133    ELM_CHECK_WIDTYPE(obj, widtype);
134    Widget_Data *wd;
135
136    if (part && strcmp(part, "default")) return;
137    wd = elm_widget_data_get(obj);
138    if (!wd) return;
139    if (wd->content == content) return;
140    if (wd->content) evas_object_del(wd->content);
141    wd->content = content;
142    if (content)
143      {
144         elm_widget_sub_object_add(obj, content);
145         evas_object_event_callback_add(content,
146                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
147                                        _changed_size_hints, obj);
148         edje_object_part_swallow(wd->base, "elm.swallow.content", content);
149      }
150    _sizing_eval(obj);
151 }
152
153 static Evas_Object *
154 _content_get_hook(const Evas_Object *obj, const char *part)
155 {
156    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
157    Widget_Data *wd;
158
159    if (part && strcmp(part, "default")) return NULL;
160    wd = elm_widget_data_get(obj);
161    if (!wd) return NULL;
162    return wd->content;
163 }
164
165 static Evas_Object *
166 _content_unset_hook(Evas_Object *obj, const char *part)
167 {
168    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
169    Widget_Data *wd;
170    Evas_Object *content;
171    if (part && strcmp(part, "default")) return NULL;
172    wd = elm_widget_data_get(obj);
173    if ((!wd) || (!wd->content)) return NULL;
174
175    content = wd->content;
176    elm_widget_sub_object_del(obj, wd->content);
177    evas_object_event_callback_del_full(content,
178                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
179                                        _changed_size_hints, obj);
180    edje_object_part_unswallow(wd->base, content);
181    wd->content = NULL;
182    return content;
183 }
184
185 static void
186 _sizing_eval(Evas_Object *obj)
187 {
188    Widget_Data *wd = elm_widget_data_get(obj);
189    Evas_Coord mw = -1, mh = -1;
190    if (!wd) return;
191
192    edje_object_size_min_calc(wd->base, &mw, &mh);
193    evas_object_size_hint_min_set(obj, mw, mh);
194    evas_object_size_hint_max_set(obj, -1, -1);
195 }
196
197 /* Example of env vars:
198  * ILLUME_KBD="0, 0, 800, 301"
199  * ILLUME_IND=0,0,800,32
200  * ILLUME_STK="0,568,800,32
201  */
202 static Eina_Bool
203 _conformant_part_geometry_env_get(const char *part, int *sx, int *sy, int *sw, int *sh)
204 {
205    const char delimiters[] = " ,;";
206    char *env_val, *token;
207    char buf[PATH_MAX];
208    int tsx, tsy, tsw;
209
210    if (!(env_val = getenv(part))) return EINA_FALSE;
211
212    /* strtok would modify env var if not copied to a buffer */
213    strncpy(buf, env_val, sizeof(buf));
214
215    token = strtok(buf, delimiters);
216    if (!token) return EINA_FALSE;
217    tsx = atoi(token);
218
219    token = strtok(NULL, delimiters);
220    if (!token) return EINA_FALSE;
221    tsy = atoi(token);
222
223    token = strtok(NULL, delimiters);
224    if (!token) return EINA_FALSE;
225    tsw = atoi(token);
226
227    token = strtok(NULL, delimiters);
228    if (!token) return EINA_FALSE;
229    *sh = atoi(token);
230
231    *sx = tsx;
232    *sy = tsy;
233    *sw = tsw;
234
235    return EINA_TRUE;
236 }
237
238 static void
239 _conformant_part_size_set(Evas_Object *obj, Evas_Object *sobj, Evas_Coord sx,
240                           Evas_Coord sy, Evas_Coord sw, Evas_Coord sh)
241 {
242    Evas_Coord cx, cy, cw, ch;
243    Evas_Coord part_height = 0, part_width = 0;
244
245    evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
246
247    /* Part overlapping with conformant */
248    if ((cx < (sx + sw)) && ((cx + cw) > sx)
249             && (cy < (sy + sh)) && ((cy + ch) > sy))
250      {
251         part_height = MIN((cy + ch), (sy + sh)) - MAX(cy, sy);
252         part_width = MIN((cx + cw), (sx + sw)) - MAX(cx, sx);
253      }
254
255    evas_object_size_hint_min_set(sobj, part_width, part_height);
256    evas_object_size_hint_max_set(sobj, part_width, part_height);
257 }
258
259 static void
260 _conformant_part_sizing_eval(Evas_Object *obj, Conformant_Part_Type part_type)
261 {
262 #ifdef HAVE_ELEMENTARY_X
263    Ecore_X_Window zone = 0;
264    Evas_Object *top;
265 #endif
266    Ecore_X_Window xwin;
267    int sx = -1, sy = -1, sw = -1, sh = -1;
268    Widget_Data *wd = elm_widget_data_get(obj);
269    if (!wd) return;
270
271 #ifdef HAVE_ELEMENTARY_X
272    top = elm_widget_top_get(obj);
273    xwin = elm_win_xwindow_get(top);
274    if (xwin)
275      zone = ecore_x_e_illume_zone_get(xwin);
276 #endif
277
278    if (part_type & ELM_CONFORM_INDICATOR_PART)
279      {
280         if ((!_conformant_part_geometry_env_get("ILLUME_IND",
281                                                 &sx, &sy, &sw, &sh)) && (xwin))
282           {
283 #ifdef HAVE_ELEMENTARY_X
284            //No information of the indicator geometry, reset the geometry.
285              if (!ecore_x_e_illume_indicator_geometry_get(zone, &sx, &sy, &sw, &sh))
286                sx = sy = sw = sh = 0;
287 #else
288              ;
289 #endif
290           }
291         _conformant_part_size_set(obj, wd->indicator, sx, sy, sw, sh);
292      }
293    if (part_type & ELM_CONFORM_VIRTUAL_KEYPAD_PART)
294      {
295         if ((!_conformant_part_geometry_env_get("ILLUME_KBD",
296                                                 &sx, &sy, &sw, &sh)) && (xwin))
297           {
298 #ifdef HAVE_ELEMENTARY_X
299            //No information of the keyboard geometry, reset the geometry.
300            if (!ecore_x_e_illume_keyboard_geometry_get(zone, &sx, &sy, &sw, &sh))
301              sx = sy = sw = sh = 0;
302 #else
303              ;
304 #endif
305           }
306         _conformant_part_size_set(obj, wd->virtualkeypad, sx, sy, sw, sh);
307      }
308    if (part_type & ELM_CONFORM_SOFTKEY_PART)
309      {
310         if ((!_conformant_part_geometry_env_get("ILLUME_STK",
311                                                 &sx, &sy, &sw, &sh)) && (xwin))
312           {
313 #ifdef HAVE_ELEMENTARY_X
314            //No information of the softkey geometry, reset the geometry.
315            if (!ecore_x_e_illume_softkey_geometry_get(zone, &sx, &sy, &sw, &sh))
316              sx = sy = sw = sh = 0;
317 #else
318              ;
319 #endif
320           }
321         _conformant_part_size_set(obj, wd->softkey, sx, sy, sw, sh);
322      }
323    if (part_type & ELM_CONFORM_CLIPBOARD_PART)
324      {
325         if ((!_conformant_part_geometry_env_get("ILLUME_CB",
326                                                 &sx, &sy, &sw, &sh)) && (xwin))
327           {
328 #ifdef HAVE_ELEMENTARY_X
329            //No information of the clipboard geometry, reset the geometry.
330            if (!ecore_x_e_illume_clipboard_geometry_get(zone, &sx, &sy, &sw, &sh))
331              sx = sy = sw = sh = 0;
332 #else
333              ;
334 #endif
335           }
336         _conformant_part_size_set(obj, wd->clipboard, sx, sy, sw, sh);
337      }
338 }
339
340 static void
341 _swallow_conformant_parts(Evas_Object *obj)
342 {
343    Widget_Data *wd = elm_widget_data_get(obj);
344    Evas *e = evas_object_evas_get(obj);
345    if (!wd || !e) return;
346
347    wd->scroller = NULL;
348
349    //Indicator
350    if (!wd->indicator)
351      {
352         wd->indicator = evas_object_rectangle_add(e);
353         elm_widget_sub_object_add(obj, wd->indicator);
354         evas_object_size_hint_min_set(wd->indicator, -1, 0);
355         evas_object_size_hint_max_set(wd->indicator, -1, 0);
356      }
357    else
358      _conformant_part_sizing_eval(obj, ELM_CONFORM_INDICATOR_PART);
359    evas_object_color_set(wd->indicator, 0, 0, 0, 0);
360    edje_object_part_swallow(wd->base, "elm.swallow.indicator", wd->indicator);
361
362    //Virtual Keyboard
363    if (!wd->virtualkeypad)
364      {
365         wd->virtualkeypad = evas_object_rectangle_add(e);
366         elm_widget_sub_object_add(obj, wd->virtualkeypad);
367         evas_object_size_hint_min_set(wd->virtualkeypad, -1, 0);
368         evas_object_size_hint_max_set(wd->virtualkeypad, -1, 0);
369      }
370    else
371      _conformant_part_sizing_eval(obj, ELM_CONFORM_VIRTUAL_KEYPAD_PART);
372    evas_object_color_set(wd->virtualkeypad, 0, 0, 0, 0);
373    edje_object_part_swallow(wd->base, "elm.swallow.virtualkeypad",
374                             wd->virtualkeypad);
375    //Clipboard
376    if (!wd->clipboard)
377      {
378         wd->clipboard = evas_object_rectangle_add(e);
379         elm_widget_sub_object_add(obj, wd->clipboard);
380         evas_object_size_hint_min_set(wd->clipboard, -1, 0);
381         evas_object_size_hint_max_set(wd->clipboard, -1, 0);
382      }
383    else
384      _conformant_part_sizing_eval(obj, ELM_CONFORM_CLIPBOARD_PART);
385    evas_object_color_set(wd->clipboard, 0, 0, 0, 0);
386    edje_object_part_swallow(wd->base, "elm.swallow.clipboard",
387                             wd->clipboard);
388
389    //Softkey
390    if (!wd->softkey)
391      {
392         wd->softkey = evas_object_rectangle_add(e);
393         elm_widget_sub_object_add(obj, wd->softkey);
394         evas_object_size_hint_min_set(wd->softkey, -1, 0);
395         evas_object_size_hint_max_set(wd->softkey, -1, 0);
396      }
397    else
398      _conformant_part_sizing_eval(obj, ELM_CONFORM_SOFTKEY_PART);
399    evas_object_color_set(wd->softkey, 0, 0, 0, 0);
400    edje_object_part_swallow(wd->base, "elm.swallow.softkey", wd->softkey);
401 }
402
403 static void
404 _changed_size_hints(void *data, Evas *e __UNUSED__,
405                     Evas_Object *obj __UNUSED__,
406                     void *event_info __UNUSED__)
407 {
408    Widget_Data *wd = elm_widget_data_get(data);
409    if (!wd) return;
410
411    _sizing_eval(data);
412 }
413
414 static void
415 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
416 {
417    Widget_Data *wd = elm_widget_data_get(obj);
418    Evas_Object *sub = event_info;
419    if (!wd) return;
420
421    if (sub == wd->content)
422      {
423         evas_object_event_callback_del_full(sub,
424                                             EVAS_CALLBACK_CHANGED_SIZE_HINTS,
425                                             _changed_size_hints, obj);
426         wd->content = NULL;
427         _sizing_eval(obj);
428      }
429 }
430
431 /* unused now - but meant to be for making sure the focused widget is always
432  * visible when the vkbd comes and goes by moving the conformant obj (and thus
433  * its children) to  show the focused widget (and if focus changes follow)
434
435 static Evas_Object *
436 _focus_object_get(const Evas_Object *obj)
437 {
438    Evas_Object *win, *foc;
439
440    win = elm_widget_top_get(obj);
441    if (!win) return NULL;
442    foc = elm_widget_top_get(win);
443 }
444
445 static void
446 _focus_object_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
447 {
448    evas_object_geometry_get(obj, x, y, w, h);
449 }
450
451 static void
452 _focus_change_del(void *data, Evas_Object *obj, void *event_info)
453 {
454    // called from toplevel when the focused window shanges
455 }
456
457 static void
458 _autoscroll_move(Evas_Object *obj)
459 {
460    // move conformant edje by delta to show focused widget
461 }
462
463 static void
464 _autoscroll_mode_enable(Evas_Object *obj)
465 {
466 // called when autoscroll mode should be on - content area smaller than
467 // its min size
468 // 1. get focused object
469 // 2. if not in visible conformant area calculate delta needed to
470 //    get it in
471 // 3. store delta and call _autoscroll_move() which either asanimates
472 //    or jumps right there
473 }
474
475 static void
476 _autoscroll_mode_disable(Evas_Object *obj)
477 {
478 // called when autoscroll mode should be off - set delta to 0 and
479 // call _autoscroll_move()
480 }
481  */
482
483 static void
484 _conformant_move_resize_event_cb(void *data __UNUSED__, Evas *e __UNUSED__,
485                                  Evas_Object *obj, void *event_info __UNUSED__)
486 {
487    Conformant_Part_Type part_type;
488    Widget_Data *wd = elm_widget_data_get(obj);
489    if (!wd) return;
490
491    part_type =  (ELM_CONFORM_INDICATOR_PART |
492                  ELM_CONFORM_SOFTKEY_PART |
493                  ELM_CONFORM_VIRTUAL_KEYPAD_PART |
494                  ELM_CONFORM_CLIPBOARD_PART);
495    _conformant_part_sizing_eval(obj, part_type);
496 }
497
498 // showing the focused/important region.
499 #ifdef HAVE_ELEMENTARY_X
500 static void
501 _content_resize_event_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj
502                          __UNUSED__, void *event_info __UNUSED__)
503 {
504    Evas_Object *conformant = (Evas_Object *)data;
505    Widget_Data *wd = elm_widget_data_get(conformant);
506    if (!wd) return;
507
508    if (wd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) return;
509
510    if (wd->show_region_job) ecore_job_del(wd->show_region_job);
511    wd->show_region_job = ecore_job_add(_show_region_job, conformant);
512 }
513 #endif
514
515 static void
516 _show_region_job(void *data)
517 {
518    Evas_Object *focus_obj;
519    Evas_Object *conformant = (Evas_Object *)data;
520    Widget_Data *wd = elm_widget_data_get(conformant);
521    if (!wd) return;
522
523    focus_obj = elm_widget_focused_object_get(conformant);
524    if (focus_obj)
525      {
526         Evas_Coord x, y, w, h;
527
528         elm_widget_show_region_get(focus_obj, &x, &y, &w, &h);
529
530         if (h < _elm_config->finger_size)
531           h = _elm_config->finger_size;
532
533         elm_widget_show_region_set(focus_obj, x, y, w, h, EINA_TRUE);
534      }
535
536    wd->show_region_job = NULL;
537 }
538
539 #ifdef HAVE_ELEMENTARY_X
540 static void
541 _update_autoscroll_objs(void *data)
542 {
543    const char *type;
544    int i;
545    Evas_Object *sub, *top_scroller = NULL;
546    Evas_Object *conformant = (Evas_Object *)data;
547    Widget_Data *wd = elm_widget_data_get(data);
548    if (!wd) return;
549
550    sub = elm_widget_focused_object_get(conformant);
551    //Look up for Top most scroller in the Focus Object hierarchy inside Conformant.
552
553    while (sub)
554      {
555         type = elm_widget_type_get(sub);
556         if (!strcmp(type, "conformant")) break;
557         for (i = 0; i < SUB_TYPE_COUNT; i++)
558           if (!strcmp(type, sub_type[i]))
559             {
560                top_scroller = sub;
561                break;
562             }
563         sub = elm_object_parent_widget_get(sub);
564      }
565
566    //If the scroller got changed by app, replace it.
567    if (top_scroller != wd->scroller)
568      {
569         if (wd->scroller) evas_object_event_callback_del(wd->scroller,
570                                                    EVAS_CALLBACK_RESIZE,
571                                                    _content_resize_event_cb);
572         wd->scroller = top_scroller;
573         if (wd->scroller) evas_object_event_callback_add(wd->scroller,
574                                                    EVAS_CALLBACK_RESIZE,
575                                                    _content_resize_event_cb,
576                                                    data);
577      }
578 }
579
580 static Eina_Bool
581 _prop_change(void *data, int type __UNUSED__, void *event)
582 {
583    Ecore_X_Event_Window_Property *ev;
584    Widget_Data *wd = elm_widget_data_get(data);
585
586    if (!wd) return ECORE_CALLBACK_PASS_ON;
587    ev = event;
588    if (ev->atom == ECORE_X_ATOM_E_ILLUME_ZONE)
589      {
590         Conformant_Part_Type part_type;
591
592         part_type =  (ELM_CONFORM_INDICATOR_PART |
593                       ELM_CONFORM_SOFTKEY_PART |
594                       ELM_CONFORM_VIRTUAL_KEYPAD_PART |
595                       ELM_CONFORM_CLIPBOARD_PART);
596         _conformant_part_sizing_eval(data, part_type);
597      }
598    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
599      _conformant_part_sizing_eval(data, ELM_CONFORM_INDICATOR_PART);
600    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
601      _conformant_part_sizing_eval(data, ELM_CONFORM_SOFTKEY_PART);
602    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
603      _conformant_part_sizing_eval(data, ELM_CONFORM_VIRTUAL_KEYPAD_PART);
604    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY)
605      _conformant_part_sizing_eval(data, ELM_CONFORM_CLIPBOARD_PART);
606    else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
607      {
608         Ecore_X_Window zone;
609
610         printf("Keyboard Geometry Changed\n");
611         zone = ecore_x_e_illume_zone_get(ev->win);
612         wd->vkb_state = ecore_x_e_virtual_keyboard_state_get(zone);
613         if (wd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
614           {
615              evas_object_size_hint_min_set(wd->virtualkeypad, -1, 0);
616              evas_object_size_hint_max_set(wd->virtualkeypad, -1, 0);
617           }
618         else
619           _update_autoscroll_objs(data);
620      }
621    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
622      {
623         Ecore_X_Window zone;
624         Ecore_X_Illume_Clipboard_State state;
625
626         zone = ecore_x_e_illume_zone_get(ev->win);
627         state = ecore_x_e_illume_clipboard_state_get(zone);
628
629         if (state != ECORE_X_ILLUME_CLIPBOARD_STATE_ON)
630           {
631              evas_object_size_hint_min_set(wd->clipboard, -1, 0);
632              evas_object_size_hint_max_set(wd->clipboard, -1, 0);
633           }
634         else
635           _update_autoscroll_objs(data);
636      }
637
638    return ECORE_CALLBACK_PASS_ON;
639 }
640 #endif
641
642 EAPI Evas_Object *
643 elm_conformant_add(Evas_Object *parent)
644 {
645    Evas_Object *obj;
646    Evas *e;
647    Widget_Data *wd;
648
649    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
650
651    ELM_SET_WIDTYPE(widtype, "conformant");
652    elm_widget_type_set(obj, "conformant");
653    elm_widget_sub_object_add(parent, obj);
654    elm_widget_data_set(obj, wd);
655    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
656    elm_widget_del_hook_set(obj, _del_hook);
657    elm_widget_theme_hook_set(obj, _theme_hook);
658    elm_widget_can_focus_set(obj, EINA_FALSE);
659    elm_widget_content_set_hook_set(obj, _content_set_hook);
660    elm_widget_content_get_hook_set(obj, _content_get_hook);
661    elm_widget_content_unset_hook_set(obj, _content_unset_hook);
662
663    wd->base = edje_object_add(e);
664    _elm_theme_object_set(obj, wd->base, "conformant", "base", "default");
665    elm_widget_resize_object_set(obj, wd->base);
666
667    _swallow_conformant_parts(obj);
668
669 #ifdef HAVE_ELEMENTARY_X
670    Evas_Object *top = elm_widget_top_get(obj);
671    Ecore_X_Window xwin = elm_win_xwindow_get(top);
672
673    if ((xwin) && (!elm_win_inlined_image_object_get(top)))
674      {
675         wd->prop_hdl = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
676                                                _prop_change, obj);
677         wd->vkb_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
678      }
679    // FIXME: get kbd region prop
680 #endif
681
682    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
683                                        _conformant_move_resize_event_cb, obj);
684    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
685                                        _conformant_move_resize_event_cb, obj);
686
687    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
688
689    _mirrored_set(obj, elm_widget_mirrored_get(obj));
690    _sizing_eval(obj);
691    return obj;
692 }