sync with master
[framework/uifw/elementary.git] / src / lib / elm_conform.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_conform.h"
4
5 #ifndef MIN
6 # define MIN(a, b) ((a) < (b)) ? (a) : (b)
7 #endif
8
9 #ifndef MAX
10 # define MAX(a, b) ((a) < (b)) ? (b) : (a)
11 #endif
12
13 EAPI const char ELM_CONFORMANT_SMART_NAME[] = "elm_conformant";
14 static char CONFORMANT_KEY[] = "_elm_conform_key";
15
16 #ifdef HAVE_ELEMENTARY_X
17 #define SUB_TYPE_COUNT 2
18 static char *sub_type[SUB_TYPE_COUNT] = { "elm_scroller", "elm_genlist" };
19 #endif
20
21
22 static const char INDICATOR_PART[] = "elm.swallow.indicator";
23 static const char VIRTUALKEYPAD_PART[] = "elm.swallow.virtualkeypad";
24 static const char CLIPBOARD_PART[] = "elm.swallow.clipboard";
25 static const char SOFTKEY_PART[] = "elm.swallow.softkey";
26
27 static const char SIG_VIRTUALKEYPAD_STATE_ON[] = "virtualkeypad,state,on";
28 static const char SIG_VIRTUALKEYPAD_STATE_OFF[] = "virtualkeypad,state,off";
29 static const char SIG_CLIPBOARD_STATE_ON[] = "clipboard,state,on";
30 static const char SIG_CLIPBOARD_STATE_OFF[] = "clipboard,state,off";
31
32 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
33    {SIG_VIRTUALKEYPAD_STATE_ON, ""},
34    {SIG_VIRTUALKEYPAD_STATE_OFF, ""},
35    {SIG_CLIPBOARD_STATE_ON, ""},
36    {SIG_CLIPBOARD_STATE_OFF, ""},
37    {NULL, NULL}
38 };
39
40 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
41 {
42    {"icon", "elm.swallow.content"},
43    {NULL, NULL}
44 };
45
46 EVAS_SMART_SUBCLASS_NEW
47   (ELM_CONFORMANT_SMART_NAME, _elm_conformant, Elm_Conformant_Smart_Class,
48   Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
49
50 /* Example of env vars:
51  * ILLUME_KBD="0, 0, 800, 301"
52  * ILLUME_IND="0, 0, 800, 32"
53  * ILLUME_STK="0, 568, 800, 32"
54  */
55 static Eina_Bool
56 _conformant_part_geometry_get_from_env(const char *part,
57                                        int *sx,
58                                        int *sy,
59                                        int *sw,
60                                        int *sh)
61 {
62    const char delimiters[] = " ,;";
63    char *env_val, *token;
64    char buf[PATH_MAX];
65    int tsx, tsy, tsw;
66
67    if (!(env_val = getenv(part))) return EINA_FALSE;
68
69    /* strtok would modify env var if not copied to a buffer */
70    strncpy(buf, env_val, sizeof(buf));
71    buf[PATH_MAX - 1] = '\0';
72
73    token = strtok(buf, delimiters);
74    if (!token) return EINA_FALSE;
75    tsx = atoi(token);
76
77    token = strtok(NULL, delimiters);
78    if (!token) return EINA_FALSE;
79    tsy = atoi(token);
80
81    token = strtok(NULL, delimiters);
82    if (!token) return EINA_FALSE;
83    tsw = atoi(token);
84
85    token = strtok(NULL, delimiters);
86    if (!token) return EINA_FALSE;
87    *sh = atoi(token);
88
89    *sx = tsx;
90    *sy = tsy;
91    *sw = tsw;
92
93    return EINA_TRUE;
94 }
95
96 static void
97 _conformant_part_size_hints_set(Evas_Object *obj,
98                                 Evas_Object *sobj,
99                                 Evas_Coord sx,
100                                 Evas_Coord sy,
101                                 Evas_Coord sw,
102                                 Evas_Coord sh)
103 {
104    Evas_Coord cx, cy, cw, ch;
105    Evas_Coord part_height = 0, part_width = 0;
106
107    evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
108
109    /* Part overlapping with conformant */
110    if ((cx < (sx + sw)) && ((cx + cw) > sx)
111        && (cy < (sy + sh)) && ((cy + ch) > sy))
112      {
113         part_height = MIN((cy + ch), (sy + sh)) - MAX(cy, sy);
114         part_width = MIN((cx + cw), (sx + sw)) - MAX(cx, sx);
115      }
116
117    evas_object_size_hint_min_set(sobj, part_width, part_height);
118    evas_object_size_hint_max_set(sobj, part_width, part_height);
119 }
120
121 static void
122 _conformant_part_sizing_eval(Evas_Object *obj,
123                              Conformant_Part_Type part_type)
124 {
125 #ifdef HAVE_ELEMENTARY_X
126    Ecore_X_Window zone = 0;
127    Evas_Object *top;
128    Ecore_X_Window xwin;
129 #endif
130    int sx = -1, sy = -1, sw = -1, sh = -1;
131
132    ELM_CONFORMANT_DATA_GET(obj, sd);
133
134 #ifdef HAVE_ELEMENTARY_X
135    top = elm_widget_top_get(obj);
136    xwin = elm_win_xwindow_get(top);
137
138    if (xwin)
139      zone = ecore_x_e_illume_zone_get(xwin);
140 #endif
141
142    if (part_type & ELM_CONFORMANT_INDICATOR_PART)
143      {
144         if ((!_conformant_part_geometry_get_from_env
145                ("ILLUME_IND", &sx, &sy, &sw, &sh)) && (xwin))
146           {
147 #ifdef HAVE_ELEMENTARY_X
148              //No information of the indicator geometry, reset the geometry.
149              if (!ecore_x_e_illume_indicator_geometry_get
150                    (zone, &sx, &sy, &sw, &sh))
151                sx = sy = sw = sh = 0;
152 #else
153              ;
154 #endif
155           }
156         if (((sd->rot == 90) || (sd->rot == 270)) && sd->landscape_indicator)
157           _conformant_part_size_hints_set(obj, sd->landscape_indicator, sx, sy, sw, sh);
158         else if (((sd->rot == 0) || (sd->rot == 180)) && sd->portrait_indicator)
159           _conformant_part_size_hints_set(obj, sd->portrait_indicator, sx, sy, sw, sh);
160      }
161
162    if (part_type & ELM_CONFORMANT_VIRTUAL_KEYPAD_PART)
163      {
164         if ((!_conformant_part_geometry_get_from_env
165                ("ILLUME_KBD", &sx, &sy, &sw, &sh)) && (xwin))
166           {
167 #ifdef HAVE_ELEMENTARY_X
168              //No information of the keyboard geometry, reset the geometry.
169 #ifdef __linux__
170                  DBG("[KEYPAD]:pid=%d, xwin=0x%x, zone=0x%x: no env value and check window property.", getpid(), xwin, zone);
171 #endif
172              if (!ecore_x_e_illume_keyboard_geometry_get(xwin, &sx, &sy, &sw, &sh))
173                {
174                           DBG("[KEYPAD]:no window property, check zone property.");
175                                   if (!ecore_x_e_illume_keyboard_geometry_get(zone, &sx, &sy, &sw, &sh))
176                     {
177                                DBG("[KEYPAD]:no zone property, reset value.");
178                        sx = sy = sw = sh = 0;
179                                     }
180                }
181 #else
182              ;
183 #endif
184           }
185                 DBG("[KEYPAD]: size(%d,%d, %dx%d).", sx, sy, sw, sh);
186         _conformant_part_size_hints_set
187           (obj, sd->virtualkeypad, sx, sy, sw, sh);
188      }
189
190    if (part_type & ELM_CONFORMANT_SOFTKEY_PART)
191      {
192         if ((!_conformant_part_geometry_get_from_env
193                ("ILLUME_STK", &sx, &sy, &sw, &sh)) && (xwin))
194           {
195 #ifdef HAVE_ELEMENTARY_X
196              //No information of the softkey geometry, reset the geometry.
197              if (!ecore_x_e_illume_softkey_geometry_get
198                    (zone, &sx, &sy, &sw, &sh))
199                sx = sy = sw = sh = 0;
200 #else
201              ;
202 #endif
203           }
204         _conformant_part_size_hints_set(obj, sd->softkey, sx, sy, sw, sh);
205      }
206    if (part_type & ELM_CONFORMANT_CLIPBOARD_PART)
207      {
208         if ((!_conformant_part_geometry_get_from_env
209                ("ILLUME_CB", &sx, &sy, &sw, &sh)) && (xwin))
210           {
211 #ifdef HAVE_ELEMENTARY_X
212              //No information of the clipboard geometry, reset the geometry.
213              if (!ecore_x_e_illume_clipboard_geometry_get
214                    (zone, &sx, &sy, &sw, &sh))
215                sx = sy = sw = sh = 0;
216 #else
217              ;
218 #endif
219           }
220         _conformant_part_size_hints_set(obj, sd->clipboard, sx, sy, sw, sh);
221      }
222 }
223
224 static void
225 _conformant_parts_swallow(Evas_Object *obj)
226 {
227    Evas *e;
228    Elm_Widget_Smart_Data *wd;
229
230    ELM_CONFORMANT_DATA_GET(obj, sd);
231
232    wd = ELM_WIDGET_DATA(sd);
233    e = evas_object_evas_get(obj);
234
235    sd->scroller = NULL;
236
237    //Virtual Keyboard
238    if (edje_object_part_exists(wd->resize_obj, VIRTUALKEYPAD_PART))
239      {
240         if (!sd->virtualkeypad)
241           {
242              sd->virtualkeypad = evas_object_rectangle_add(e);
243              elm_widget_sub_object_add(obj, sd->virtualkeypad);
244              evas_object_size_hint_max_set(sd->virtualkeypad, -1, 0);
245           }
246         else
247           _conformant_part_sizing_eval(obj, ELM_CONFORMANT_VIRTUAL_KEYPAD_PART);
248
249         evas_object_color_set(sd->virtualkeypad, 0, 0, 0, 0);
250         elm_layout_content_set(obj, VIRTUALKEYPAD_PART, sd->virtualkeypad);
251      }
252    else if (sd->virtualkeypad)
253      {
254         evas_object_del(sd->virtualkeypad);
255         sd->virtualkeypad = NULL;
256      }
257
258    //Clipboard
259    if (edje_object_part_exists(wd->resize_obj, CLIPBOARD_PART))
260      {
261         if (!sd->clipboard)
262           {
263              sd->clipboard = evas_object_rectangle_add(e);
264              evas_object_size_hint_min_set(sd->clipboard, -1, 0);
265              evas_object_size_hint_max_set(sd->clipboard, -1, 0);
266           }
267         else
268           _conformant_part_sizing_eval(obj, ELM_CONFORMANT_CLIPBOARD_PART);
269
270         evas_object_color_set(sd->clipboard, 0, 0, 0, 0);
271         elm_layout_content_set(obj, CLIPBOARD_PART, sd->clipboard);
272      }
273    else if (sd->clipboard)
274      {
275         evas_object_del(sd->clipboard);
276         sd->clipboard = NULL;
277      }
278
279    //Softkey
280    if (edje_object_part_exists(wd->resize_obj, SOFTKEY_PART))
281      {
282         if (!sd->softkey)
283           {
284              sd->softkey = evas_object_rectangle_add(e);
285              evas_object_size_hint_min_set(sd->softkey, -1, 0);
286              evas_object_size_hint_max_set(sd->softkey, -1, 0);
287           }
288         else
289           _conformant_part_sizing_eval(obj, ELM_CONFORMANT_SOFTKEY_PART);
290
291         evas_object_color_set(sd->softkey, 0, 0, 0, 0);
292         elm_layout_content_set(obj, SOFTKEY_PART, sd->softkey);
293      }
294    else if (sd->softkey)
295      {
296         evas_object_del(sd->softkey);
297         sd->softkey = NULL;
298      }
299 }
300
301 static Eina_Bool
302 _port_indicator_connect_cb(void *data)
303 {
304    const char   *indicator_serv_name;
305    Elm_Conformant_Smart_Data *sd = data;
306    int rot;
307
308    if (!sd) return ECORE_CALLBACK_CANCEL;
309    if (sd->indmode != ELM_WIN_INDICATOR_SHOW)
310      {
311         sd->port_indi_timer = NULL;
312         return ECORE_CALLBACK_CANCEL;
313      }
314    rot = (int) evas_object_data_get(sd->portrait_indicator, CONFORMANT_KEY);
315    indicator_serv_name = elm_config_indicator_service_get(rot);
316    if (!indicator_serv_name)
317      {
318         DBG("Conformant cannot find indicator service name: Rotation=%d\n",rot);
319         sd->port_indi_timer = NULL;
320         return ECORE_CALLBACK_CANCEL;
321      }
322    if (elm_plug_connect(sd->portrait_indicator, indicator_serv_name, 0, EINA_FALSE))
323      {
324         DBG("Conformant connect to server[%s]\n", indicator_serv_name);
325         sd->port_indi_timer = NULL;
326         return ECORE_CALLBACK_CANCEL;
327      }
328    return ECORE_CALLBACK_RENEW;
329 }
330
331
332 static Eina_Bool
333 _land_indicator_connect_cb(void *data)
334 {
335    const char   *indicator_serv_name;
336    Elm_Conformant_Smart_Data *sd = data;
337    int rot;
338
339    if (!sd) return ECORE_CALLBACK_CANCEL;
340    if (sd->indmode != ELM_WIN_INDICATOR_SHOW)
341      {
342         sd->land_indi_timer = NULL;
343         return ECORE_CALLBACK_CANCEL;
344      }
345    rot = (int) evas_object_data_get(sd->landscape_indicator, CONFORMANT_KEY);
346    indicator_serv_name = elm_config_indicator_service_get(rot);
347    if (!indicator_serv_name)
348      {
349         DBG("Conformant cannot find indicator service name: Rotation=%d\n",rot);
350         sd->land_indi_timer = NULL;
351         return ECORE_CALLBACK_CANCEL;
352      }
353    if (elm_plug_connect(sd->landscape_indicator, indicator_serv_name, 0, EINA_FALSE))
354      {
355         DBG("Conformant connect to server[%s]\n", indicator_serv_name);
356         sd->land_indi_timer = NULL;
357         return ECORE_CALLBACK_CANCEL;
358      }
359    return ECORE_CALLBACK_RENEW;
360 }
361
362 static void
363 _land_indicator_disconnected(void *data,
364                              Evas_Object *obj __UNUSED__,
365                              void *event_info __UNUSED__)
366 {
367    Evas_Object *conform = data;
368
369    ELM_CONFORMANT_DATA_GET(conform, sd);
370
371    sd->land_indi_timer = ecore_timer_add(1, _land_indicator_connect_cb, sd);
372 }
373
374 static void
375 _port_indicator_disconnected(void *data,
376                              Evas_Object *obj __UNUSED__,
377                              void *event_info __UNUSED__)
378 {
379    Evas_Object *conform = data;
380
381    ELM_CONFORMANT_DATA_GET(conform, sd);
382
383    sd->port_indi_timer = ecore_timer_add(1, _port_indicator_connect_cb, sd);
384 }
385
386 static void
387 _access_activate_cb(void *data,
388                     Evas_Object *part_obj,
389                     Elm_Object_Item *item __UNUSED__)
390 {
391    Evas_Coord x, y, w, h;
392
393 #ifdef HAVE_ELEMENTARY_X
394    Evas_Object *top = elm_widget_top_get(data);
395    Ecore_X_Window xwin = elm_win_xwindow_get(top);
396
397    evas_object_geometry_get(part_obj, &x, &y, &w, &h);
398
399    ecore_x_mouse_down_send(xwin, (x + (w / 2)), (y + (h / 2)), 1);
400    ecore_x_mouse_up_send(xwin, (x + (w / 2)), (y + (h / 2)), 1);
401 #endif
402 }
403
404 static void
405 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
406 {
407    Evas_Object *ao;
408
409    ELM_CONFORMANT_DATA_GET(obj, sd);
410
411    if (is_access)
412      {
413         ao = _elm_access_edje_object_part_object_register
414                (obj, ELM_WIDGET_DATA(sd)->resize_obj, "access");
415
416         _elm_access_text_set(_elm_access_object_get(ao),
417           ELM_ACCESS_TYPE, "Indicator, Double Tap To Open");
418         _elm_access_activate_callback_set
419           (_elm_access_object_get(ao), _access_activate_cb, obj);
420
421         edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
422           "elm,state,access,on", "elm");
423      }
424    else
425      {
426         _elm_access_edje_object_part_object_unregister
427           (obj, ELM_WIDGET_DATA(sd)->resize_obj, "access");
428
429         edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
430           "elm,state,access,off", "elm");
431      }
432 }
433
434 static const char PLUG_KEY[] = "__Plug_Ecore_Evas";
435 // procotol version - change this as needed
436 #define MSG_DOMAIN_CONTROL_INDICATOR 0x10001
437 #define MSG_ID_INDICATOR_REPEAT_EVENT 0x10002
438 #define MSG_ID_INDICATOR_ROTATION 0x10003
439 #define MSG_ID_INDICATOR_OPACITY 0X1004
440 #define MSG_ID_INDICATOR_TYPE 0X1005
441
442 static void
443 _plug_msg_handle(Ecore_Evas *ee, int msg_domain, int msg_id, void *data, int size)
444 {
445    Evas_Object *conformant;
446
447    if (!data) return;
448    DBG("Receive msg from plug ee=%p msg_domain=%x msg_id=%x size=%d", ee, msg_domain, msg_id, size);
449    //get plug object form ee
450    conformant = (Evas_Object *)ecore_evas_data_get(ee, CONFORMANT_KEY);
451    ELM_CONFORMANT_DATA_GET(conformant, sd);
452    if (msg_domain == MSG_DOMAIN_CONTROL_INDICATOR)
453      {
454         if (msg_id == MSG_ID_INDICATOR_REPEAT_EVENT)
455           {
456              int *repeat = data;
457              DBG("Receive repeat event change message:(%d)", *repeat);
458           }
459         if (msg_id == MSG_ID_INDICATOR_TYPE)
460           {
461              Elm_Win_Indicator_Type_Mode *indi_t_mode = data;
462              Evas_Object *win = elm_widget_top_get(conformant);
463              DBG("Receive indicator type change message:(%d)", *indi_t_mode);
464              elm_win_indicator_type_set(win, *indi_t_mode);
465           }
466          }
467 }
468
469 static Evas_Object *
470 _create_portrait_indicator(Evas_Object *obj)
471 {
472    Evas_Object *port_indicator = NULL;
473    Ecore_Evas *indicator_ee = NULL;
474    const char *port_indicator_serv_name;
475
476    ELM_CONFORMANT_DATA_GET(obj, sd);
477
478    port_indicator_serv_name = elm_config_indicator_service_get(sd->rot);
479    if (!port_indicator_serv_name)
480      {
481         DBG("Conformant cannot get portrait indicator service name\n");
482         return NULL;
483      }
484
485    port_indicator = elm_plug_add(obj);
486    if (!port_indicator)
487      {
488         DBG("Conformant cannot create plug to server[%s]\n", port_indicator_serv_name);
489         return NULL;
490      }
491
492    if (!elm_plug_connect(port_indicator, port_indicator_serv_name, 0, EINA_FALSE))
493      {
494         DBG("Conformant cannot connect to server[%s]\n", port_indicator_serv_name);
495         return NULL;
496      }
497
498    //callback to deal with extn socket message
499    indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(port_indicator));
500    DBG("This is portrait indicator's ee=%p.", indicator_ee);
501    ecore_evas_callback_msg_handle_set(indicator_ee, _plug_msg_handle);
502    ecore_evas_data_set(indicator_ee, CONFORMANT_KEY, obj);
503
504    DBG("The rotation value of portrait indicator was changed:(%d)", sd->rot);
505    ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
506
507    elm_widget_sub_object_add(obj, port_indicator);
508    evas_object_smart_callback_add(port_indicator, "image.deleted", _port_indicator_disconnected, obj);
509
510    evas_object_size_hint_min_set(port_indicator, -1, 0);
511    evas_object_size_hint_max_set(port_indicator, -1, 0);
512
513    /* access */
514    if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
515
516    return port_indicator;
517 }
518
519 static Evas_Object *
520 _create_landscape_indicator(Evas_Object *obj)
521 {
522    Ecore_Evas *indicator_ee = NULL;
523    Evas_Object *land_indicator = NULL;
524    const char *land_indicator_serv_name;
525
526    ELM_CONFORMANT_DATA_GET(obj, sd);
527
528    land_indicator_serv_name = elm_config_indicator_service_get(sd->rot);
529    if (!land_indicator_serv_name)
530      {
531         DBG("Conformant cannot get portrait indicator service name\n");
532         return NULL;
533      }
534
535    land_indicator = elm_plug_add(obj);
536    if (!land_indicator)
537      {
538         DBG("Conformant cannot create plug to server[%s]\n", land_indicator_serv_name);
539         return NULL;
540      }
541
542    if (!elm_plug_connect(land_indicator, land_indicator_serv_name, 0, EINA_FALSE))
543      {
544         DBG("Conformant cannot connect to server[%s]\n", land_indicator_serv_name);
545         return NULL;
546      }
547
548    //callback to deal with extn socket message
549    indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(land_indicator));
550    ecore_evas_data_set(indicator_ee, CONFORMANT_KEY, obj);
551    DBG("This is landscape indicator's ee=%p.", indicator_ee);
552    ecore_evas_callback_msg_handle_set(indicator_ee, _plug_msg_handle);
553    DBG("The rotation value of landscape indicator was changed:(%d)", sd->rot);
554    ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
555
556    elm_widget_sub_object_add(obj, land_indicator);
557    evas_object_smart_callback_add(land_indicator, "image.deleted",_land_indicator_disconnected, obj);
558
559    evas_object_size_hint_min_set(land_indicator, -1, 0);
560    evas_object_size_hint_max_set(land_indicator, -1, 0);
561
562    /* access */
563    if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
564
565    return land_indicator;
566 }
567
568 static void
569 _indicator_mode_set(Evas_Object *conformant, Elm_Win_Indicator_Mode indmode)
570 {
571    Evas_Object *old_indi = NULL;
572    Elm_Widget_Smart_Data *wd;
573    ELM_CONFORMANT_DATA_GET(conformant, sd);
574    sd->indmode = indmode;
575
576    wd = ELM_WIDGET_DATA(sd);
577
578    if (!edje_object_part_exists(wd->resize_obj, INDICATOR_PART))
579      return;
580
581    if (indmode == ELM_WIN_INDICATOR_SHOW)
582      {
583         old_indi = elm_layout_content_get(conformant, INDICATOR_PART);
584
585         //create new indicator
586         if (!old_indi)
587           {
588              if ((sd->rot == 90)||(sd->rot == 270))
589                {
590                   if (!sd->landscape_indicator)
591                     sd->landscape_indicator = _create_landscape_indicator(conformant);
592
593                   if (!sd->landscape_indicator) return;
594
595                   evas_object_show(sd->landscape_indicator);
596                   elm_layout_content_set(conformant, INDICATOR_PART, sd->landscape_indicator);
597                }
598              else
599                {
600                   if (!sd->portrait_indicator)
601                     sd->portrait_indicator = _create_portrait_indicator(conformant);
602
603                   if (!sd->portrait_indicator) return;
604
605                   evas_object_show(sd->portrait_indicator);
606                   elm_layout_content_set(conformant, INDICATOR_PART, sd->portrait_indicator);
607                }
608
609           }
610         elm_object_signal_emit(conformant, "elm,state,indicator,show", "elm");
611      }
612    else
613      {
614         old_indi = elm_layout_content_get(conformant, INDICATOR_PART);
615         if (old_indi)
616           {
617              evas_object_hide(old_indi);
618           }
619         elm_object_signal_emit(conformant, "elm,state,indicator,hide", "elm");
620      }
621 }
622
623 static void
624 _indicator_opacity_set(Evas_Object *conformant, Elm_Win_Indicator_Opacity_Mode ind_o_mode)
625 {
626    ELM_CONFORMANT_DATA_GET(conformant, sd);
627    sd->ind_o_mode = ind_o_mode;
628    //TODO: opacity change
629    //send indicator information
630    if (sd->landscape_indicator)
631      {
632         Ecore_Evas *indicator_ee = NULL;
633         DBG("The opacity mode of landscape indicator was changed:(%d)", ind_o_mode);
634         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->landscape_indicator));
635         ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_OPACITY, &(sd->ind_o_mode), sizeof(Elm_Win_Indicator_Opacity_Mode));
636      }
637    if (sd->portrait_indicator)
638      {
639         Ecore_Evas *indicator_ee = NULL;
640         DBG("The opacity mode of portrait indicator was changed:(%d)", ind_o_mode);
641         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->portrait_indicator));
642         ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_OPACITY, &(sd->ind_o_mode), sizeof(Elm_Win_Indicator_Opacity_Mode));
643      }
644 }
645
646 static void
647 _on_indicator_mode_changed(void *data,
648                     Evas_Object *obj,
649                     void *event_info __UNUSED__)
650 {
651    Evas_Object *conformant = data;
652    Evas_Object *win = obj;
653
654    Elm_Win_Indicator_Mode indmode;
655    Elm_Win_Indicator_Opacity_Mode ind_o_mode;
656
657    ELM_CONFORMANT_DATA_GET(conformant, sd);
658
659    indmode = elm_win_indicator_mode_get(win);
660    ind_o_mode = elm_win_indicator_opacity_get(win);
661    if (indmode != sd->indmode)
662      _indicator_mode_set(conformant, indmode);
663    if (ind_o_mode != sd->ind_o_mode)
664      _indicator_opacity_set(conformant, ind_o_mode);
665 }
666
667 static void
668 _on_rotation_changed(void *data,
669               Evas_Object *obj,
670               void *event_info __UNUSED__)
671 {
672    int rot = 0;
673    Evas_Object *win = obj;
674    Evas_Object *conformant = data;
675    Evas_Object *old_indi = NULL;
676
677    ELM_CONFORMANT_DATA_GET(data, sd);
678
679    rot = elm_win_rotation_get(win);
680
681    if (rot == sd->rot) return;
682
683    sd->rot = rot;
684    //send indicator information
685    if (sd->landscape_indicator)
686      {
687         Ecore_Evas *indicator_ee = NULL;
688         DBG("The rotation value of landscape indicator was changed:(%d)", rot);
689         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->landscape_indicator));
690         ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
691      }
692    if (sd->portrait_indicator)
693      {
694         Ecore_Evas *indicator_ee = NULL;
695         DBG("The rotation value of portrait indicator was changed:(%d)", rot);
696         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->portrait_indicator));
697         ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
698      }
699    old_indi = elm_layout_content_unset(conformant, INDICATOR_PART);
700    /* this means ELM_WIN_INDICATOR_SHOW never be set.we don't need to change indicator type*/
701    if (!old_indi) return;
702    evas_object_hide(old_indi);
703
704    if ((rot == 90) || (rot == 270))
705      {
706         if (!sd->landscape_indicator)
707           sd->landscape_indicator = _create_landscape_indicator(conformant);
708
709         if (!sd->landscape_indicator) return;
710
711         evas_object_show(sd->landscape_indicator);
712         evas_object_data_set(sd->landscape_indicator, CONFORMANT_KEY, (void *) rot);
713         elm_layout_content_set(conformant, INDICATOR_PART, sd->landscape_indicator);
714      }
715    else
716      {
717         if (!sd->portrait_indicator)
718           sd->portrait_indicator = _create_portrait_indicator(conformant);
719
720         if (!sd->portrait_indicator) return;
721
722         evas_object_show(sd->portrait_indicator);
723         evas_object_data_set(sd->portrait_indicator, CONFORMANT_KEY, (void *) rot);
724         elm_layout_content_set(conformant, INDICATOR_PART, sd->portrait_indicator);
725      }
726 }
727
728 static Eina_Bool
729 _elm_conformant_smart_theme(Evas_Object *obj)
730 {
731    if (!ELM_WIDGET_CLASS(_elm_conformant_parent_sc)->theme(obj))
732      return EINA_FALSE;
733
734    _conformant_parts_swallow(obj);
735
736    elm_layout_sizing_eval(obj);
737
738    return EINA_TRUE;
739 }
740
741 // unused now - but meant to be for making sure the focused widget is always
742 // visible when the vkbd comes and goes by moving the conformant obj (and thus
743 // its children) to  show the focused widget (and if focus changes follow)
744 /*
745    static Evas_Object *
746    _focus_object_get(const Evas_Object *obj)
747    {
748    Evas_Object *win, *foc;
749
750    win = elm_widget_top_get(obj);
751    if (!win) return NULL;
752    foc = elm_widget_top_get(win);
753    }
754
755    static void
756    _focus_object_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
757    {
758    evas_object_geometry_get(obj, x, y, w, h);
759    }
760
761    static void
762    _focus_change_del(void *data, Evas_Object *obj, void *event_info)
763    {
764    // called from toplevel when the focused window shanges
765    }
766
767    static void
768    _autoscroll_move(Evas_Object *obj)
769    {
770    // move conformant edje by delta to show focused widget
771    }
772
773    static void
774    _autoscroll_mode_enable(Evas_Object *obj)
775    {
776    // called when autoscroll mode should be on - content area smaller than
777    // its min size
778    // 1. get focused object
779    // 2. if not in visible conformant area calculate delta needed to
780    //    get it in
781    // 3. store delta and call _autoscroll_move() which either asanimates
782    //    or jumps right there
783    }
784
785    static void
786    _autoscroll_mode_disable(Evas_Object *obj)
787    {
788    // called when autoscroll mode should be off - set delta to 0 and
789    // call _autoscroll_move()
790    }
791  */
792
793 static void
794 _move_resize_cb(void *data __UNUSED__,
795                 Evas *e __UNUSED__,
796                 Evas_Object *obj,
797                 void *event_info __UNUSED__)
798 {
799    Conformant_Part_Type part_type;
800
801    part_type = (ELM_CONFORMANT_INDICATOR_PART |
802                 ELM_CONFORMANT_SOFTKEY_PART |
803                 ELM_CONFORMANT_VIRTUAL_KEYPAD_PART |
804                 ELM_CONFORMANT_CLIPBOARD_PART);
805
806    _conformant_part_sizing_eval(obj, part_type);
807 }
808
809 static void
810 _show_region_job(void *data)
811 {
812    Evas_Object *focus_obj;
813
814    ELM_CONFORMANT_DATA_GET(data, sd);
815
816    focus_obj = elm_widget_focused_object_get(data);
817    if (focus_obj)
818      {
819         Evas_Coord x, y, w, h;
820
821         elm_widget_show_region_get(focus_obj, &x, &y, &w, &h);
822
823
824         if (h < _elm_config->finger_size)
825           h = _elm_config->finger_size;
826
827         elm_widget_show_region_set(focus_obj, x, y, w, h, EINA_TRUE);
828      }
829
830    sd->show_region_job = NULL;
831 }
832
833 // showing the focused/important region.
834 #ifdef HAVE_ELEMENTARY_X
835 static void
836 _on_content_resize(void *data,
837                    Evas *e __UNUSED__,
838                    Evas_Object *obj __UNUSED__,
839                    void *event_info __UNUSED__)
840 {
841    ELM_CONFORMANT_DATA_GET(data, sd);
842
843    if ((sd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) &&
844        (sd->clipboard_state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF))
845      return;
846
847    if (sd->show_region_job) ecore_job_del(sd->show_region_job);
848    sd->show_region_job = ecore_job_add(_show_region_job, data);
849 }
850
851 #endif
852
853 #ifdef HAVE_ELEMENTARY_X
854 static void
855 _autoscroll_objects_update(void *data)
856 {
857    int i;
858    const char *type;
859    Evas_Object *sub, *top_scroller = NULL;
860
861    ELM_CONFORMANT_DATA_GET(data, sd);
862
863    sub = elm_widget_focused_object_get(data);
864    //Look up for top most scroller in the focus object hierarchy
865    //inside Conformant.
866
867    while (sub)
868      {
869         type = elm_widget_type_get(sub);
870         if (!strcmp(type, ELM_CONFORMANT_SMART_NAME)) break;
871
872         for (i = 0; i < SUB_TYPE_COUNT; i++)
873           if (!strcmp(type, sub_type[i]))
874             {
875                top_scroller = sub;
876                break;
877             }
878         sub = elm_object_parent_widget_get(sub);
879      }
880
881    //If the scroller got changed by app, replace it.
882    if (top_scroller != sd->scroller)
883      {
884         if (sd->scroller)
885           evas_object_event_callback_del
886             (sd->scroller, EVAS_CALLBACK_RESIZE, _on_content_resize);
887         sd->scroller = top_scroller;
888
889         if (sd->scroller)
890           evas_object_event_callback_add
891             (sd->scroller, EVAS_CALLBACK_RESIZE, _on_content_resize, data);
892      }
893 }
894
895 static void
896 _virtualkeypad_state_change(Evas_Object *obj, Ecore_X_Event_Window_Property *ev)
897 {
898    ELM_CONFORMANT_DATA_GET(obj, sd);
899
900    Ecore_X_Window zone = ecore_x_e_illume_zone_get(ev->win);
901    Ecore_X_Virtual_Keyboard_State state =
902       ecore_x_e_virtual_keyboard_state_get(ev->win);
903
904    DBG("[KEYPAD]:window's state win=0x%x, state=%d.", ev->win, state);
905    if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN)
906      {
907         state = ecore_x_e_virtual_keyboard_state_get(zone);
908         DBG("[KEYPAD]:zone's state zone=0x%x, state=%d.", zone, state);
909      }
910
911    if (sd->vkb_state == state) return;
912    sd->vkb_state = state;
913
914    if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
915      {
916         DBG("[KEYPAD]:ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF");
917         _conformant_part_sizing_eval(obj, ELM_CONFORMANT_VIRTUAL_KEYPAD_PART);
918         // Tizen Only - SIP regions for virtual keypad and clipboard are the same in Tizen
919         if (sd->clipboard_state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF)
920           elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_NONE);
921         evas_object_smart_callback_call(obj, SIG_VIRTUALKEYPAD_STATE_OFF, NULL);
922      }
923    else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
924      {
925         DBG("[KEYPAD]:ECORE_X_VIRTUAL_KEYBOARD_STATE_ON");
926         _conformant_part_sizing_eval(obj, ELM_CONFORMANT_VIRTUAL_KEYPAD_PART);
927         elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_COMPRESS);
928         _autoscroll_objects_update(obj);
929         evas_object_smart_callback_call(obj, SIG_VIRTUALKEYPAD_STATE_ON, NULL);
930      }
931 }
932
933 static void
934 _clipboard_state_change(Evas_Object *obj, Ecore_X_Event_Window_Property *ev)
935 {
936    ELM_CONFORMANT_DATA_GET(obj, sd);
937
938    Ecore_X_Window zone = ecore_x_e_illume_zone_get(ev->win);
939    Ecore_X_Illume_Clipboard_State state =
940       ecore_x_e_illume_clipboard_state_get(ev->win);
941
942    DBG("[CLIPBOARD]:window's state win=0x%x, state=%d.", ev->win, state);
943
944    if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_UNKNOWN)
945      {
946         state = ecore_x_e_illume_clipboard_state_get(ev->win);
947         DBG("[CLIPBOARD]:zone's state zone=0x%x, state=%d.", zone, state);
948      }
949
950    if (sd->clipboard_state == state) return;
951    sd->clipboard_state = state;
952
953    if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF)
954      {
955         evas_object_size_hint_min_set(sd->clipboard, -1, 0);
956         evas_object_size_hint_max_set(sd->clipboard, -1, 0);
957         // Tizen Only - SIP regions for virtual keypad and clipboard are the same in Tizen
958         if (sd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
959           elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_NONE);
960         evas_object_smart_callback_call(obj, SIG_CLIPBOARD_STATE_OFF, NULL);
961      }
962    else if(state == ECORE_X_ILLUME_CLIPBOARD_STATE_ON)
963      {
964         elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_COMPRESS);
965         _autoscroll_objects_update(obj);
966         evas_object_smart_callback_call(obj, SIG_CLIPBOARD_STATE_ON, NULL);
967      }
968 }
969
970 static Eina_Bool
971 _on_prop_change(void *data,
972                 int type __UNUSED__,
973                 void *event)
974 {
975    Ecore_X_Event_Window_Property *ev = event;
976
977    int pid = 0;
978
979 #ifdef __linux__
980    pid = (int)getpid();
981 #endif
982
983    if (ev->atom == ECORE_X_ATOM_E_ILLUME_ZONE)
984      {
985                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_ZONE.\n", pid, ev->win);
986         Conformant_Part_Type part_type;
987
988         part_type = (ELM_CONFORMANT_INDICATOR_PART |
989                      ELM_CONFORMANT_SOFTKEY_PART |
990                      ELM_CONFORMANT_VIRTUAL_KEYPAD_PART |
991                      ELM_CONFORMANT_CLIPBOARD_PART);
992
993         _conformant_part_sizing_eval(data, part_type);
994      }
995    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
996      {
997                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY.", pid, ev->win);
998         _conformant_part_sizing_eval(data, ELM_CONFORMANT_INDICATOR_PART);
999          }
1000    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
1001      {
1002                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY.", pid, ev->win);
1003         _conformant_part_sizing_eval(data, ELM_CONFORMANT_SOFTKEY_PART);
1004          }
1005    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
1006      {
1007                 DBG("[KEYPAD]:pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY.", pid, ev->win);
1008         _conformant_part_sizing_eval(data, ELM_CONFORMANT_VIRTUAL_KEYPAD_PART);
1009      }
1010    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY)
1011      {
1012                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY.", pid, ev->win);
1013         _conformant_part_sizing_eval(data, ELM_CONFORMANT_CLIPBOARD_PART);
1014      }
1015    else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
1016      {
1017                 DBG("[KEYPAD]:pid=%d, win=0x%x, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE.", pid, ev->win);
1018         _virtualkeypad_state_change(data, ev);
1019      }
1020    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
1021      {
1022                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE.", pid, ev->win);
1023         _clipboard_state_change(data, ev);
1024      }
1025
1026    return ECORE_CALLBACK_PASS_ON;
1027 }
1028
1029 #endif
1030
1031 static void
1032 _elm_conformant_smart_add(Evas_Object *obj)
1033 {
1034    EVAS_SMART_DATA_ALLOC(obj, Elm_Conformant_Smart_Data);
1035
1036    ELM_WIDGET_CLASS(_elm_conformant_parent_sc)->base.add(obj);
1037
1038    elm_widget_can_focus_set(obj, EINA_FALSE);
1039
1040    elm_layout_theme_set(obj, "conformant", "base", elm_widget_style_get(obj));
1041
1042    _conformant_parts_swallow(obj);
1043
1044    evas_object_event_callback_add
1045      (obj, EVAS_CALLBACK_RESIZE, _move_resize_cb, obj);
1046    evas_object_event_callback_add
1047      (obj, EVAS_CALLBACK_MOVE, _move_resize_cb, obj);
1048
1049    elm_layout_sizing_eval(obj);
1050 }
1051
1052 static void
1053 _elm_conformant_smart_del(Evas_Object *obj)
1054 {
1055    Evas_Object *top;
1056    ELM_CONFORMANT_DATA_GET(obj, sd);
1057
1058 #ifdef HAVE_ELEMENTARY_X
1059    if (sd->prop_hdl) ecore_event_handler_del(sd->prop_hdl);
1060 #endif
1061
1062    if (sd->show_region_job) ecore_job_del(sd->show_region_job);
1063    if (sd->port_indi_timer) ecore_timer_del(sd->port_indi_timer);
1064    if (sd->land_indi_timer) ecore_timer_del(sd->land_indi_timer);
1065    if (sd->portrait_indicator)
1066      evas_object_del(sd->portrait_indicator);
1067    if (sd->landscape_indicator)
1068      evas_object_del(sd->landscape_indicator);
1069    top = elm_widget_top_get(obj);
1070    evas_object_data_set(top, "\377 elm,conformant", NULL);
1071
1072    ELM_WIDGET_CLASS(_elm_conformant_parent_sc)->base.del(obj);
1073 }
1074
1075 static void
1076 _elm_conformant_smart_parent_set(Evas_Object *obj,
1077                                  Evas_Object *parent)
1078 {
1079 #ifdef HAVE_ELEMENTARY_X
1080    Evas_Object *top = elm_widget_top_get(parent);
1081    Ecore_X_Window xwin = elm_win_xwindow_get(parent);
1082
1083    if ((xwin) && (!elm_win_inlined_image_object_get(top)))
1084      {
1085         ELM_CONFORMANT_DATA_GET(obj, sd);
1086
1087         sd->prop_hdl = ecore_event_handler_add
1088             (ECORE_X_EVENT_WINDOW_PROPERTY, _on_prop_change, obj);
1089         sd->vkb_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
1090         sd->clipboard_state = ECORE_X_ILLUME_CLIPBOARD_STATE_OFF;
1091      }
1092    // FIXME: get kbd region prop
1093 #endif
1094 }
1095
1096 static void
1097 _elm_conformant_smart_access(Evas_Object *obj, Eina_Bool is_access)
1098 {
1099    ELM_CONFORMANT_CHECK(obj);
1100
1101    _access_obj_process(obj, is_access);
1102 }
1103
1104 static void
1105 _elm_conformant_smart_set_user(Elm_Conformant_Smart_Class *sc)
1106 {
1107    ELM_WIDGET_CLASS(sc)->base.add = _elm_conformant_smart_add;
1108    ELM_WIDGET_CLASS(sc)->base.del = _elm_conformant_smart_del;
1109
1110    ELM_WIDGET_CLASS(sc)->parent_set = _elm_conformant_smart_parent_set;
1111    ELM_WIDGET_CLASS(sc)->theme = _elm_conformant_smart_theme;
1112    ELM_WIDGET_CLASS(sc)->access = _elm_conformant_smart_access;
1113
1114    ELM_LAYOUT_CLASS(sc)->content_aliases = _content_aliases;
1115 }
1116
1117 EAPI const Elm_Conformant_Smart_Class *
1118 elm_conformant_smart_class_get(void)
1119 {
1120    static Elm_Conformant_Smart_Class _sc =
1121      ELM_CONFORMANT_SMART_CLASS_INIT_NAME_VERSION(ELM_CONFORMANT_SMART_NAME);
1122    static const Elm_Conformant_Smart_Class *class = NULL;
1123    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1124
1125    if (class)
1126      return class;
1127
1128    _elm_conformant_smart_set(&_sc);
1129    esc->callbacks = _smart_callbacks;
1130    class = &_sc;
1131
1132    return class;
1133 }
1134
1135 EAPI Evas_Object *
1136 elm_conformant_add(Evas_Object *parent)
1137 {
1138    Evas_Object *obj;
1139    Evas_Object *top;
1140
1141    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1142
1143    obj = elm_widget_add(_elm_conformant_smart_class_new(), parent);
1144    if (!obj) return NULL;
1145
1146    if (!elm_widget_sub_object_add(parent, obj))
1147      ERR("could not add %p as sub object of %p", obj, parent);
1148
1149    ELM_CONFORMANT_DATA_GET(obj, sd);
1150
1151    top = elm_widget_top_get(obj);
1152    _on_indicator_mode_changed(obj, top, NULL);
1153    _on_rotation_changed(obj, top, NULL);
1154
1155    sd->indmode = elm_win_indicator_mode_get(top);
1156    sd->ind_o_mode = elm_win_indicator_opacity_get(top);
1157    sd->rot = elm_win_rotation_get(top);
1158    evas_object_data_set(top, "\377 elm,conformant", obj);
1159
1160    evas_object_smart_callback_add
1161      (top, "indicator,prop,changed", _on_indicator_mode_changed, obj);
1162    evas_object_smart_callback_add
1163      (top, "rotation,changed", _on_rotation_changed, obj);
1164
1165    return obj;
1166 }