elementary/map - map supports language,changed
[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
387 static const char PLUG_KEY[] = "__Plug_Ecore_Evas";
388 // procotol version - change this as needed
389 #define MSG_DOMAIN_CONTROL_INDICATOR 0x10001
390 #define MSG_ID_INDICATOR_REPEAT_EVENT 0x10002
391 #define MSG_ID_INDICATOR_ROTATION 0x10003
392 #define MSG_ID_INDICATOR_OPACITY 0X1004
393 #define MSG_ID_INDICATOR_TYPE 0X1005
394
395 static void
396 _plug_msg_handle(Ecore_Evas *ee, int msg_domain, int msg_id, void *data, int size)
397 {
398    Evas_Object *conformant;
399
400    if (!data) return;
401    DBG("Receive msg from plug ee=%p msg_domain=%x msg_id=%x size=%d", ee, msg_domain, msg_id, size);
402    //get plug object form ee
403    conformant = (Evas_Object *)ecore_evas_data_get(ee, CONFORMANT_KEY);
404    ELM_CONFORMANT_DATA_GET(conformant, sd);
405    if (msg_domain == MSG_DOMAIN_CONTROL_INDICATOR)
406      {
407         if (msg_id == MSG_ID_INDICATOR_REPEAT_EVENT)
408           {
409               int *repeat = data;
410               DBG("Receive repeat event change message:(%d)", *repeat);
411               if (1 == *repeat)
412                 evas_object_repeat_events_set(sd->landscape_indicator, EINA_TRUE);
413               else
414                 evas_object_repeat_events_set(sd->landscape_indicator, EINA_FALSE);
415           }
416         if (msg_id == MSG_ID_INDICATOR_TYPE)
417           {
418              Elm_Win_Indicator_Type_Mode *indi_t_mode = data;
419              Evas_Object *win = elm_widget_top_get(conformant);
420              DBG("Receive indicator type change message:(%d)", *indi_t_mode);
421              elm_win_indicator_type_set(win, *indi_t_mode);
422           }
423      }
424 }
425
426 static Evas_Object *
427 _create_portrait_indicator(Evas_Object *obj)
428 {
429    Evas_Object *port_indicator = NULL;
430    Ecore_Evas *indicator_ee = NULL;
431    const char *port_indicator_serv_name;
432
433    ELM_CONFORMANT_DATA_GET(obj, sd);
434
435    port_indicator_serv_name = elm_config_indicator_service_get(sd->rot);
436    if (!port_indicator_serv_name)
437      {
438         DBG("Conformant cannot get portrait indicator service name\n");
439         return NULL;
440      }
441
442    port_indicator = elm_plug_add(obj);
443    if (!port_indicator)
444      {
445         DBG("Conformant cannot create plug to server[%s]\n", port_indicator_serv_name);
446         return NULL;
447      }
448
449    if (!elm_plug_connect(port_indicator, port_indicator_serv_name, 0, EINA_FALSE))
450      {
451         DBG("Conformant cannot connect to server[%s]\n", port_indicator_serv_name);
452         return NULL;
453      }
454
455    //callback to deal with extn socket message
456    indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(port_indicator));
457    DBG("This is portrait indicator's ee=%p.", indicator_ee);
458    ecore_evas_callback_msg_handle_set(indicator_ee, _plug_msg_handle);
459    ecore_evas_data_set(indicator_ee, CONFORMANT_KEY, obj);
460
461    DBG("The rotation value of portrait indicator was changed:(%d)", sd->rot);
462    ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
463
464    elm_widget_sub_object_add(obj, port_indicator);
465    evas_object_smart_callback_add(port_indicator, "image.deleted", _port_indicator_disconnected, obj);
466
467    evas_object_size_hint_min_set(port_indicator, -1, 0);
468    evas_object_size_hint_max_set(port_indicator, -1, 0);
469
470    return port_indicator;
471 }
472
473 static Evas_Object *
474 _create_landscape_indicator(Evas_Object *obj)
475 {
476    Ecore_Evas *indicator_ee = NULL;
477    Evas_Object *land_indicator = NULL;
478    const char *land_indicator_serv_name;
479
480    ELM_CONFORMANT_DATA_GET(obj, sd);
481
482    land_indicator_serv_name = elm_config_indicator_service_get(sd->rot);
483    if (!land_indicator_serv_name)
484      {
485         DBG("Conformant cannot get portrait indicator service name\n");
486         return NULL;
487      }
488
489    land_indicator = elm_plug_add(obj);
490    if (!land_indicator)
491      {
492         DBG("Conformant cannot create plug to server[%s]\n", land_indicator_serv_name);
493         return NULL;
494      }
495
496    if (!elm_plug_connect(land_indicator, land_indicator_serv_name, 0, EINA_FALSE))
497      {
498         DBG("Conformant cannot connect to server[%s]\n", land_indicator_serv_name);
499         return NULL;
500      }
501
502    //callback to deal with extn socket message
503    indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(land_indicator));
504    ecore_evas_data_set(indicator_ee, CONFORMANT_KEY, obj);
505    DBG("This is landscape indicator's ee=%p.", indicator_ee);
506    ecore_evas_callback_msg_handle_set(indicator_ee, _plug_msg_handle);
507    DBG("The rotation value of landscape indicator was changed:(%d)", sd->rot);
508    ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
509
510    elm_widget_sub_object_add(obj, land_indicator);
511    evas_object_smart_callback_add(land_indicator, "image.deleted",_land_indicator_disconnected, obj);
512
513    evas_object_size_hint_min_set(land_indicator, -1, 0);
514    evas_object_size_hint_max_set(land_indicator, -1, 0);
515    return land_indicator;
516 }
517
518 static void
519 _indicator_mode_set(Evas_Object *conformant, Elm_Win_Indicator_Mode indmode)
520 {
521    Evas_Object *old_indi = NULL;
522    Elm_Widget_Smart_Data *wd;
523    ELM_CONFORMANT_DATA_GET(conformant, sd);
524    sd->indmode = indmode;
525
526    wd = ELM_WIDGET_DATA(sd);
527
528    if (!edje_object_part_exists(wd->resize_obj, INDICATOR_PART))
529      return;
530
531    if (indmode == ELM_WIN_INDICATOR_SHOW)
532      {
533         old_indi = elm_layout_content_get(conformant, INDICATOR_PART);
534
535         //create new indicator
536         if (!old_indi)
537           {
538              if ((sd->rot == 90)||(sd->rot == 270))
539                {
540                   if (!sd->landscape_indicator)
541                     sd->landscape_indicator = _create_landscape_indicator(conformant);
542
543                   if (!sd->landscape_indicator) return;
544
545                   evas_object_show(sd->landscape_indicator);
546                   elm_layout_content_set(conformant, INDICATOR_PART, sd->landscape_indicator);
547                }
548              else
549                {
550                   if (!sd->portrait_indicator)
551                     sd->portrait_indicator = _create_portrait_indicator(conformant);
552
553                   if (!sd->portrait_indicator) return;
554
555                   evas_object_show(sd->portrait_indicator);
556                   elm_layout_content_set(conformant, INDICATOR_PART, sd->portrait_indicator);
557                }
558
559           }
560         elm_object_signal_emit(conformant, "elm,state,indicator,show", "elm");
561      }
562    else
563      {
564         old_indi = elm_layout_content_get(conformant, INDICATOR_PART);
565         if (old_indi)
566           {
567              evas_object_hide(old_indi);
568           }
569         elm_object_signal_emit(conformant, "elm,state,indicator,hide", "elm");
570      }
571 }
572
573 static void
574 _indicator_opacity_set(Evas_Object *conformant, Elm_Win_Indicator_Opacity_Mode ind_o_mode)
575 {
576    ELM_CONFORMANT_DATA_GET(conformant, sd);
577    sd->ind_o_mode = ind_o_mode;
578    //TODO: opacity change
579    //send indicator information
580    if (sd->landscape_indicator)
581      {
582         Ecore_Evas *indicator_ee = NULL;
583         DBG("The opacity mode of landscape indicator was changed:(%d)", ind_o_mode);
584         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->landscape_indicator));
585         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));
586      }
587    if (sd->portrait_indicator)
588      {
589         Ecore_Evas *indicator_ee = NULL;
590         DBG("The opacity mode of portrait indicator was changed:(%d)", ind_o_mode);
591         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->portrait_indicator));
592         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));
593      }
594 }
595
596 static void
597 _on_indicator_mode_changed(void *data,
598                     Evas_Object *obj,
599                     void *event_info __UNUSED__)
600 {
601    Evas_Object *conformant = data;
602    Evas_Object *win = obj;
603
604    Elm_Win_Indicator_Mode indmode;
605    Elm_Win_Indicator_Opacity_Mode ind_o_mode;
606
607    ELM_CONFORMANT_DATA_GET(conformant, sd);
608
609    indmode = elm_win_indicator_mode_get(win);
610    ind_o_mode = elm_win_indicator_opacity_get(win);
611    if (indmode != sd->indmode)
612      _indicator_mode_set(conformant, indmode);
613    if (ind_o_mode != sd->ind_o_mode)
614      _indicator_opacity_set(conformant, ind_o_mode);
615 }
616
617 static void
618 _on_rotation_changed(void *data,
619               Evas_Object *obj,
620               void *event_info __UNUSED__)
621 {
622    int rot = 0;
623    Evas_Object *win = obj;
624    Evas_Object *conformant = data;
625    Evas_Object *old_indi = NULL;
626
627    ELM_CONFORMANT_DATA_GET(data, sd);
628
629    rot = elm_win_rotation_get(win);
630
631    if (rot == sd->rot) return;
632
633    sd->rot = rot;
634    //send indicator information
635    if (sd->landscape_indicator)
636      {
637         Ecore_Evas *indicator_ee = NULL;
638         DBG("The rotation value of landscape indicator was changed:(%d)", rot);
639         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->landscape_indicator));
640         ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
641      }
642    if (sd->portrait_indicator)
643      {
644         Ecore_Evas *indicator_ee = NULL;
645         DBG("The rotation value of portrait indicator was changed:(%d)", rot);
646         indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(sd->portrait_indicator));
647         ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
648      }
649    old_indi = elm_layout_content_unset(conformant, INDICATOR_PART);
650    /* this means ELM_WIN_INDICATOR_SHOW never be set.we don't need to change indicator type*/
651    if (!old_indi) return;
652    evas_object_hide(old_indi);
653
654    if ((rot == 90) || (rot == 270))
655      {
656         if (!sd->landscape_indicator)
657           sd->landscape_indicator = _create_landscape_indicator(conformant);
658
659         if (!sd->landscape_indicator) return;
660
661         evas_object_show(sd->landscape_indicator);
662         evas_object_data_set(sd->landscape_indicator, CONFORMANT_KEY, (void *) rot);
663         elm_layout_content_set(conformant, INDICATOR_PART, sd->landscape_indicator);
664      }
665    else
666      {
667         if (!sd->portrait_indicator)
668           sd->portrait_indicator = _create_portrait_indicator(conformant);
669
670         if (!sd->portrait_indicator) return;
671
672         evas_object_show(sd->portrait_indicator);
673         evas_object_data_set(sd->portrait_indicator, CONFORMANT_KEY, (void *) rot);
674         elm_layout_content_set(conformant, INDICATOR_PART, sd->portrait_indicator);
675      }
676 }
677
678 static Eina_Bool
679 _elm_conformant_smart_theme(Evas_Object *obj)
680 {
681    if (!ELM_WIDGET_CLASS(_elm_conformant_parent_sc)->theme(obj))
682      return EINA_FALSE;
683
684    _conformant_parts_swallow(obj);
685
686    elm_layout_sizing_eval(obj);
687
688    return EINA_TRUE;
689 }
690
691 // unused now - but meant to be for making sure the focused widget is always
692 // visible when the vkbd comes and goes by moving the conformant obj (and thus
693 // its children) to  show the focused widget (and if focus changes follow)
694 /*
695    static Evas_Object *
696    _focus_object_get(const Evas_Object *obj)
697    {
698    Evas_Object *win, *foc;
699
700    win = elm_widget_top_get(obj);
701    if (!win) return NULL;
702    foc = elm_widget_top_get(win);
703    }
704
705    static void
706    _focus_object_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
707    {
708    evas_object_geometry_get(obj, x, y, w, h);
709    }
710
711    static void
712    _focus_change_del(void *data, Evas_Object *obj, void *event_info)
713    {
714    // called from toplevel when the focused window shanges
715    }
716
717    static void
718    _autoscroll_move(Evas_Object *obj)
719    {
720    // move conformant edje by delta to show focused widget
721    }
722
723    static void
724    _autoscroll_mode_enable(Evas_Object *obj)
725    {
726    // called when autoscroll mode should be on - content area smaller than
727    // its min size
728    // 1. get focused object
729    // 2. if not in visible conformant area calculate delta needed to
730    //    get it in
731    // 3. store delta and call _autoscroll_move() which either asanimates
732    //    or jumps right there
733    }
734
735    static void
736    _autoscroll_mode_disable(Evas_Object *obj)
737    {
738    // called when autoscroll mode should be off - set delta to 0 and
739    // call _autoscroll_move()
740    }
741  */
742
743 static void
744 _move_resize_cb(void *data __UNUSED__,
745                 Evas *e __UNUSED__,
746                 Evas_Object *obj,
747                 void *event_info __UNUSED__)
748 {
749    Conformant_Part_Type part_type;
750
751    part_type = (ELM_CONFORMANT_INDICATOR_PART |
752                 ELM_CONFORMANT_SOFTKEY_PART |
753                 ELM_CONFORMANT_VIRTUAL_KEYPAD_PART |
754                 ELM_CONFORMANT_CLIPBOARD_PART);
755
756    _conformant_part_sizing_eval(obj, part_type);
757 }
758
759 static void
760 _show_region_job(void *data)
761 {
762    Evas_Object *focus_obj;
763
764    ELM_CONFORMANT_DATA_GET(data, sd);
765
766    focus_obj = elm_widget_focused_object_get(data);
767    if (focus_obj)
768      {
769         Evas_Coord x, y, w, h;
770
771         elm_widget_show_region_get(focus_obj, &x, &y, &w, &h);
772
773
774         if (h < _elm_config->finger_size)
775           h = _elm_config->finger_size;
776
777         elm_widget_show_region_set(focus_obj, x, y, w, h, EINA_TRUE);
778      }
779
780    sd->show_region_job = NULL;
781 }
782
783 // showing the focused/important region.
784 #ifdef HAVE_ELEMENTARY_X
785 static void
786 _on_content_resize(void *data,
787                    Evas *e __UNUSED__,
788                    Evas_Object *obj __UNUSED__,
789                    void *event_info __UNUSED__)
790 {
791    ELM_CONFORMANT_DATA_GET(data, sd);
792
793    if ((sd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) &&
794        (sd->clipboard_state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF))
795      return;
796
797    if (sd->show_region_job) ecore_job_del(sd->show_region_job);
798    sd->show_region_job = ecore_job_add(_show_region_job, data);
799 }
800
801 #endif
802
803 #ifdef HAVE_ELEMENTARY_X
804 static void
805 _autoscroll_objects_update(void *data)
806 {
807    int i;
808    const char *type;
809    Evas_Object *sub, *top_scroller = NULL;
810
811    ELM_CONFORMANT_DATA_GET(data, sd);
812
813    sub = elm_widget_focused_object_get(data);
814    //Look up for top most scroller in the focus object hierarchy
815    //inside Conformant.
816
817    while (sub)
818      {
819         type = elm_widget_type_get(sub);
820         if (!strcmp(type, ELM_CONFORMANT_SMART_NAME)) break;
821
822         for (i = 0; i < SUB_TYPE_COUNT; i++)
823           if (!strcmp(type, sub_type[i]))
824             {
825                top_scroller = sub;
826                break;
827             }
828         sub = elm_object_parent_widget_get(sub);
829      }
830
831    //If the scroller got changed by app, replace it.
832    if (top_scroller != sd->scroller)
833      {
834         if (sd->scroller)
835           evas_object_event_callback_del
836             (sd->scroller, EVAS_CALLBACK_RESIZE, _on_content_resize);
837         sd->scroller = top_scroller;
838
839         if (sd->scroller)
840           evas_object_event_callback_add
841             (sd->scroller, EVAS_CALLBACK_RESIZE, _on_content_resize, data);
842      }
843 }
844
845 static void
846 _virtualkeypad_state_change(Evas_Object *obj, Ecore_X_Event_Window_Property *ev)
847 {
848    ELM_CONFORMANT_DATA_GET(obj, sd);
849
850    Ecore_X_Window zone = ecore_x_e_illume_zone_get(ev->win);
851    Ecore_X_Virtual_Keyboard_State state =
852       ecore_x_e_virtual_keyboard_state_get(ev->win);
853
854    DBG("[KEYPAD]:window's state win=0x%x, state=%d.", ev->win, state);
855    if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN)
856      {
857         state = ecore_x_e_virtual_keyboard_state_get(zone);
858         DBG("[KEYPAD]:zone's state zone=0x%x, state=%d.", zone, state);
859      }
860
861    if (sd->vkb_state == state) return;
862    sd->vkb_state = state;
863
864    if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
865      {
866         DBG("[KEYPAD]:ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF");
867         _conformant_part_sizing_eval(obj, ELM_CONFORMANT_VIRTUAL_KEYPAD_PART);
868         // Tizen Only - SIP regions for virtual keypad and clipboard are the same in Tizen
869         if (sd->clipboard_state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF)
870           elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_NONE);
871         evas_object_smart_callback_call(obj, SIG_VIRTUALKEYPAD_STATE_OFF, NULL);
872      }
873    else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
874      {
875         DBG("[KEYPAD]:ECORE_X_VIRTUAL_KEYBOARD_STATE_ON");
876         _conformant_part_sizing_eval(obj, ELM_CONFORMANT_VIRTUAL_KEYPAD_PART);
877         elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_COMPRESS);
878         _autoscroll_objects_update(obj);
879         evas_object_smart_callback_call(obj, SIG_VIRTUALKEYPAD_STATE_ON, NULL);
880      }
881 }
882
883 static void
884 _clipboard_state_change(Evas_Object *obj, Ecore_X_Event_Window_Property *ev)
885 {
886    ELM_CONFORMANT_DATA_GET(obj, sd);
887
888    Ecore_X_Window zone = ecore_x_e_illume_zone_get(ev->win);
889    Ecore_X_Illume_Clipboard_State state =
890       ecore_x_e_illume_clipboard_state_get(ev->win);
891
892    DBG("[CLIPBOARD]:window's state win=0x%x, state=%d.", ev->win, state);
893
894    if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_UNKNOWN)
895      {
896         state = ecore_x_e_illume_clipboard_state_get(ev->win);
897         DBG("[CLIPBOARD]:zone's state zone=0x%x, state=%d.", zone, state);
898      }
899
900    if (sd->clipboard_state == state) return;
901    sd->clipboard_state = state;
902
903    if (state == ECORE_X_ILLUME_CLIPBOARD_STATE_OFF)
904      {
905         // Tizen Only - SIP regions for virtual keypad and clipboard are the same in Tizen
906         edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj, "elm,state,clipboard,off", "elm");
907         evas_object_size_hint_min_set(sd->clipboard, -1, 0);
908         evas_object_size_hint_max_set(sd->clipboard, -1, 0);
909         // Tizen Only - SIP regions for virtual keypad and clipboard are the same in Tizen
910         if (sd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
911           elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_NONE);
912         evas_object_smart_callback_call(obj, SIG_CLIPBOARD_STATE_OFF, NULL);
913      }
914    else if(state == ECORE_X_ILLUME_CLIPBOARD_STATE_ON)
915      {
916         elm_widget_display_mode_set(obj, EVAS_DISPLAY_MODE_COMPRESS);
917         _autoscroll_objects_update(obj);
918         // Tizen Only - SIP regions for virtual keypad and clipboard are the same in Tizen
919         edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj, "elm,state,clipboard,on", "elm");
920         evas_object_smart_callback_call(obj, SIG_CLIPBOARD_STATE_ON, NULL);
921      }
922 }
923
924 static Eina_Bool
925 _on_prop_change(void *data,
926                 int type __UNUSED__,
927                 void *event)
928 {
929    Ecore_X_Event_Window_Property *ev = event;
930
931    int pid = 0;
932
933 #ifdef __linux__
934    pid = (int)getpid();
935 #endif
936
937    if (ev->atom == ECORE_X_ATOM_E_ILLUME_ZONE)
938      {
939                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_ZONE.\n", pid, ev->win);
940         Conformant_Part_Type part_type;
941
942         part_type = (ELM_CONFORMANT_INDICATOR_PART |
943                      ELM_CONFORMANT_SOFTKEY_PART |
944                      ELM_CONFORMANT_VIRTUAL_KEYPAD_PART |
945                      ELM_CONFORMANT_CLIPBOARD_PART);
946
947         _conformant_part_sizing_eval(data, part_type);
948      }
949    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
950      {
951                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY.", pid, ev->win);
952         _conformant_part_sizing_eval(data, ELM_CONFORMANT_INDICATOR_PART);
953          }
954    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
955      {
956                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY.", pid, ev->win);
957         _conformant_part_sizing_eval(data, ELM_CONFORMANT_SOFTKEY_PART);
958          }
959    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
960      {
961                 DBG("[KEYPAD]:pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY.", pid, ev->win);
962         _conformant_part_sizing_eval(data, ELM_CONFORMANT_VIRTUAL_KEYPAD_PART);
963      }
964    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY)
965      {
966                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY.", pid, ev->win);
967         _conformant_part_sizing_eval(data, ELM_CONFORMANT_CLIPBOARD_PART);
968      }
969    else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
970      {
971                 DBG("[KEYPAD]:pid=%d, win=0x%x, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE.", pid, ev->win);
972         _virtualkeypad_state_change(data, ev);
973      }
974    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
975      {
976                 DBG("pid=%d, win=0x%x, ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE.", pid, ev->win);
977         _clipboard_state_change(data, ev);
978      }
979
980    return ECORE_CALLBACK_PASS_ON;
981 }
982
983 #endif
984
985 static void
986 _elm_conformant_smart_add(Evas_Object *obj)
987 {
988    EVAS_SMART_DATA_ALLOC(obj, Elm_Conformant_Smart_Data);
989
990    ELM_WIDGET_CLASS(_elm_conformant_parent_sc)->base.add(obj);
991
992    elm_widget_can_focus_set(obj, EINA_FALSE);
993
994    elm_layout_theme_set(obj, "conformant", "base", elm_widget_style_get(obj));
995
996    _conformant_parts_swallow(obj);
997
998    evas_object_event_callback_add
999      (obj, EVAS_CALLBACK_RESIZE, _move_resize_cb, obj);
1000    evas_object_event_callback_add
1001      (obj, EVAS_CALLBACK_MOVE, _move_resize_cb, obj);
1002
1003    elm_layout_sizing_eval(obj);
1004 }
1005
1006 static void
1007 _elm_conformant_smart_del(Evas_Object *obj)
1008 {
1009    Evas_Object *top;
1010    ELM_CONFORMANT_DATA_GET(obj, sd);
1011
1012 #ifdef HAVE_ELEMENTARY_X
1013    if (sd->prop_hdl) ecore_event_handler_del(sd->prop_hdl);
1014 #endif
1015
1016    if (sd->show_region_job) ecore_job_del(sd->show_region_job);
1017    if (sd->port_indi_timer) ecore_timer_del(sd->port_indi_timer);
1018    if (sd->land_indi_timer) ecore_timer_del(sd->land_indi_timer);
1019    if (sd->portrait_indicator)
1020      evas_object_del(sd->portrait_indicator);
1021    if (sd->landscape_indicator)
1022      evas_object_del(sd->landscape_indicator);
1023    top = elm_widget_top_get(obj);
1024    evas_object_data_set(top, "\377 elm,conformant", NULL);
1025
1026    ELM_WIDGET_CLASS(_elm_conformant_parent_sc)->base.del(obj);
1027 }
1028
1029 static void
1030 _elm_conformant_smart_parent_set(Evas_Object *obj,
1031                                  Evas_Object *parent)
1032 {
1033 #ifdef HAVE_ELEMENTARY_X
1034    Evas_Object *top = elm_widget_top_get(parent);
1035    Ecore_X_Window xwin = elm_win_xwindow_get(parent);
1036
1037    if ((xwin) && (!elm_win_inlined_image_object_get(top)))
1038      {
1039         ELM_CONFORMANT_DATA_GET(obj, sd);
1040
1041         sd->prop_hdl = ecore_event_handler_add
1042             (ECORE_X_EVENT_WINDOW_PROPERTY, _on_prop_change, obj);
1043         sd->vkb_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
1044         sd->clipboard_state = ECORE_X_ILLUME_CLIPBOARD_STATE_OFF;
1045      }
1046    // FIXME: get kbd region prop
1047 #endif
1048 }
1049
1050 static void
1051 _elm_conformant_smart_set_user(Elm_Conformant_Smart_Class *sc)
1052 {
1053    ELM_WIDGET_CLASS(sc)->base.add = _elm_conformant_smart_add;
1054    ELM_WIDGET_CLASS(sc)->base.del = _elm_conformant_smart_del;
1055
1056    ELM_WIDGET_CLASS(sc)->parent_set = _elm_conformant_smart_parent_set;
1057    ELM_WIDGET_CLASS(sc)->theme = _elm_conformant_smart_theme;
1058
1059    ELM_LAYOUT_CLASS(sc)->content_aliases = _content_aliases;
1060 }
1061
1062 EAPI const Elm_Conformant_Smart_Class *
1063 elm_conformant_smart_class_get(void)
1064 {
1065    static Elm_Conformant_Smart_Class _sc =
1066      ELM_CONFORMANT_SMART_CLASS_INIT_NAME_VERSION(ELM_CONFORMANT_SMART_NAME);
1067    static const Elm_Conformant_Smart_Class *class = NULL;
1068    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1069
1070    if (class)
1071      return class;
1072
1073    _elm_conformant_smart_set(&_sc);
1074    esc->callbacks = _smart_callbacks;
1075    class = &_sc;
1076
1077    return class;
1078 }
1079
1080 EAPI Evas_Object *
1081 elm_conformant_add(Evas_Object *parent)
1082 {
1083    Evas_Object *obj;
1084    Evas_Object *top;
1085
1086    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1087
1088    obj = elm_widget_add(_elm_conformant_smart_class_new(), parent);
1089    if (!obj) return NULL;
1090
1091    if (!elm_widget_sub_object_add(parent, obj))
1092      ERR("could not add %p as sub object of %p", obj, parent);
1093
1094    ELM_CONFORMANT_DATA_GET(obj, sd);
1095
1096    top = elm_widget_top_get(obj);
1097    _on_indicator_mode_changed(obj, top, NULL);
1098    _on_rotation_changed(obj, top, NULL);
1099
1100    sd->indmode = elm_win_indicator_mode_get(top);
1101    sd->ind_o_mode = elm_win_indicator_opacity_get(top);
1102    sd->rot = elm_win_rotation_get(top);
1103    evas_object_data_set(top, "\377 elm,conformant", obj);
1104
1105    evas_object_smart_callback_add
1106      (top, "indicator,prop,changed", _on_indicator_mode_changed, obj);
1107    evas_object_smart_callback_add
1108      (top, "rotation,changed", _on_rotation_changed, obj);
1109
1110    return obj;
1111 }