Merge branch 'master' into svn_merge
[framework/uifw/elementary.git] / src / lib / els_cursor.c
1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
3 #include "elm_priv.h"
4
5 #ifdef HAVE_ELEMENTARY_X
6 #include <Ecore_X.h>
7 #include <Ecore_X_Cursor.h>
8 #endif
9
10 /**
11  * @defgroup Cursors Cursors
12  *
13  * The Cursor is an internal smart object used to customize the
14  * cursor displayed over objects (or widgets).
15  * It can use default X cursors (if using X), or cursors from a
16  * theme.
17  */
18
19 #define _cursor_key "_elm_cursor"
20
21 struct _Cursor_Id
22 {
23    const char *name;
24 #ifdef HAVE_ELEMENTARY_X
25    int id;
26 #endif
27 };
28
29 #ifdef HAVE_ELEMENTARY_X
30 #define CURSOR(_name, _xid) \
31    {_name , _xid}
32 # else
33 #define CURSOR(_name, _xid) \
34    {_name}
35 #endif
36
37 /* Please keep order in sync with Ecore_X_Cursor.h values! */
38 struct _Cursor_Id _cursors[] =
39 {
40    CURSOR(ELM_CURSOR_X                  , ECORE_X_CURSOR_X                  ),
41    CURSOR(ELM_CURSOR_ARROW              , ECORE_X_CURSOR_ARROW              ),
42    CURSOR(ELM_CURSOR_BASED_ARROW_DOWN   , ECORE_X_CURSOR_BASED_ARROW_DOWN   ),
43    CURSOR(ELM_CURSOR_BASED_ARROW_UP     , ECORE_X_CURSOR_UP                 ),
44    CURSOR(ELM_CURSOR_BOAT               , ECORE_X_CURSOR_BOAT               ),
45    CURSOR(ELM_CURSOR_BOGOSITY           , ECORE_X_CURSOR_BOGOSITY           ),
46    CURSOR(ELM_CURSOR_BOTTOM_LEFT_CORNER , ECORE_X_CURSOR_BOTTOM_LEFT_CORNER ),
47    CURSOR(ELM_CURSOR_BOTTOM_RIGHT_CORNER, ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER),
48    CURSOR(ELM_CURSOR_BOTTOM_SIDE        , ECORE_X_CURSOR_BOTTOM_SIDE        ),
49    CURSOR(ELM_CURSOR_BOTTOM_TEE         , ECORE_X_CURSOR_BOTTOM_TEE         ),
50    CURSOR(ELM_CURSOR_BOX_SPIRAL         , ECORE_X_CURSOR_BOX_SPIRAL         ),
51    CURSOR(ELM_CURSOR_CENTER_PTR         , ECORE_X_CURSOR_CENTER_PTR         ),
52    CURSOR(ELM_CURSOR_CIRCLE             , ECORE_X_CURSOR_CIRCLE             ),
53    CURSOR(ELM_CURSOR_CLOCK              , ECORE_X_CURSOR_CLOCK              ),
54    CURSOR(ELM_CURSOR_COFFEE_MUG         , ECORE_X_CURSOR_COFFEE_MUG         ),
55    CURSOR(ELM_CURSOR_CROSS              , ECORE_X_CURSOR_CROSS              ),
56    CURSOR(ELM_CURSOR_CROSS_REVERSE      , ECORE_X_CURSOR_CROSS_REVERSE      ),
57    CURSOR(ELM_CURSOR_CROSSHAIR          , ECORE_X_CURSOR_CROSSHAIR          ),
58    CURSOR(ELM_CURSOR_DIAMOND_CROSS      , ECORE_X_CURSOR_DIAMOND_CROSS      ),
59    CURSOR(ELM_CURSOR_DOT                , ECORE_X_CURSOR_DOT                ),
60    CURSOR(ELM_CURSOR_DOT_BOX_MASK       , ECORE_X_CURSOR_DOT_BOX_MASK       ),
61    CURSOR(ELM_CURSOR_DOUBLE_ARROW       , ECORE_X_CURSOR_DOUBLE_ARROW       ),
62    CURSOR(ELM_CURSOR_DRAFT_LARGE        , ECORE_X_CURSOR_DRAFT_LARGE        ),
63    CURSOR(ELM_CURSOR_DRAFT_SMALL        , ECORE_X_CURSOR_DRAFT_SMALL        ),
64    CURSOR(ELM_CURSOR_DRAPED_BOX         , ECORE_X_CURSOR_DRAPED_BOX         ),
65    CURSOR(ELM_CURSOR_EXCHANGE           , ECORE_X_CURSOR_EXCHANGE           ),
66    CURSOR(ELM_CURSOR_FLEUR              , ECORE_X_CURSOR_FLEUR              ),
67    CURSOR(ELM_CURSOR_GOBBLER            , ECORE_X_CURSOR_GOBBLER            ),
68    CURSOR(ELM_CURSOR_GUMBY              , ECORE_X_CURSOR_GUMBY              ),
69    CURSOR(ELM_CURSOR_HAND1              , ECORE_X_CURSOR_HAND1              ),
70    CURSOR(ELM_CURSOR_HAND2              , ECORE_X_CURSOR_HAND2              ),
71    CURSOR(ELM_CURSOR_HEART              , ECORE_X_CURSOR_HEART              ),
72    CURSOR(ELM_CURSOR_ICON               , ECORE_X_CURSOR_ICON               ),
73    CURSOR(ELM_CURSOR_IRON_CROSS         , ECORE_X_CURSOR_IRON_CROSS         ),
74    CURSOR(ELM_CURSOR_LEFT_PTR           , ECORE_X_CURSOR_LEFT_PTR           ),
75    CURSOR(ELM_CURSOR_LEFT_SIDE          , ECORE_X_CURSOR_LEFT_SIDE          ),
76    CURSOR(ELM_CURSOR_LEFT_TEE           , ECORE_X_CURSOR_LEFT_TEE           ),
77    CURSOR(ELM_CURSOR_LEFTBUTTON         , ECORE_X_CURSOR_LEFTBUTTON         ),
78    CURSOR(ELM_CURSOR_LL_ANGLE           , ECORE_X_CURSOR_LL_ANGLE           ),
79    CURSOR(ELM_CURSOR_LR_ANGLE           , ECORE_X_CURSOR_LR_ANGLE           ),
80    CURSOR(ELM_CURSOR_MAN                , ECORE_X_CURSOR_MAN                ),
81    CURSOR(ELM_CURSOR_MIDDLEBUTTON       , ECORE_X_CURSOR_MIDDLEBUTTON       ),
82    CURSOR(ELM_CURSOR_MOUSE              , ECORE_X_CURSOR_MOUSE              ),
83    CURSOR(ELM_CURSOR_PENCIL             , ECORE_X_CURSOR_PENCIL             ),
84    CURSOR(ELM_CURSOR_PIRATE             , ECORE_X_CURSOR_PIRATE             ),
85    CURSOR(ELM_CURSOR_PLUS               , ECORE_X_CURSOR_PLUS               ),
86    CURSOR(ELM_CURSOR_QUESTION_ARROW     , ECORE_X_CURSOR_QUESTION_ARROW     ),
87    CURSOR(ELM_CURSOR_RIGHT_PTR          , ECORE_X_CURSOR_RIGHT_PTR          ),
88    CURSOR(ELM_CURSOR_RIGHT_SIDE         , ECORE_X_CURSOR_RIGHT_SIDE         ),
89    CURSOR(ELM_CURSOR_RIGHT_TEE          , ECORE_X_CURSOR_RIGHT_TEE          ),
90    CURSOR(ELM_CURSOR_RIGHTBUTTON        , ECORE_X_CURSOR_RIGHTBUTTON        ),
91    CURSOR(ELM_CURSOR_RTL_LOGO           , ECORE_X_CURSOR_RTL_LOGO           ),
92    CURSOR(ELM_CURSOR_SAILBOAT           , ECORE_X_CURSOR_SAILBOAT           ),
93    CURSOR(ELM_CURSOR_SB_DOWN_ARROW      , ECORE_X_CURSOR_SB_DOWN_ARROW      ),
94    CURSOR(ELM_CURSOR_SB_H_DOUBLE_ARROW  , ECORE_X_CURSOR_SB_H_DOUBLE_ARROW  ),
95    CURSOR(ELM_CURSOR_SB_LEFT_ARROW      , ECORE_X_CURSOR_SB_LEFT_ARROW      ),
96    CURSOR(ELM_CURSOR_SB_RIGHT_ARROW     , ECORE_X_CURSOR_SB_RIGHT_ARROW     ),
97    CURSOR(ELM_CURSOR_SB_UP_ARROW        , ECORE_X_CURSOR_SB_UP_ARROW        ),
98    CURSOR(ELM_CURSOR_SB_V_DOUBLE_ARROW  , ECORE_X_CURSOR_SB_V_DOUBLE_ARROW  ),
99    CURSOR(ELM_CURSOR_SHUTTLE            , ECORE_X_CURSOR_SHUTTLE            ),
100    CURSOR(ELM_CURSOR_SIZING             , ECORE_X_CURSOR_SIZING             ),
101    CURSOR(ELM_CURSOR_SPIDER             , ECORE_X_CURSOR_SPIDER             ),
102    CURSOR(ELM_CURSOR_SPRAYCAN           , ECORE_X_CURSOR_SPRAYCAN           ),
103    CURSOR(ELM_CURSOR_STAR               , ECORE_X_CURSOR_STAR               ),
104    CURSOR(ELM_CURSOR_TARGET             , ECORE_X_CURSOR_TARGET             ),
105    CURSOR(ELM_CURSOR_TCROSS             , ECORE_X_CURSOR_TCROSS             ),
106    CURSOR(ELM_CURSOR_TOP_LEFT_ARROW     , ECORE_X_CURSOR_TOP_LEFT_ARROW     ),
107    CURSOR(ELM_CURSOR_TOP_LEFT_CORNER    , ECORE_X_CURSOR_TOP_LEFT_CORNER    ),
108    CURSOR(ELM_CURSOR_TOP_RIGHT_CORNER   , ECORE_X_CURSOR_TOP_RIGHT_CORNER   ),
109    CURSOR(ELM_CURSOR_TOP_SIDE           , ECORE_X_CURSOR_TOP_SIDE           ),
110    CURSOR(ELM_CURSOR_TOP_TEE            , ECORE_X_CURSOR_TOP_TEE            ),
111    CURSOR(ELM_CURSOR_TREK               , ECORE_X_CURSOR_TREK               ),
112    CURSOR(ELM_CURSOR_UL_ANGLE           , ECORE_X_CURSOR_UL_ANGLE           ),
113    CURSOR(ELM_CURSOR_UMBRELLA           , ECORE_X_CURSOR_UMBRELLA           ),
114    CURSOR(ELM_CURSOR_UR_ANGLE           , ECORE_X_CURSOR_UR_ANGLE           ),
115    CURSOR(ELM_CURSOR_WATCH              , ECORE_X_CURSOR_WATCH              ),
116    CURSOR(ELM_CURSOR_XTERM              , ECORE_X_CURSOR_XTERM              )
117 };
118 static const int _cursors_count = sizeof(_cursors)/sizeof(struct _Cursor_Id);
119
120 #define ELM_CURSOR_GET_OR_RETURN(cur, obj, ...)         \
121   Elm_Cursor *cur;                                      \
122   do                                                    \
123     {                                                   \
124        if (!(obj))                                      \
125          {                                              \
126             CRITICAL("Null pointer: " #obj);            \
127             return __VA_ARGS__;                         \
128          }                                              \
129        cur = evas_object_data_get((obj), _cursor_key);  \
130        if (!cur)                                        \
131          {                                              \
132             ERR("Object does not have cursor: " #obj);  \
133             return __VA_ARGS__;                         \
134          }                                              \
135     }                                                   \
136   while (0)
137
138 struct _Elm_Cursor
139 {
140    Evas_Object *obj;
141    Evas_Object *eventarea, *owner;
142    const char *style, *cursor_name;
143    int hot_x, hot_y;
144    Ecore_Evas *ee;
145    Evas *evas;
146 #ifdef HAVE_ELEMENTARY_X
147    Ecore_X_Cursor cursor;
148    Ecore_X_Window win;
149 #endif
150    Eina_Bool visible:1;
151    Eina_Bool use_engine:1;
152    Eina_Bool engine_only:1;
153 };
154
155 static void
156 _elm_cursor_obj_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
157 {
158    Elm_Cursor *cur = data;
159
160    if (cur) cur->obj = NULL;
161 }
162
163 static Eina_Bool
164 _elm_cursor_obj_add(Evas_Object *obj, Elm_Cursor *cur)
165 {
166    int x, y;
167
168    cur->obj = edje_object_add(cur->evas);
169
170    if (!cur->obj)
171      return EINA_FALSE;
172
173    if (!_elm_theme_object_set(obj, cur->obj, "cursor", cur->cursor_name,
174                               cur->style ? cur->style : "default"))
175      {
176         evas_object_del(cur->obj);
177         cur->obj = NULL;
178         return EINA_FALSE;
179      }
180
181    evas_object_event_callback_add(cur->obj, EVAS_CALLBACK_DEL,
182                                   _elm_cursor_obj_del, cur);
183
184    edje_object_size_min_get(cur->obj, &x, &y);
185    evas_object_resize(cur->obj, x, y);
186    return EINA_TRUE;
187 }
188
189 static void
190 _elm_cursor_set_hot_spots(Elm_Cursor *cur)
191 {
192    const char *str;
193
194    str = edje_object_data_get(cur->obj, "hot_x");
195    if (str) cur->hot_x = atoi(str);
196    else cur->hot_x = 0;
197
198    str = edje_object_data_get(cur->obj, "hot_y");
199    if (str) cur->hot_y = atoi(str);
200    else cur->hot_y = 0;
201 }
202
203 static void
204 _elm_cursor_mouse_in(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
205 {
206    Elm_Cursor *cur = data;
207
208    if (cur->visible) return;
209    evas_event_freeze(cur->evas);
210    cur->visible = EINA_TRUE;
211    if ((!cur->engine_only) && (!cur->use_engine))
212      {
213         if (!cur->obj)
214           _elm_cursor_obj_add(cur->eventarea, cur);
215         ecore_evas_object_cursor_set(cur->ee, cur->obj,
216                                      ELM_OBJECT_LAYER_CURSOR, cur->hot_x,
217                                      cur->hot_y);
218      }
219    else
220      {
221 #ifdef HAVE_ELEMENTARY_X
222         if (cur->win)
223           {
224              ecore_x_window_cursor_set(cur->win, cur->cursor);
225           }
226 #endif
227      }
228    evas_event_thaw(cur->evas);
229 }
230
231 static void
232 _elm_cursor_mouse_out(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
233 {
234    Evas_Object *sobj_parent;
235    Elm_Cursor *pcur = NULL;
236    Elm_Cursor *cur = data;
237
238    if (!cur->visible) return;
239    evas_event_freeze(cur->evas);
240    cur->visible = EINA_FALSE;
241
242    sobj_parent = evas_object_data_get(cur->eventarea, "elm-parent");
243    while (sobj_parent)
244      {
245         pcur = evas_object_data_get((sobj_parent), _cursor_key);
246         if ((pcur) && (pcur->visible)) break;
247         sobj_parent = evas_object_data_get(sobj_parent, "elm-parent");
248      }
249
250    if (pcur)
251      {
252         pcur->visible = EINA_FALSE;
253         evas_event_thaw(cur->evas);
254         _elm_cursor_mouse_in(pcur, NULL, NULL, NULL);
255         return;
256      }
257
258    if ((!cur->engine_only) || (!cur->use_engine))
259      {
260         ecore_evas_object_cursor_set(cur->ee, NULL, ELM_OBJECT_LAYER_CURSOR,
261                                      cur->hot_x, cur->hot_y);
262      }
263    else
264      {
265 #ifdef HAVE_ELEMENTARY_X
266         if (cur->win)
267           {
268              ecore_x_window_cursor_set(cur->win, ECORE_X_CURSOR_X);
269           }
270 #endif
271      }
272    evas_event_thaw(cur->evas);
273 }
274
275 static void
276 _elm_cursor_del(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
277 {
278    elm_object_cursor_unset(obj);
279 }
280
281 static int
282 _elm_cursor_strcmp(const void *data1, const void *data2)
283 {
284    const struct _Cursor_Id *c1 = data1;
285    const struct _Cursor_Id *c2 = data2;
286    return strcmp (c1->name, c2->name);
287 }
288
289 static void
290 _elm_cursor_cur_set(Elm_Cursor *cur)
291 {
292    if (cur->engine_only)
293      {
294         INF("Using only engine cursors");
295         cur->use_engine = EINA_TRUE;
296      }
297    else if (_elm_cursor_obj_add(cur->eventarea, cur))
298      {
299         _elm_cursor_set_hot_spots(cur);
300         cur->use_engine = EINA_FALSE;
301         elm_widget_cursor_add(cur->owner, cur);
302      }
303    else
304      {
305         INF("Cursor couldn't be found on theme: %s", cur->cursor_name);
306         cur->use_engine = EINA_TRUE;
307      }
308
309    if (cur->use_engine)
310      {
311 #ifdef HAVE_ELEMENTARY_X
312         struct _Cursor_Id cur_search, *cur_id;
313
314         cur_search.name = cur->cursor_name;
315         cur_id = bsearch(&(cur->cursor_name), _cursors, _cursors_count,
316                          sizeof(struct _Cursor_Id), _elm_cursor_strcmp);
317
318         cur->win = elm_win_xwindow_get(cur->eventarea);
319         if (cur->win)
320           {
321              if (!cur_id)
322                {
323                   INF("X cursor couldn't be found: %s. Using default.",
324                       cur->cursor_name);
325                   cur->cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_X);
326                }
327              else
328                 cur->cursor = ecore_x_cursor_shape_get(cur_id->id);
329           }
330 #endif
331      }
332 }
333
334 /**
335  * Set the cursor to be shown when mouse is over the object
336  *
337  * Set the cursor that will be displayed when mouse is over the
338  * object. The object can have only one cursor set to it, so if
339  * this function is called twice for an object, the previous set
340  * will be unset.
341  * If using X cursors, a definition of all the valid cursor names
342  * is listed on Elementary_Cursors.h. If an invalid name is set
343  * the default cursor will be used.
344  *
345  * This is an internal function that is used by objects with sub-items
346  * that want to provide different cursors for each of them. The @a
347  * owner object should be an elm_widget and will be used to track
348  * theme changes and to feed @a func and @a del_cb. The @a eventarea
349  * may be any object and is the one that should be used later on with
350  * elm_object_cursor apis, such as elm_object_cursor_unset().
351  *
352  * @param eventarea the object being attached a cursor.
353  * @param owner the elm_widget that owns this object, will be used to
354  *        track theme changes and to be used in @a func or @a del_cb.
355  * @param cursor the cursor name to be used.
356  *
357  * @internal
358  * @ingroup Cursors
359  */
360 void
361 elm_object_sub_cursor_set(Evas_Object *eventarea, Evas_Object *owner, const char *cursor)
362 {
363    Elm_Cursor *cur = NULL;
364
365    cur = evas_object_data_get(eventarea, _cursor_key);
366    if (cur)
367      elm_object_cursor_unset(eventarea);
368
369    if (!cursor) return;
370
371    cur = ELM_NEW(Elm_Cursor);
372    if (!cur) return;
373
374    cur->owner = owner;
375    cur->eventarea = eventarea;
376    cur->engine_only = _elm_config->cursor_engine_only;
377    cur->visible = EINA_FALSE;
378
379    cur->cursor_name = eina_stringshare_add(cursor);
380    if (!cur->cursor_name)
381      ERR("Could not store cursor name %s", cursor);
382
383    cur->evas = evas_object_evas_get(eventarea);
384    cur->ee = ecore_evas_ecore_evas_get(cur->evas);
385
386    _elm_cursor_cur_set(cur);
387
388    evas_object_data_set(eventarea, _cursor_key, cur);
389
390    evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_IN,
391                                   _elm_cursor_mouse_in, cur);
392    evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_OUT,
393                                   _elm_cursor_mouse_out, cur);
394    evas_object_event_callback_add(eventarea, EVAS_CALLBACK_DEL,
395                                   _elm_cursor_del, cur);
396 }
397
398 /**
399  * Set the cursor to be shown when mouse is over the object
400  *
401  * Set the cursor that will be displayed when mouse is over the
402  * object. The object can have only one cursor set to it, so if
403  * this function is called twice for an object, the previous set
404  * will be unset.
405  * If using X cursors, a definition of all the valid cursor names
406  * is listed on Elementary_Cursors.h. If an invalid name is set
407  * the default cursor will be used.
408  *
409  * @param obj the object being set a cursor.
410  * @param cursor the cursor name to be used.
411  *
412  * @ingroup Cursors
413  */
414 EAPI void
415 elm_object_cursor_set(Evas_Object *obj, const char *cursor)
416 {
417    EINA_SAFETY_ON_NULL_RETURN(obj);
418    elm_object_sub_cursor_set(obj, obj, cursor);
419 }
420
421 /**
422  * Get the cursor to be shown when mouse is over the object
423  *
424  * @param obj an object with cursor already set.
425  * @return the cursor name.
426  *
427  * @ingroup Cursors
428  */
429 EAPI const char *
430 elm_object_cursor_get(const Evas_Object *obj)
431 {
432    ELM_CURSOR_GET_OR_RETURN(cur, obj, NULL);
433    return cur->cursor_name;
434 }
435
436 /**
437  * Unset cursor for object
438  *
439  * Unset cursor for object, and set the cursor to default if the mouse
440  * was over this object.
441  *
442  * @param obj Target object
443  * @see elm_object_cursor_set()
444  *
445  * @ingroup Cursors
446  */
447 EAPI void
448 elm_object_cursor_unset(Evas_Object *obj)
449 {
450    ELM_CURSOR_GET_OR_RETURN(cur, obj);
451
452    eina_stringshare_del(cur->cursor_name);
453    eina_stringshare_del(cur->style);
454
455    if (cur->owner)
456      elm_widget_cursor_del(cur->owner, cur);
457
458    if (cur->obj)
459      evas_object_del(cur->obj);
460
461    if (cur->visible)
462      {
463         if (!cur->use_engine)
464           ecore_evas_object_cursor_set(cur->ee, NULL, ELM_OBJECT_LAYER_CURSOR,
465                                        cur->hot_x, cur->hot_y);
466 #ifdef HAVE_ELEMENTARY_X
467         else
468           ecore_x_window_cursor_set(cur->win, ECORE_X_CURSOR_X);
469 #endif
470      }
471
472    evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_IN,
473                                   _elm_cursor_mouse_in);
474    evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_OUT,
475                                   _elm_cursor_mouse_out);
476    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _elm_cursor_del);
477
478    evas_object_data_del(obj, _cursor_key);
479    free(cur);
480 }
481
482 /**
483  * Sets a different style for this object cursor.
484  *
485  * @note before you set a style you should define a cursor with
486  *       elm_object_cursor_set()
487  *
488  * @param obj an object with cursor already set.
489  * @param style the theme style to use (default, transparent, ...)
490  *
491  * @ingroup Cursors
492  */
493 EAPI void
494 elm_object_cursor_style_set(Evas_Object *obj, const char *style)
495 {
496    ELM_CURSOR_GET_OR_RETURN(cur, obj);
497
498    if (!eina_stringshare_replace(&cur->style, style))
499      ERR("Could not set current style=%s", style);
500
501    if (cur->use_engine) return;
502
503    if (!cur->obj)
504      {
505         if (!_elm_cursor_obj_add(obj, cur))
506           ERR("Could not create cursor object");
507         else
508           _elm_cursor_set_hot_spots(cur);
509      }
510    else
511      {
512         if (!_elm_theme_object_set(obj, cur->obj, "cursor", cur->cursor_name,
513                                    style))
514           ERR("Could not apply the theme to the cursor style=%s", style);
515         else
516           _elm_cursor_set_hot_spots(cur);
517      }
518 }
519
520 /**
521  * Get the style for this object cursor.
522  *
523  * @param obj an object with cursor already set.
524  * @return style the theme style in use, defaults to "default". If the
525  *         object does not have a cursor set, then NULL is returned.
526  *
527  * @ingroup Cursors
528  */
529 EAPI const char *
530 elm_object_cursor_style_get(const Evas_Object *obj)
531 {
532    ELM_CURSOR_GET_OR_RETURN(cur, obj, NULL);
533    return cur->style ? cur->style : "default";
534 }
535
536 /**
537  * Notify cursor should recalculate its theme.
538  * @internal
539  */
540 void
541 elm_cursor_theme(Elm_Cursor *cur)
542 {
543    if ((!cur) || (!cur->obj)) return;
544    if (!_elm_theme_object_set(cur->eventarea, cur->obj, "cursor",
545                               cur->cursor_name, cur->style))
546      ERR("Could not apply the theme to the cursor style=%s", cur->style);
547    else
548      _elm_cursor_set_hot_spots(cur);
549 }
550
551 /**
552  * Set if the cursor set should be searched on the theme or should use
553  * the provided by the engine, only.
554  *
555  * @note before you set if should look on theme you should define a cursor
556  * with elm_object_cursor_set(). By default it will only look for cursors
557  * provided by the engine.
558  *
559  * @param obj an object with cursor already set.
560  * @param engine_only boolean to define it cursors should be looked only
561  * between the provided by the engine or searched on widget's theme as well.
562  *
563  * @ingroup Cursors
564  */
565 EAPI void
566 elm_object_cursor_engine_only_set(Evas_Object *obj, Eina_Bool engine_only)
567 {
568    ELM_CURSOR_GET_OR_RETURN(cur, obj);
569    cur->engine_only = engine_only;
570    if (cur->obj)
571      {
572         evas_object_del(cur->obj);
573         cur->obj = NULL;
574      }
575    _elm_cursor_cur_set(cur);
576 }
577
578 /**
579  * Get the cursor engine only usage for this object cursor.
580  *
581  * @param obj an object with cursor already set.
582  * @return engine_only boolean to define it cursors should be looked only
583  * between the provided by the engine or searched on widget's theme as well. If
584  *         the object does not have a cursor set, then EINA_FALSE is returned.
585  *
586  * @ingroup Cursors
587  */
588 EAPI Eina_Bool
589 elm_object_cursor_engine_only_get(const Evas_Object *obj)
590 {
591    ELM_CURSOR_GET_OR_RETURN(cur, obj, EINA_FALSE);
592    return cur->engine_only;
593 }
594
595 /**
596  * Get the configured cursor engine only usage
597  *
598  * This gets the globally configured exclusive usage of engine cursors.
599  *
600  * @return 1 if only engine cursors should be used
601  * @ingroup Cursors
602  */
603 EAPI int
604 elm_cursor_engine_only_get(void)
605 {
606    return _elm_config->cursor_engine_only;
607 }
608
609 /**
610  * Set the configured cursor engine only usage
611  *
612  * This sets the globally configured exclusive usage of engine cursors.
613  * It won't affect cursors set before changing this value.
614  *
615  * @param engine_only If 1 only engine cursors will be enabled, if 0 will
616  * look for them on theme before.
617  * @return EINA_TRUE if value is valid and setted (0 or 1)
618  * @ingroup Cursors
619  */
620 EAPI Eina_Bool
621 elm_cursor_engine_only_set(int engine_only)
622 {
623    if ((engine_only < 0) || (engine_only > 1)) return EINA_FALSE;
624    _elm_config->cursor_engine_only = engine_only;
625    return EINA_TRUE;
626 }