1 #include <Elementary.h>
6 # define STUPID(X) STR(X)
7 # define TTDBG(x...) fprintf(stderr, STUPID(__LINE__)": " x)
12 static const char _tooltip_key[] = "_elm_tooltip";
14 #define ELM_TOOLTIP_GET_OR_RETURN(tt, obj, ...) \
20 CRITICAL("Null pointer: " #obj); \
23 tt = evas_object_data_get((obj), _tooltip_key); \
26 ERR("Object does not have tooltip: " #obj); \
34 Elm_Tooltip_Content_Cb func;
39 Evas_Object *eventarea, *owner;
40 Evas_Object *tooltip, *content;
42 Ecore_Timer *show_timer;
43 Ecore_Timer *hide_timer;
44 Ecore_Job *reconfigure_job;
45 Evas_Coord mouse_x, mouse_y;
48 Evas_Coord x, y, bx, by;
54 double hide_timeout; /* from theme */
55 Eina_Bool visible_lock:1;
56 Eina_Bool changed_style:1;
57 Eina_Bool free_size : 1;
60 static void _elm_tooltip_reconfigure(Elm_Tooltip *tt);
61 static void _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt);
62 static void _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt);
63 static void _elm_tooltip_hide_anim_start(Elm_Tooltip *tt);
64 static void _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt);
65 static void _elm_tooltip_show_timer_stop(Elm_Tooltip *tt);
66 static void _elm_tooltip_hide(Elm_Tooltip *tt);
67 static void _elm_tooltip_data_clean(Elm_Tooltip *tt);
70 _elm_tooltip_content_changed_hints_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
72 _elm_tooltip_reconfigure_job_start(data);
73 TTDBG("HINTS CHANGED\n");
77 _elm_tooltip_content_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
79 Elm_Tooltip *tt = data;
81 tt->visible_lock = EINA_FALSE;
82 if (tt->tooltip) _elm_tooltip_hide(tt);
86 _elm_tooltip_obj_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
88 Elm_Tooltip *tt = data;
89 _elm_tooltip_reconfigure_job_start(tt);
94 _elm_tooltip_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
96 Elm_Tooltip *tt = data;
97 _elm_tooltip_reconfigure_job_start(tt);
102 _elm_tooltip_obj_mouse_move_cb(Elm_Tooltip *tt, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Event_Mouse_Move *ev)
104 if (tt->mouse_x || tt->mouse_y)
106 if ((abs(ev->cur.output.x - tt->mouse_x) < 3) &&
107 (abs(ev->cur.output.y - tt->mouse_y) < 3))
109 TTDBG("MOUSE MOVE REJECTED!\n");
113 tt->mouse_x = ev->cur.output.x;
114 tt->mouse_y = ev->cur.output.y;
115 TTDBG("MOUSE MOVED\n");
116 _elm_tooltip_reconfigure_job_start(tt);
120 _elm_tooltip_show(Elm_Tooltip *tt)
122 _elm_tooltip_show_timer_stop(tt);
123 _elm_tooltip_hide_anim_stop(tt);
128 _elm_tooltip_reconfigure_job_start(tt);
129 TTDBG("RECURSIVE JOB\n");
134 tt->tt_win = elm_win_add(NULL, "tooltip", ELM_WIN_TOOLTIP);
135 elm_win_override_set(tt->tt_win, EINA_TRUE);
136 tt->tt_evas = evas_object_evas_get(tt->tt_win);
137 tt->tooltip = edje_object_add(tt->tt_evas);
138 evas_object_size_hint_weight_set(tt->tooltip, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
139 evas_object_size_hint_align_set(tt->tooltip, EVAS_HINT_FILL, EVAS_HINT_FILL);
140 elm_win_resize_object_add(tt->tt_win, tt->tooltip);
143 tt->tooltip = edje_object_add(tt->evas);
144 if (!tt->tooltip) return;
147 evas_object_layer_set(tt->tooltip, ELM_OBJECT_LAYER_TOOLTIP);
149 evas_object_event_callback_add
150 (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
151 evas_object_event_callback_add
152 (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
153 evas_object_event_callback_add
154 (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_move_cb, tt);
156 tt->changed_style = EINA_TRUE;
157 _elm_tooltip_reconfigure_job_start(tt);
161 _elm_tooltip_content_del(Elm_Tooltip *tt)
163 if (!tt->content) return;
165 TTDBG("CONTENT DEL\n");
166 evas_object_event_callback_del_full
167 (tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
168 _elm_tooltip_content_changed_hints_cb, tt);
169 evas_object_event_callback_del_full
170 (tt->content, EVAS_CALLBACK_DEL,
171 _elm_tooltip_content_del_cb, tt);
172 evas_object_hide(tt->content);
173 evas_object_del(tt->content);
179 _elm_tooltip_hide(Elm_Tooltip *tt)
183 _elm_tooltip_show_timer_stop(tt);
184 _elm_tooltip_hide_anim_stop(tt);
185 _elm_tooltip_reconfigure_job_stop(tt);
187 if (!tt->tooltip) return;
188 if (tt->visible_lock) return;
190 _elm_tooltip_content_del(tt);
192 evas_object_event_callback_del_full
193 (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
194 evas_object_event_callback_del_full
195 (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
196 evas_object_event_callback_del_full
197 (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_move_cb, tt);
199 del = tt->tt_win ?: tt->tooltip;
204 evas_object_del(del);
208 _elm_tooltip_reconfigure_job(void *data)
210 Elm_Tooltip *tt = data;
211 tt->reconfigure_job = NULL;
212 _elm_tooltip_reconfigure(data);
216 _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt)
218 if (!tt->reconfigure_job) return;
219 ecore_job_del(tt->reconfigure_job);
220 tt->reconfigure_job = NULL;
224 _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt)
226 if (tt->reconfigure_job) ecore_job_del(tt->reconfigure_job);
227 tt->reconfigure_job = ecore_job_add(_elm_tooltip_reconfigure_job, tt);
231 _elm_tooltip_hide_anim_cb(void *data)
233 Elm_Tooltip *tt = data;
234 tt->hide_timer = NULL;
235 _elm_tooltip_hide(tt);
240 _elm_tooltip_hide_anim_start(Elm_Tooltip *tt)
243 if (tt->hide_timer) return;
244 TTDBG("HIDE START\n");
245 /* hide slightly faster when in window mode to look less stupid */
246 if ((tt->hide_timeout > 0) && tt->tt_win) extra = 0.1;
247 edje_object_signal_emit(tt->tooltip, "elm,action,hide", "elm");
248 tt->hide_timer = ecore_timer_add
249 (tt->hide_timeout - extra, _elm_tooltip_hide_anim_cb, tt);
253 _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt)
255 if (!tt->hide_timer) return;
257 edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
258 ecore_timer_del(tt->hide_timer);
259 tt->hide_timer = NULL;
263 _elm_tooltip_reconfigure(Elm_Tooltip *tt)
265 Evas_Coord ox, oy, ow, oh, px, py, tx, ty, tw, th, cw = 0, ch = 0;
266 Evas_Coord eminw, eminh, ominw, ominh;
268 Eina_Bool inside_eventarea;
270 _elm_tooltip_reconfigure_job_stop(tt);
272 if (tt->hide_timer) return;
273 if (!tt->tooltip) return;
274 if (tt->changed_style)
276 const char *style = tt->style ? tt->style : "default";
278 if (!_elm_theme_object_set(tt->tt_win ? NULL : tt->owner, tt->tooltip,
279 "tooltip", "base", style))
281 ERR("Could not apply the theme to the tooltip! style=%s", style);
282 if (tt->tt_win) evas_object_del(tt->tt_win);
283 else evas_object_del(tt->tooltip);
297 tt->hide_timeout = 0.0;
299 str = edje_object_data_get(tt->tooltip, "transparent");
301 { /* FIXME: hardcoded here is bad */
302 if (str && (!strcmp(str, "enabled")))
304 evas_object_hide(tt->tt_win);
305 elm_win_alpha_set(tt->tt_win, EINA_TRUE);
306 #ifdef HAVE_ELEMENTARY_X
307 ecore_x_window_shape_input_rectangle_set(elm_win_xwindow_get(tt->tt_win), 0, 0, 0, 0);
309 evas_object_show(tt->tt_win);
313 evas_object_hide(tt->tt_win);
314 elm_win_alpha_set(tt->tt_win, EINA_FALSE);
315 #ifdef HAVE_ELEMENTARY_X
316 ecore_x_window_shape_input_rectangle_set(elm_win_xwindow_get(tt->tt_win), 0, 0, 0, 0);
318 evas_object_show(tt->tt_win);
322 str = edje_object_data_get(tt->tooltip, "pad_x");
323 if (str) tt->pad.x = atoi(str);
324 str = edje_object_data_get(tt->tooltip, "pad_y");
325 if (str) tt->pad.y = atoi(str);
327 str = edje_object_data_get(tt->tooltip, "pad_border_x");
328 if (str) tt->pad.bx = atoi(str);
329 str = edje_object_data_get(tt->tooltip, "pad_border_y");
330 if (str) tt->pad.by = atoi(str);
332 str = edje_object_data_get(tt->tooltip, "hide_timeout");
335 tt->hide_timeout = _elm_atof(str);
336 if (tt->hide_timeout < 0.0) tt->hide_timeout = 0.0;
339 evas_object_pass_events_set(tt->tooltip, EINA_TRUE);
340 tt->changed_style = EINA_FALSE;
342 edje_object_part_swallow(tt->tooltip, "elm.swallow.content",
345 edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
350 tt->content = tt->func((void *)tt->data, tt->owner, tt->tt_win ? : tt->owner);
353 WRN("could not create tooltip content!");
354 if (tt->tt_win) evas_object_del(tt->tt_win);
355 else evas_object_del(tt->tooltip);
362 evas_object_show(tt->content);
363 evas_object_layer_set(tt->content, ELM_OBJECT_LAYER_TOOLTIP);
364 evas_object_pass_events_set(tt->content, EINA_TRUE);
365 edje_object_part_swallow
366 (tt->tooltip, "elm.swallow.content", tt->content);
367 evas_object_event_callback_add(tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
368 _elm_tooltip_content_changed_hints_cb, tt);
369 evas_object_event_callback_add(tt->content, EVAS_CALLBACK_DEL,
370 _elm_tooltip_content_del_cb, tt);
373 TTDBG("*******RECALC\n");
374 evas_object_size_hint_min_get(tt->content, &ominw, &ominh);
375 edje_object_size_min_get(tt->tooltip, &eminw, &eminh);
377 if (eminw && (ominw < eminw)) ominw = eminw;
378 if (eminh && (ominh < eminh)) ominh = eminh;
380 if (ominw < 1) ominw = 10; /* at least it is noticeable */
381 if (ominh < 1) ominh = 10; /* at least it is noticeable */
383 edje_object_size_min_restricted_calc(tt->tooltip, &tw, &th, ominw, ominh);
384 TTDBG("TTSIZE: tw=%d,th=%d,ominw=%d,ominh=%d\n", tw, th, ominw, ominh);
387 elm_win_screen_size_get(elm_object_top_widget_get(tt->owner), NULL, NULL, &cw, &ch);
389 evas_output_size_get(tt->tt_evas ?: tt->evas, &cw, &ch);
390 TTDBG("SCREEN: cw=%d,ch=%d\n", cw, ch);
392 evas_object_geometry_get(tt->eventarea, &ox, &oy, &ow, &oh);
393 TTDBG("EVENTAREA: ox=%d,oy=%d,ow=%d,oh=%d\n", ox, oy, ow, oh);
398 Evas_Object *win = elm_object_top_widget_get(tt->owner);
399 #ifdef HAVE_ELEMENTARY_X
400 Ecore_X_Window xwin = elm_win_xwindow_get(win);
401 ecore_x_pointer_xy_get(xwin, &px, &py);
403 elm_win_screen_position_get(win, &x, &y);
410 evas_pointer_canvas_xy_get(tt->evas, &px, &py);
411 TTDBG("POINTER: px=%d,py=%d\n", px, py);
412 inside_eventarea = ((px >= ox) && (py >= oy) &&
413 (px <= ox + ow) && (py <= oy + oh));
414 if (inside_eventarea)
416 /* try to position bottom right corner at pointer */
419 TTDBG("INIT (EVENTAREA)\n");
423 /* try centered on middle of eventarea */
424 tx = ox + (ow / 2) - (tw / 2);
425 if (0 > (th - oy - oh)) ty = oy + th;
427 TTDBG("INIT (INTERPRETED)\n");
429 TTDBG("ADJUST (POINTER): tx=%d,ty=%d\n", tx, ty);
432 /* if we're offscreen, try to flip over the Y axis */
433 if (abs((tx + 2 * tw) - cw) < abs(tx))
436 else if ((tx > px) && (px > tw))
443 /* if we're offscreen, try to flip over the X axis */
444 if (abs((ty + 2 * th) - ch) < abs(ty))
447 else if ((ty > py) && (py > th))
452 TTDBG("ADJUST (FLIP): tx=%d,ty=%d\n", tx, ty);
453 if (inside_eventarea)
455 if ((tx == px) && ((tx + tw + tt->pad.x < cw) || (tx + tw > cw))) tx += tt->pad.x;
456 else if ((tx - tt->pad.x > 0) || (tx < 0)) tx -= tt->pad.x;
457 if ((ty == py) && ((ty + th + tt->pad.y < ch) || (ty + th > ch))) ty += tt->pad.y;
458 else if ((ty - tt->pad.y > 0) || (ty < 0)) ty -= tt->pad.y;
460 TTDBG("PAD: tx=%d,ty=%d\n", tx, ty);
461 if (tt->pad.bx * 2 + tw < cw)
463 if (tx < tt->pad.bx) tx = tt->pad.bx;
464 else if ((tx >= tw) && (tx + tt->pad.bx <= cw)) tx += tt->pad.bx;
465 else if (tx - tt->pad.bx >= 0) tx -= tt->pad.bx;
467 else if (tx < 0) tx -= tt->pad.bx;
468 else if (tx > cw) tx += tt->pad.bx;
469 if (tt->pad.by * 2 + th < ch)
471 if (ty < tt->pad.by) ty = tt->pad.by;
472 else if ((ty >= th) && (ty + tt->pad.by <= ch)) ty += tt->pad.by;
473 else if (ty - tt->pad.by >= 0) ty -= tt->pad.by;
475 else if (ty < 0) ty -= tt->pad.by;
476 else if (ty > ch) ty += tt->pad.by;
477 TTDBG("PAD (BORDER): tx=%d,ty=%d\n", tx, ty);
478 if (((tx < 0) && (tw < cw)) || ((ty < 0) && (th < ch)))
480 TTDBG("POSITIONING FAILED! THIS IS A BUG SOMEWHERE!\n");
484 evas_object_move(tt->tt_win ? : tt->tooltip, tx, ty);
485 evas_object_resize(tt->tt_win ? : tt->tooltip, tw, th);
486 TTDBG("FINAL: tx=%d,ty=%d,tw=%d,th=%d\n", tx, ty, tw, th);
487 evas_object_show(tt->tooltip);
489 if (inside_eventarea)
491 rel_x = (px - tx) / (double)tw;
492 rel_y = (py - ty) / (double)th;
496 rel_x = (ox + (ow / 2) - tx) / (double)tw;
497 rel_y = (oy + (oh / 2) - ty) / (double)th;
500 #define FDIF(a, b) (fabs((a) - (b)) > 0.0001)
501 if ((FDIF(rel_x, tt->rel_pos.x)) || (FDIF(rel_y, tt->rel_pos.y)))
503 Edje_Message_Float_Set *msg;
505 msg = alloca(sizeof(Edje_Message_Float_Set) + sizeof(double));
509 tt->rel_pos.x = rel_x;
510 tt->rel_pos.y = rel_y;
512 edje_object_message_send(tt->tooltip, EDJE_MESSAGE_FLOAT_SET, 1, msg);
518 _elm_tooltip_show_timer_stop(Elm_Tooltip *tt)
520 if (!tt->show_timer) return;
521 ecore_timer_del(tt->show_timer);
522 tt->show_timer = NULL;
526 _elm_tooltip_timer_show_cb(void *data)
528 Elm_Tooltip *tt = data;
529 tt->show_timer = NULL;
530 _elm_tooltip_show(tt);
531 return ECORE_CALLBACK_CANCEL;
535 _elm_tooltip_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
537 Elm_Tooltip *tt = data;
539 _elm_tooltip_hide_anim_stop(tt);
541 if ((tt->show_timer) || (tt->tooltip)) return;
543 tt->show_timer = ecore_timer_add(_elm_config->tooltip_delay, _elm_tooltip_timer_show_cb, tt);
548 _elm_tooltip_obj_mouse_out_cb(Elm_Tooltip *tt, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Event_Mouse_Out *event __UNUSED__)
550 if (tt->visible_lock) return;
554 _elm_tooltip_show_timer_stop(tt);
557 _elm_tooltip_hide_anim_start(tt);
558 TTDBG("MOUSE OUT\n");
561 static void _elm_tooltip_obj_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
564 _elm_tooltip_unset(Elm_Tooltip *tt)
566 tt->visible_lock = EINA_FALSE;
567 _elm_tooltip_hide(tt);
568 _elm_tooltip_data_clean(tt);
572 evas_object_event_callback_del_full
573 (tt->eventarea, EVAS_CALLBACK_MOUSE_IN,
574 _elm_tooltip_obj_mouse_in_cb, tt);
575 evas_object_event_callback_del_full
576 (tt->eventarea, EVAS_CALLBACK_MOUSE_OUT,
577 (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_out_cb, tt);
578 evas_object_event_callback_del_full
579 (tt->eventarea, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
581 evas_object_data_del(tt->eventarea, _tooltip_key);
585 evas_object_event_callback_del_full
586 (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
587 elm_widget_tooltip_del(tt->owner, tt);
590 eina_stringshare_del(tt->style);
595 _elm_tooltip_obj_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
597 Elm_Tooltip *tt = data;
598 if (tt->eventarea == obj) tt->eventarea = NULL;
599 if (tt->owner == obj) tt->owner = NULL;
600 _elm_tooltip_unset(tt);
604 _elm_tooltip_label_create(void *data, Evas_Object *obj __UNUSED__, Evas_Object *tooltip)
606 Evas_Object *label = elm_label_add(tooltip);
609 elm_object_style_set(label, "tooltip");
610 elm_object_text_set(label, data);
615 _elm_tooltip_trans_label_create(void *data, Evas_Object *obj __UNUSED__, Evas_Object *tooltip)
617 Evas_Object *label = elm_label_add(tooltip);
618 const char **text = data;
621 elm_object_style_set(label, "tooltip");
622 elm_object_domain_translatable_text_set(label, text[0], text[1]);
627 _elm_tooltip_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
629 eina_stringshare_del(data);
633 _elm_tooltip_trans_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
635 const char **text = data;
636 eina_stringshare_del(text[0]);
637 eina_stringshare_del(text[1]);
642 _elm_tooltip_data_clean(Elm_Tooltip *tt)
644 if (tt->del_cb) tt->del_cb((void *)tt->data, tt->owner, NULL);
646 _elm_tooltip_content_del(tt);
653 * Notify tooltip should recalculate its theme.
657 elm_tooltip_theme(Elm_Tooltip *tt)
659 if (!tt->tooltip) return;
660 tt->changed_style = EINA_TRUE;
661 _elm_tooltip_reconfigure_job_start(tt);
666 * Set the content to be shown in the tooltip object for specific event area.
668 * Setup the tooltip to object. The object @a eventarea can have only
669 * one tooltip, so any previous tooltip data is removed. @p func(with
670 * @p data) will be called every time that need show the tooltip and
671 * it should return a valid Evas_Object. This object is then managed
672 * fully by tooltip system and is deleted when the tooltip is gone.
674 * This is an internal function that is used by objects with sub-items
675 * that want to provide different tooltips for each of them. The @a
676 * owner object should be an elm_widget and will be used to track
677 * theme changes and to feed @a func and @a del_cb. The @a eventarea
678 * may be any object and is the one that should be used later on with
679 * elm_object_tooltip apis, such as elm_object_tooltip_hide(),
680 * elm_object_tooltip_show() or elm_object_tooltip_unset().
682 * @param eventarea the object being attached a tooltip.
683 * @param owner the elm_widget that owns this object, will be used to
684 * track theme changes and to be used in @a func or @a del_cb.
685 * @param func the function used to create the tooltip contents. The
686 * @a Evas_Object parameters will receive @a owner as value.
687 * @param data what to provide to @a func as callback data/context.
688 * @param del_cb called when data is not needed anymore, either when
689 * another callback replaces @p func, the tooltip is unset with
690 * elm_object_tooltip_unset() or the owner object @a obj
691 * dies. This callback receives as the first parameter the
692 * given @a data, and @c event_info is NULL.
698 elm_object_sub_tooltip_content_cb_set(Evas_Object *eventarea, Evas_Object *owner, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
700 Elm_Tooltip *tt = NULL;
701 Eina_Bool just_created;
703 EINA_SAFETY_ON_NULL_GOTO(owner, error);
704 EINA_SAFETY_ON_NULL_GOTO(eventarea, error);
708 elm_object_tooltip_unset(eventarea);
712 tt = evas_object_data_get(eventarea, _tooltip_key);
715 if (tt->owner != owner)
717 if (tt->owner != eventarea)
718 evas_object_event_callback_del_full
719 (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
721 elm_widget_tooltip_del(tt->owner, tt);
723 if (owner != eventarea)
724 evas_object_event_callback_add
725 (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
727 elm_widget_tooltip_add(tt->owner, tt);
730 if ((tt->func == func) && (tt->data == data) &&
731 (tt->del_cb == del_cb))
733 _elm_tooltip_data_clean(tt);
734 just_created = EINA_FALSE;
738 tt = ELM_NEW(Elm_Tooltip);
742 tt->eventarea = eventarea;
743 tt->evas = evas_object_evas_get(eventarea);
744 evas_object_data_set(eventarea, _tooltip_key, tt);
746 just_created = EINA_TRUE;
748 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_IN,
749 _elm_tooltip_obj_mouse_in_cb, tt);
750 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_OUT,
751 (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_out_cb, tt);
752 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_FREE,
753 _elm_tooltip_obj_free_cb, tt);
755 if (owner != eventarea)
756 evas_object_event_callback_add
757 (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
759 elm_widget_tooltip_add(tt->owner, tt);
766 if (!just_created) _elm_tooltip_reconfigure_job_start(tt);
770 if (del_cb) del_cb((void *)data, owner, NULL);
774 * Force show tooltip of object
776 * @param obj Target object
778 * Force show the tooltip and disable hide on mouse_out.
779 * If another content is set as tooltip, the visible tooltip will hididen and
780 * showed again with new content.
781 * This can force show more than one tooltip at a time.
786 elm_object_tooltip_show(Evas_Object *obj)
788 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
789 tt->visible_lock = EINA_TRUE;
790 _elm_tooltip_show(tt);
794 * Force hide tooltip of object
796 * @param obj Target object
798 * Force hide the tooltip and (re)enable future mouse interations.
803 elm_object_tooltip_hide(Evas_Object *obj)
805 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
806 tt->visible_lock = EINA_FALSE;
807 _elm_tooltip_hide_anim_start(tt);
811 * Set the text to be shown in the tooltip object
813 * @param obj Target object
814 * @param text The text to set in the content
816 * Setup the text as tooltip to object. The object can have only one tooltip,
817 * so any previous tooltip data is removed.
818 * This method call internaly the elm_tooltip_content_cb_set().
823 elm_object_tooltip_text_set(Evas_Object *obj, const char *text)
825 EINA_SAFETY_ON_NULL_RETURN(obj);
826 EINA_SAFETY_ON_NULL_RETURN(text);
828 text = eina_stringshare_add(text);
829 elm_object_tooltip_content_cb_set
830 (obj, _elm_tooltip_label_create, text, _elm_tooltip_label_del_cb);
836 elm_object_tooltip_domain_translatable_text_set(Evas_Object *obj, const char *domain, const char *text)
839 EINA_SAFETY_ON_NULL_RETURN(obj);
840 EINA_SAFETY_ON_NULL_RETURN(text);
842 data = malloc(2 * sizeof(char *));
844 data[0] = eina_stringshare_add(domain);
845 data[1] = eina_stringshare_add(text);
846 elm_object_tooltip_content_cb_set
847 (obj, _elm_tooltip_trans_label_create, data,
848 _elm_tooltip_trans_label_del_cb);
852 * Set the content to be shown in the tooltip object
854 * Setup the tooltip to object. The object can have only one tooltip,
855 * so any previous tooltip data is removed. @p func(with @p data) will
856 * be called every time that need show the tooltip and it should
857 * return a valid Evas_Object. This object is then managed fully by
858 * tooltip system and is deleted when the tooltip is gone.
860 * @param obj the object being attached a tooltip.
861 * @param func the function used to create the tooltip contents.
862 * @param data what to provide to @a func as callback data/context.
863 * @param del_cb called when data is not needed anymore, either when
864 * another callback replaces @p func, the tooltip is unset with
865 * elm_object_tooltip_unset() or the owner object @a obj
866 * dies. This callback receives as the first parameter the
867 * given @a data, and @c event_info is NULL.
872 elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
874 elm_object_sub_tooltip_content_cb_set(obj, obj, func, data, del_cb);
878 * Unset tooltip from object
880 * @param obj Target object
882 * Remove tooltip from object. The callback provided as del_cb to
883 * elm_object_tooltip_content_cb_set() will be called to notify it is
886 * @see elm_object_tooltip_content_cb_set()
891 elm_object_tooltip_unset(Evas_Object *obj)
893 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
894 _elm_tooltip_unset(tt);
898 * Sets a different style for this object tooltip.
900 * @note before you set a style you should define a tooltip with
901 * elm_object_tooltip_content_cb_set() or
902 * elm_object_tooltip_text_set().
904 * @param obj an object with tooltip already set.
905 * @param style the theme style to use (default, transparent, ...)
908 elm_object_tooltip_style_set(Evas_Object *obj, const char *style)
910 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
911 if (!eina_stringshare_replace(&tt->style, style)) return;
912 elm_tooltip_theme(tt);
916 * Get the style for this object tooltip.
918 * @param obj an object with tooltip already set.
919 * @return style the theme style in use, defaults to "default". If the
920 * object does not have a tooltip set, then NULL is returned.
923 elm_object_tooltip_style_get(const Evas_Object *obj)
925 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, NULL);
926 return tt->style ? tt->style : "default";
930 * @brief Disable size restrictions on an object's tooltip
931 * @param obj The tooltip's anchor object
932 * @param disable If EINA_TRUE, size restrictions are disabled
933 * @return EINA_FALSE on failure, EINA_TRUE on success
935 * This function allows a tooltip to expand beyond its parent window's canvas.
936 * It will instead be limited only by the size of the display.
939 elm_object_tooltip_window_mode_set(Evas_Object *obj, Eina_Bool disable)
941 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, EINA_FALSE);
942 return tt->free_size = disable;
946 * @brief Retrieve size restriction state of an object's tooltip
947 * @param obj The tooltip's anchor object
948 * @return If EINA_TRUE, size restrictions are disabled
950 * This function returns whether a tooltip is allowed to expand beyond
951 * its parent window's canvas.
952 * It will instead be limited only by the size of the display.
955 elm_object_tooltip_window_mode_get(const Evas_Object *obj)
957 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, EINA_FALSE);
958 return tt->free_size;