1 #include <Elementary.h>
5 * @defgroup Conformant Conformant
8 * The aim is to provide a widget that can be used in elementary apps to
9 * account for space taken up by the indicator & softkey windows when running
10 * the illume2 module of E17.
13 typedef struct _Widget_Data Widget_Data;
17 Evas_Object *shelf, *panel;
19 #ifdef HAVE_CONFORMANT_AUTOSCROLL
20 Evas_Object *virtualkeypad;
21 Evas_Object *focus_obj;
22 Evas_Object *scroller;
23 Evas_Coord frelx, frely;
25 Ecore_X_Virtual_Keyboard_State vkeypad_state;
27 Ecore_Event_Handler *prop_hdl;
29 Ecore_Animator *animator; // animaton timer
30 double start; // time started
31 Evas_Coord auto_x, auto_y; // desired delta
32 Evas_Coord x, y; // current delta
36 /* local function prototypes */
37 static const char *widtype = NULL;
38 #ifdef HAVE_CONFORMANT_AUTOSCROLL
39 static const char SIG_IMPREGION_CHANGED[] = "impregion,changed";
41 static void _del_hook(Evas_Object *obj);
42 static void _theme_hook(Evas_Object *obj);
43 static void _swallow_conformant_parts(Evas_Object *obj);
44 static void _sizing_eval(Evas_Object *obj);
45 static Eina_Bool _prop_change(void *data, int type, void *event);
50 _del_hook(Evas_Object *obj)
52 Widget_Data *wd = elm_widget_data_get(obj);
54 if (wd->prop_hdl) ecore_event_handler_del(wd->prop_hdl);
59 _theme_hook(Evas_Object *obj)
61 Widget_Data *wd = elm_widget_data_get(obj);
63 _elm_theme_object_set(obj, wd->base, "conformant", "base", elm_widget_style_get(obj));
64 _swallow_conformant_parts(obj);
67 edje_object_part_swallow(wd->base, "elm.swallow.content", wd->content);
68 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
73 _sizing_eval(Evas_Object *obj)
75 Widget_Data *wd = elm_widget_data_get(obj);
76 Evas_Coord mw = -1, mh = -1;
78 edje_object_size_min_calc(wd->base, &mw, &mh);
79 evas_object_size_hint_min_set(obj, mw, mh);
80 evas_object_size_hint_max_set(obj, -1, -1);
84 _swallow_conformant_parts(Evas_Object *obj)
86 #ifdef HAVE_ELEMENTARY_X
87 Widget_Data *wd = elm_widget_data_get(obj);
89 Ecore_X_Window zone, xwin;
92 xwin = elm_win_xwindow_get(obj);
93 zone = ecore_x_e_illume_zone_get(xwin);
95 ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
98 wd->shelf = evas_object_rectangle_add(evas_object_evas_get(obj));
99 evas_object_color_set(wd->shelf, 0, 0, 0, 0);
100 evas_object_size_hint_min_set(wd->shelf, -1, sh);
101 evas_object_size_hint_max_set(wd->shelf, -1, sh);
102 edje_object_part_swallow(wd->base, "elm.swallow.shelf", wd->shelf);
104 #ifdef HAVE_CONFORMANT_AUTOSCROLL
106 wd->focus_obj = NULL;
108 ecore_x_e_illume_keyboard_geometry_get(zone, NULL, NULL, NULL, &sh);
110 wd->vkeypad_height = sh;
111 if (!wd->virtualkeypad)
112 wd->virtualkeypad= evas_object_rectangle_add(evas_object_evas_get(obj));
113 evas_object_color_set(wd->virtualkeypad, 0, 0, 0, 0);
114 evas_object_size_hint_min_set(wd->virtualkeypad, -1, sh);
115 evas_object_size_hint_max_set(wd->virtualkeypad, -1, sh);
116 edje_object_part_swallow(wd->base, "elm.swallow.virtualkeypad", wd->virtualkeypad);
120 ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
123 wd->panel = evas_object_rectangle_add(evas_object_evas_get(obj));
124 evas_object_color_set(wd->panel, 0, 0, 0, 0);
125 evas_object_size_hint_min_set(wd->panel, -1, sh);
126 evas_object_size_hint_max_set(wd->panel, -1, sh);
127 edje_object_part_swallow(wd->base, "elm.swallow.panel", wd->panel);
132 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
134 Widget_Data *wd = elm_widget_data_get(data);
140 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
142 Widget_Data *wd = elm_widget_data_get(obj);
143 Evas_Object *sub = event_info;
145 if (sub == wd->content)
147 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
148 _changed_size_hints, obj);
154 #ifdef HAVE_CONFORMANT_AUTOSCROLL
156 _focus_object_get(const Evas_Object *obj)
158 Evas_Object *parent = NULL, *foc = NULL;
159 parent = elm_widget_top_get(obj);
160 if (!parent) return NULL;
161 foc = elm_widget_focused_object_get(parent);
166 _imp_region_show(void *data, Evas_Object *obj)
168 Evas_Coord x = 0, y = 0, w = 0, h = 0;
169 Evas_Object * immed_scroll = NULL;
170 Widget_Data *wd = elm_widget_data_get(data);
172 if (!wd->scroller) return;
173 if (!wd->focus_obj) return;
174 immed_scroll = elm_widget_imp_region_get(wd->focus_obj, &x, &y, &w, &h);
179 //if (wd->vkeypad_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
180 elm_scroller_region_bring_in(wd->scroller, x, y, w, h);
184 _imp_region_changed_cb(void *data, Evas_Object *obj, void *event_info)
186 _imp_region_show(data, obj);
190 _scroller_resize_event_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
192 _imp_region_show(data, obj);
196 _focus_object_region_calc(void *data, int *kh, Eina_Bool reg_scrol_resz_evnt)
198 Evas_Coord fx = 0, fy = 0, fw = 0, fh = 0;
199 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
200 Evas_Coord tsx = 0, tsy = 0, tsw = 0, tsh = 0;
202 Widget_Data *wd = elm_widget_data_get(data);
203 if (!wd) return EINA_FALSE;
204 if (!wd->scroller) return EINA_FALSE;
205 if (!wd->focus_obj) return EINA_FALSE;
206 evas_object_geometry_get(wd->focus_obj, &fx, &fy, &fw, &fh);
207 evas_object_geometry_get(wd->scroller, &sx, &sy, &sw, &sh);
208 elm_scroller_region_get(wd->scroller, &tsx, &tsy, &tsw, &tsh);
213 wd->frelx = tsx + fx;
214 wd->frely = tsy + fy;
218 _get_scroller(void *data, Evas_Object * foc_obj, Eina_Bool reg_scrol_resz_evnt)
220 Evas_Coord x = 0, y = 0, w = 0, h = 0;
221 Evas_Object * parent = NULL;
222 Evas_Object * immed_scroll=NULL;
223 Evas_Object * root_scroller = NULL;
224 Evas_Object *win=NULL;
225 const char * type=NULL;
226 Widget_Data *wd = elm_widget_data_get(data);
227 if (!wd) return EINA_FALSE;
228 win = elm_widget_top_get(foc_obj);
229 if (!win) return EINA_FALSE;
230 immed_scroll = elm_widget_imp_region_get(foc_obj, &x, &y, &w, &h);
231 parent = elm_object_parent_widget_get( foc_obj );
234 type=elm_widget_type_get(parent);
235 if (!strcmp(type,"scroller"))
237 root_scroller = parent;
240 parent = elm_object_parent_widget_get( parent );
242 while (parent && (parent !=win));
244 wd->scroller = root_scroller;
245 else if (immed_scroll)
246 wd->scroller = immed_scroll;
256 _autoscroll_mode_enable(void *data)
258 Evas_Object * focused_object=NULL;
259 Eina_Bool ret = EINA_FALSE;
261 Widget_Data *wd = elm_widget_data_get(data);
263 focused_object=_focus_object_get(data);
266 wd->focus_obj = focused_object;
267 ret = _get_scroller(data, focused_object, EINA_TRUE);
269 if (ret == EINA_TRUE)
271 ret = _focus_object_region_calc(data, NULL, EINA_TRUE);
272 evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE,
273 _scroller_resize_event_cb, data);
274 evas_object_smart_callback_add(wd->focus_obj, SIG_IMPREGION_CHANGED,
275 _imp_region_changed_cb, data);
280 _autoscroll_mode_disable(void *data)
282 Widget_Data *wd = elm_widget_data_get(data);
284 evas_object_event_callback_del(wd->scroller, EVAS_CALLBACK_RESIZE, _scroller_resize_event_cb);
285 evas_object_smart_callback_del(wd->focus_obj, SIG_IMPREGION_CHANGED, _imp_region_changed_cb);
287 wd->focus_obj = NULL;
293 _prop_change(void *data, int type __UNUSED__, void *event)
295 #ifdef HAVE_ELEMENTARY_X
296 #ifdef HAVE_CONFORMANT_AUTOSCROLL
297 int indicator_height=57;
298 Ecore_X_Virtual_Keyboard_State virt_keypad_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN;
300 Ecore_X_Event_Window_Property *ev;
301 Widget_Data *wd = elm_widget_data_get(data);
302 if (!wd) return ECORE_CALLBACK_PASS_ON;
304 if (ev->atom == ECORE_X_ATOM_E_ILLUME_ZONE)
309 zone = ecore_x_e_illume_zone_get(ev->win);
310 ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
311 #ifdef HAVE_CONFORMANT_AUTOSCROLL
312 if (sh < 0) sh = indicator_height;
316 evas_object_size_hint_min_set(wd->shelf, -1, sh);
317 evas_object_size_hint_max_set(wd->shelf, -1, sh);
318 #ifdef HAVE_CONFORMANT_AUTOSCROLL
320 zone = ecore_x_e_illume_zone_get(ev->win);
321 ecore_x_e_illume_keyboard_geometry_get(zone, NULL, NULL, NULL, &sh);
323 evas_object_size_hint_min_set(wd->virtualkeypad, -1, sh);
324 evas_object_size_hint_max_set(wd->virtualkeypad, -1, sh);
327 ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
329 evas_object_size_hint_min_set(wd->panel, -1, sh);
330 evas_object_size_hint_max_set(wd->panel, -1, sh);
332 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
337 zone = ecore_x_e_illume_zone_get(ev->win);
338 ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
340 evas_object_size_hint_min_set(wd->shelf, -1, sh);
341 evas_object_size_hint_max_set(wd->shelf, -1, sh);
343 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
348 zone = ecore_x_e_illume_zone_get(ev->win);
349 ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
351 evas_object_size_hint_min_set(wd->panel, -1, sh);
352 evas_object_size_hint_max_set(wd->panel, -1, sh);
354 #ifdef HAVE_CONFORMANT_AUTOSCROLL
355 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
358 int ky = -1, kh = -1;
360 printf("Keyboard Geometry Changed\n");
361 zone = ecore_x_e_illume_zone_get(ev->win);
362 ecore_x_e_illume_keyboard_geometry_get(zone, NULL, &ky, NULL, &kh);
363 printf("\tGeom: %d\n", ky);
365 if (kh == wd->vkeypad_height) return ECORE_CALLBACK_PASS_ON;
366 wd->vkeypad_height = kh;
367 evas_object_size_hint_min_set(wd->virtualkeypad, -1, kh);
368 evas_object_size_hint_max_set(wd->virtualkeypad, -1, kh);
370 else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
373 zone = ecore_x_e_illume_zone_get(ev->win);
374 virt_keypad_state = ecore_x_e_virtual_keyboard_state_get(zone);
375 if (virt_keypad_state == wd->vkeypad_state) return ECORE_CALLBACK_PASS_ON;
376 wd->vkeypad_state = virt_keypad_state;
377 if(wd->vkeypad_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
379 _autoscroll_mode_enable(data);
381 else if (wd->vkeypad_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
383 _autoscroll_mode_disable(data);
389 return ECORE_CALLBACK_PASS_ON;
393 * Add a new Conformant object
395 * @param parent The parent object
396 * @return The new conformant object or NULL if it cannot be created
398 * @ingroup Conformant
401 elm_conformant_add(Evas_Object *parent)
407 wd = ELM_NEW(Widget_Data);
409 evas = evas_object_evas_get(parent);
411 obj = elm_widget_add(evas);
412 ELM_SET_WIDTYPE(widtype, "conformant");
413 elm_widget_type_set(obj, "conformant");
414 elm_widget_sub_object_add(parent, obj);
415 elm_widget_data_set(obj, wd);
416 elm_widget_del_hook_set(obj, _del_hook);
417 elm_widget_theme_hook_set(obj, _theme_hook);
419 wd->base = edje_object_add(evas);
420 _elm_theme_object_set(obj, wd->base, "conformant", "base", "default");
421 elm_widget_resize_object_set(obj, wd->base);
422 _swallow_conformant_parts(obj);
424 #ifdef HAVE_ELEMENTARY_X
425 wd->prop_hdl = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
427 #ifdef HAVE_CONFORMANT_AUTOSCROLL
428 wd->vkeypad_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
432 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
439 * Set the content of the conformant widget
441 * Once the content object is set, a previously set one will be deleted.
442 * If you want to keep that old content object, use the
443 * elm_conformat_content_unset() function.
445 * @param obj The conformant object
446 * @return The content that was being used
448 * @ingroup Conformant
451 elm_conformant_content_set(Evas_Object *obj, Evas_Object *content)
453 ELM_CHECK_WIDTYPE(obj, widtype);
454 Widget_Data *wd = elm_widget_data_get(obj);
456 if (wd->content == content) return;
457 if (wd->content) evas_object_del(wd->content);
458 wd->content = content;
461 elm_widget_sub_object_add(obj, content);
462 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
463 _changed_size_hints, obj);
464 edje_object_part_swallow(wd->base, "elm.swallow.content", content);
470 * Unset the content of the conformant widget
472 * Unparent and return the content object which was set for this widget;
474 * @param obj The conformant object
475 * @return The content that was being used
477 * @ingroup Conformant
480 elm_conformant_content_unset(Evas_Object *obj)
482 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
483 Widget_Data *wd = elm_widget_data_get(obj);
484 Evas_Object *content;
485 if (!wd) return NULL;
486 if (!wd->content) return NULL;
487 content = wd->content;
488 elm_widget_sub_object_del(obj, wd->content);
489 edje_object_part_unswallow(wd->base, wd->content);