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 static void _del_hook(Evas_Object *obj);
39 static void _theme_hook(Evas_Object *obj);
40 static void _sizing_eval(Evas_Object *obj);
41 static Eina_Bool _prop_change(void *data, int type, void *event);
42 #ifdef HAVE_CONFORMANT_AUTOSCROLL
43 static const char SIG_IMPREGION_CHANGED[] = "impregion,changed";
48 _del_hook(Evas_Object *obj)
50 Widget_Data *wd = elm_widget_data_get(obj);
52 if (wd->prop_hdl) ecore_event_handler_del(wd->prop_hdl);
57 _theme_hook(Evas_Object *obj)
59 Widget_Data *wd = elm_widget_data_get(obj);
61 _elm_theme_object_set(obj, wd->base, "conformant", "base", elm_widget_style_get(obj));
63 edje_object_part_swallow(wd->base, "elm.swallow.content", wd->content);
64 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
69 _sizing_eval(Evas_Object *obj)
71 Widget_Data *wd = elm_widget_data_get(obj);
72 Evas_Coord mw = -1, mh = -1;
74 edje_object_size_min_calc(wd->base, &mw, &mh);
75 evas_object_size_hint_min_set(obj, mw, mh);
76 evas_object_size_hint_max_set(obj, -1, -1);
80 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
82 Widget_Data *wd = elm_widget_data_get(data);
88 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
90 Widget_Data *wd = elm_widget_data_get(obj);
91 Evas_Object *sub = event_info;
93 if (sub == wd->content)
95 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
96 _changed_size_hints, obj);
102 #ifdef HAVE_CONFORMANT_AUTOSCROLL
104 _focus_object_get(const Evas_Object *obj)
106 Evas_Object *parent = NULL, *foc = NULL;
107 parent = elm_widget_top_get(obj);
108 if (!parent) return NULL;
109 foc = elm_widget_focused_object_get(parent);
114 _imp_region_show(void *data, Evas_Object *obj)
116 Evas_Coord x = 0, y = 0, w = 0, h = 0;
117 Evas_Object * immed_scroll = NULL;
118 Widget_Data *wd = elm_widget_data_get(data);
120 if (!wd->scroller) return;
121 if (!wd->focus_obj) return;
122 immed_scroll = elm_widget_imp_region_get(wd->focus_obj, &x, &y, &w, &h);
127 //if(wd->vkeypad_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
128 elm_scroller_region_show(wd->scroller, x, y, w, h);
132 _imp_region_changed_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
134 _imp_region_show(data, obj);
138 _scroller_resize_event_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
140 _imp_region_show(data, obj);
144 _focus_object_region_calc(void *data, int *kh, bool reg_scrol_resz_evnt)
146 Evas_Coord fx = 0, fy = 0, fw = 0, fh = 0;
147 Evas_Coord sx = 0, sy = 0, sw = 0, sh = 0;
148 Evas_Coord tsx = 0, tsy = 0, tsw = 0, tsh = 0;
150 Widget_Data *wd = elm_widget_data_get(data);
151 if (!wd) return EINA_FALSE;
152 if (!wd->scroller) return EINA_FALSE;
153 if (!wd->focus_obj) return EINA_FALSE;
154 evas_object_geometry_get(wd->focus_obj, &fx, &fy, &fw, &fh);
155 evas_object_geometry_get(wd->scroller, &sx, &sy, &sw, &sh);
156 elm_scroller_region_get(wd->scroller, &tsx, &tsy, &tsw, &tsh);
161 wd->frelx = tsx + fx;
162 wd->frely = tsy + fy;
166 _get_scroller(void *data, Evas_Object * foc_obj, bool reg_scrol_resz_evnt)
168 Evas_Coord x = 0, y = 0, w = 0, h = 0;
169 Evas_Object * parent = NULL;
170 Evas_Object * immed_scroll=NULL;
171 Evas_Object * root_scroller = NULL;
172 Evas_Object *win=NULL;
173 const char * type=NULL;
174 Widget_Data *wd = elm_widget_data_get(data);
175 if (!wd) return EINA_FALSE;
176 win = elm_widget_top_get(foc_obj);
177 if (!win) return EINA_FALSE;
178 immed_scroll = elm_widget_imp_region_get(foc_obj, &x, &y, &w, &h);
179 parent = elm_object_parent_widget_get( foc_obj );
182 type=elm_widget_type_get(parent);
183 if(!strcmp(type,"scroller"))
185 root_scroller = parent;
188 parent = elm_object_parent_widget_get( parent );
189 }while(parent && (parent !=win));
191 wd->scroller = root_scroller;
192 else if(immed_scroll)
193 wd->scroller = immed_scroll;
203 _autoscroll_mode_enable(void *data)
205 Evas_Object * focused_object=NULL;
206 bool ret = EINA_FALSE;
208 Widget_Data *wd = elm_widget_data_get(data);
209 if (!wd) return EINA_FALSE;
210 focused_object=_focus_object_get(data);
213 wd->focus_obj = focused_object;
214 ret = _get_scroller(data, focused_object, EINA_TRUE);
218 ret = _focus_object_region_calc(data, NULL, EINA_TRUE);
219 evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE,
220 _scroller_resize_event_cb, data);
221 evas_object_smart_callback_add(wd->focus_obj, SIG_IMPREGION_CHANGED,
222 _imp_region_changed_cb, data);
227 _autoscroll_mode_disable(void *data)
229 Widget_Data *wd = elm_widget_data_get(data);
230 if (!wd) return EINA_FALSE;
231 evas_object_event_callback_del(wd->scroller, EVAS_CALLBACK_RESIZE, _scroller_resize_event_cb);
232 evas_object_smart_callback_del(wd->focus_obj, SIG_IMPREGION_CHANGED, _imp_region_changed_cb);
234 wd->focus_obj = NULL;
238 /* unused now - but meant to be for making sure the focused widget is always
239 * visible when the vkbd comes and goes by moving the conformant obj (and thus
240 * its children) to show the focused widget (and if focus changes follow)
243 _focus_object_get(const Evas_Object *obj)
245 Evas_Object *win, *foc;
247 win = elm_widget_top_get(obj);
248 if (!win) return NULL;
249 foc = elm_widget_top_get(win);
253 _focus_object_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
255 evas_object_geometry_get(obj, x, y, w, h);
259 _focus_change_del(void *data, Evas_Object *obj, void *event_info)
261 // called from toplevel when the focused window shanges
265 _autoscroll_move(Evas_Object *obj)
267 // move conformant edje by delta to show focused widget
271 _autoscroll_mode_enable(Evas_Object *obj)
273 // called when autoscroll mode should be on - content area smaller than
275 // 1. get focused object
276 // 2. if not in visible conformant area calculate delta needed to
278 // 3. store delta and call _autoscroll_move() which either asanimates
279 // or jumps right there
283 _autoscroll_mode_disable(Evas_Object *obj)
285 // called when autoscroll mode should be off - set delta to 0 and
286 // call _autoscroll_move()
291 _prop_change(void *data, int type __UNUSED__, void *event)
293 #ifdef HAVE_ELEMENTARY_X
294 #ifdef HAVE_CONFORMANT_AUTOSCROLL
295 int indicator_height=57;
296 Ecore_X_Virtual_Keyboard_State virt_keypad_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN;
298 Ecore_X_Event_Window_Property *ev;
299 Widget_Data *wd = elm_widget_data_get(data);
300 if (!wd) return ECORE_CALLBACK_PASS_ON;
302 if (ev->atom == ECORE_X_ATOM_E_ILLUME_ZONE)
307 zone = ecore_x_e_illume_zone_get(ev->win);
308 ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
309 #ifdef HAVE_CONFORMANT_AUTOSCROLL
310 if (sh < 0) sh = indicator_height;
314 evas_object_size_hint_min_set(wd->shelf, -1, sh);
315 evas_object_size_hint_max_set(wd->shelf, -1, sh);
316 #ifdef HAVE_CONFORMANT_AUTOSCROLL
318 zone = ecore_x_e_illume_zone_get(ev->win);
319 ecore_x_e_illume_keyboard_geometry_get(zone, NULL, NULL, NULL, &sh);
321 evas_object_size_hint_min_set(wd->virtualkeypad, -1, sh);
322 evas_object_size_hint_max_set(wd->virtualkeypad, -1, sh);
325 ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
327 evas_object_size_hint_min_set(wd->panel, -1, sh);
328 evas_object_size_hint_max_set(wd->panel, -1, sh);
330 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
335 zone = ecore_x_e_illume_zone_get(ev->win);
336 ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
338 evas_object_size_hint_min_set(wd->shelf, -1, sh);
339 evas_object_size_hint_max_set(wd->shelf, -1, sh);
341 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
346 zone = ecore_x_e_illume_zone_get(ev->win);
347 ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
349 evas_object_size_hint_min_set(wd->panel, -1, sh);
350 evas_object_size_hint_max_set(wd->panel, -1, sh);
352 #ifdef HAVE_CONFORMANT_AUTOSCROLL
353 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
356 int ky = -1, kh = -1;
358 printf("Keyboard Geometry Changed\n");
359 zone = ecore_x_e_illume_zone_get(ev->win);
360 ecore_x_e_illume_keyboard_geometry_get(zone, NULL, &ky, NULL, &kh);
361 printf("\tGeom: %d\n", ky);
363 if (kh == wd->vkeypad_height) return ECORE_CALLBACK_PASS_ON;
364 wd->vkeypad_height = kh;
365 evas_object_size_hint_min_set(wd->virtualkeypad, -1, kh);
366 evas_object_size_hint_max_set(wd->virtualkeypad, -1, kh);
368 else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
371 zone = ecore_x_e_illume_zone_get(ev->win);
372 virt_keypad_state = ecore_x_e_virtual_keyboard_state_get(zone);
373 if (virt_keypad_state == wd->vkeypad_state) return ECORE_CALLBACK_PASS_ON;
374 wd->vkeypad_state = virt_keypad_state;
375 if(wd->vkeypad_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON)
377 _autoscroll_mode_enable(data);
379 else if(wd->vkeypad_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
381 _autoscroll_mode_disable(data);
387 return ECORE_CALLBACK_PASS_ON;
391 * Add a new Conformant object
393 * @param parent The parent object
394 * @return The new conformant object or NULL if it cannot be created
396 * @ingroup Conformant
399 elm_conformant_add(Evas_Object *parent)
405 wd = ELM_NEW(Widget_Data);
407 evas = evas_object_evas_get(parent);
409 obj = elm_widget_add(evas);
410 ELM_SET_WIDTYPE(widtype, "conformant");
411 elm_widget_type_set(obj, "conformant");
412 elm_widget_sub_object_add(parent, obj);
413 elm_widget_data_set(obj, wd);
414 elm_widget_del_hook_set(obj, _del_hook);
415 elm_widget_theme_hook_set(obj, _theme_hook);
417 wd->base = edje_object_add(evas);
418 _elm_theme_object_set(obj, wd->base, "conformant", "base", "default");
419 elm_widget_resize_object_set(obj, wd->base);
421 #ifdef HAVE_ELEMENTARY_X
422 Ecore_X_Window zone, xwin;
425 xwin = elm_win_xwindow_get(parent);
426 zone = ecore_x_e_illume_zone_get(xwin);
428 ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &sh);
430 wd->shelf = evas_object_rectangle_add(evas);
431 evas_object_color_set(wd->shelf, 0, 0, 0, 0);
432 evas_object_size_hint_min_set(wd->shelf, -1, sh);
433 evas_object_size_hint_max_set(wd->shelf, -1, sh);
434 edje_object_part_swallow(wd->base, "elm.swallow.shelf", wd->shelf);
436 #ifdef HAVE_CONFORMANT_AUTOSCROLL
438 wd->focus_obj = NULL;
440 ecore_x_e_illume_keyboard_geometry_get(zone, NULL, NULL, NULL, &sh);
442 wd->virtualkeypad= evas_object_rectangle_add(evas);
443 evas_object_color_set(wd->virtualkeypad, 0, 0, 0, 0);
444 evas_object_size_hint_min_set(wd->virtualkeypad, -1, sh);
445 evas_object_size_hint_max_set(wd->virtualkeypad, -1, sh);
446 edje_object_part_swallow(wd->base, "elm.swallow.virtualkeypad", wd->virtualkeypad);
447 wd->vkeypad_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN;
451 ecore_x_e_illume_softkey_geometry_get(zone, NULL, NULL, NULL, &sh);
453 wd->panel = evas_object_rectangle_add(evas);
454 evas_object_color_set(wd->panel, 0, 0, 0, 0);
455 evas_object_size_hint_min_set(wd->panel, -1, sh);
456 evas_object_size_hint_max_set(wd->panel, -1, sh);
457 edje_object_part_swallow(wd->base, "elm.swallow.panel", wd->panel);
459 wd->prop_hdl = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
461 // FIXME: get kbd region prop
464 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
471 * Set the content of the conformant widget
473 * Once the content object is set, a previously set one will be deleted.
474 * If you want to keep that old content object, use the
475 * elm_conformat_content_unset() function.
477 * @param obj The conformant object
478 * @return The content that was being used
480 * @ingroup Conformant
483 elm_conformant_content_set(Evas_Object *obj, Evas_Object *content)
485 ELM_CHECK_WIDTYPE(obj, widtype);
486 Widget_Data *wd = elm_widget_data_get(obj);
488 if (wd->content == content) return;
489 if (wd->content) evas_object_del(wd->content);
490 wd->content = content;
493 elm_widget_sub_object_add(obj, content);
494 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
495 _changed_size_hints, obj);
496 edje_object_part_swallow(wd->base, "elm.swallow.content", content);
502 * Unset the content of the conformant widget
504 * Unparent and return the content object which was set for this widget;
506 * @param obj The conformant object
507 * @return The content that was being used
509 * @ingroup Conformant
512 elm_conformant_content_unset(Evas_Object *obj)
514 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
515 Widget_Data *wd = elm_widget_data_get(obj);
516 Evas_Object *content;
517 if (!wd) return NULL;
518 if (!wd->content) return NULL;
519 content = wd->content;
520 elm_widget_sub_object_del(obj, wd->content);
521 edje_object_part_unswallow(wd->base, wd->content);