e_comp_wl: add config for cursor_timer hiding the cursor after some interval
[platform/upstream/enlightenment.git] / src / bin / e_pointer.c
1 #include "e.h"
2
3 typedef struct _E_Pointer_Stack E_Pointer_Stack;
4 struct _E_Pointer_Stack
5 {
6    void *obj;
7    const char *type;
8 };
9
10 /* local variables */
11 static Eina_List *_hdlrs = NULL;
12 static Eina_List *_ptrs = NULL;
13 static Eina_Bool _initted = EINA_FALSE;
14
15 static inline void 
16 _e_pointer_hot_update(E_Pointer *ptr, int x, int y)
17 {
18    if ((ptr->hot.x != x) || (ptr->hot.y != y))
19      {
20         ptr->hot.x = x;
21         ptr->hot.y = y;
22         ptr->hot.update = EINA_TRUE;
23      }
24 }
25
26 static void 
27 _e_pointer_active(E_Pointer *ptr)
28 {
29    if (!ptr->idle) return;
30    if (ptr->o_ptr)
31      edje_object_signal_emit(ptr->o_ptr, "e,state,mouse,active", "e");
32    ptr->idle = EINA_FALSE;
33 }
34
35 static void 
36 _e_pointer_idle(E_Pointer *ptr)
37 {
38    if (ptr->idle) return;
39    if (ptr->o_ptr)
40      edje_object_signal_emit(ptr->o_ptr, "e,state,mouse,idle", "e");
41    ptr->idle = EINA_TRUE;
42 }
43
44 static Eina_Bool 
45 _e_pointer_cb_idle_poller(void *data)
46 {
47    E_Pointer *ptr;
48    int x = 0, y = 0;
49
50    if (!(ptr = data)) return ECORE_CALLBACK_RENEW;
51
52    if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) || 
53        (!e_config->idle_cursor))
54      {
55         ptr->idle_poll = NULL;
56         return ECORE_CALLBACK_CANCEL;
57      }
58
59 #ifndef HAVE_WAYLAND_ONLY
60    if (!ptr->canvas)
61      ecore_x_pointer_xy_get(ptr->win, &x, &y);
62    else
63 #endif
64      ecore_evas_pointer_xy_get(ptr->ee, &x, &y);
65
66    if ((ptr->x != x) || (ptr->y != y))
67      {
68         ptr->x = x;
69         ptr->y = y;
70         if (ptr->idle) _e_pointer_active(ptr);
71         return ECORE_CALLBACK_RENEW;
72      }
73
74    if (!ptr->idle) _e_pointer_idle(ptr);
75
76    return ECORE_CALLBACK_RENEW;
77 }
78
79 static Eina_Bool 
80 _e_pointer_cb_idle_wait(void *data)
81 {
82    E_Pointer *ptr;
83
84    if (!(ptr = data)) return ECORE_CALLBACK_RENEW;
85    ptr->idle_tmr = NULL;
86    if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) || 
87        (!e_config->idle_cursor))
88      {
89         E_FREE_FUNC(ptr->idle_poll, ecore_poller_del);
90         return ECORE_CALLBACK_CANCEL;
91      }
92
93    if (!ptr->idle_poll)
94      ptr->idle_poll = ecore_poller_add(ECORE_POLLER_CORE, 64, 
95                                        _e_pointer_cb_idle_poller, ptr);
96
97    return ECORE_CALLBACK_CANCEL;
98 }
99
100 static Eina_Bool 
101 _e_pointer_cb_idle_pre(void *data)
102 {
103    E_Pointer *ptr;
104
105    if (!(ptr = data)) return ECORE_CALLBACK_RENEW;
106
107 #ifndef HAVE_WAYLAND_ONLY
108    if (!ptr->canvas)
109      ecore_x_pointer_xy_get(ptr->win, &ptr->x, &ptr->y);
110    else
111 #endif
112      ecore_evas_pointer_xy_get(ptr->ee, &ptr->x, &ptr->y);
113
114    ptr->idle_tmr = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_wait, ptr);
115
116    return ECORE_CALLBACK_CANCEL;
117 }
118
119 static void 
120 _e_pointer_active_handle(E_Pointer *ptr)
121 {
122    _e_pointer_active(ptr);
123    if (ptr->idle_tmr)
124      ecore_timer_reset(ptr->idle_tmr);
125    else
126      {
127         E_FREE_FUNC(ptr->idle_poll, ecore_poller_del);
128         if (e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) return;
129         if (!e_config->idle_cursor) return;
130         ptr->idle_tmr = ecore_timer_loop_add(1.0, _e_pointer_cb_idle_pre, ptr);
131      }
132 }
133
134 static Eina_Bool 
135 _e_pointer_cb_mouse_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
136 {
137    Eina_List *l;
138    E_Pointer *ptr;
139
140    EINA_LIST_FOREACH(_ptrs, l, ptr)
141      {
142         _e_pointer_active_handle(ptr);
143         if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
144           {
145              if (ptr->o_ptr)
146                edje_object_signal_emit(ptr->o_ptr, "e,action,mouse,down", "e");
147           }
148      }
149
150    return ECORE_CALLBACK_PASS_ON;
151 }
152
153 static Eina_Bool 
154 _e_pointer_cb_mouse_up(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
155 {
156    Eina_List *l;
157    E_Pointer *ptr;
158
159    EINA_LIST_FOREACH(_ptrs, l, ptr)
160      {
161         _e_pointer_active_handle(ptr);
162         if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
163           {
164              if (ptr->o_ptr)
165                edje_object_signal_emit(ptr->o_ptr, "e,action,mouse,up", "e");
166           }
167      }
168
169    return ECORE_CALLBACK_PASS_ON;
170 }
171
172 static Eina_Bool 
173 _e_pointer_cb_mouse_move(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
174 {
175    Eina_List *l;
176    E_Pointer *ptr;
177
178    EINA_LIST_FOREACH(_ptrs, l, ptr)
179      {
180         _e_pointer_active_handle(ptr);
181         if (e_powersave_mode_get() < E_POWERSAVE_MODE_HIGH)
182           {
183              if (ptr->o_ptr)
184                edje_object_signal_emit(ptr->o_ptr, "e,action,mouse,move", "e");
185           }
186      }
187
188    return ECORE_CALLBACK_PASS_ON;
189 }
190
191 static Eina_Bool 
192 _e_pointer_cb_mouse_wheel(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
193 {
194    Eina_List *l;
195    E_Pointer *ptr;
196
197    EINA_LIST_FOREACH(_ptrs, l, ptr)
198      {
199         _e_pointer_active_handle(ptr);
200         if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
201           {
202              if (ptr->o_ptr)
203                edje_object_signal_emit(ptr->o_ptr, "e,action,mouse,wheel", "e");
204           }
205      }
206
207    return ECORE_CALLBACK_PASS_ON;
208 }
209
210 static void 
211 _e_pointer_cb_hot_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
212 {
213    E_Pointer *ptr;
214    int x = 0, y = 0;
215
216    if (!(ptr = data)) return;
217    if (!ptr->e_cursor) return;
218    if (!evas_object_visible_get(ptr->o_ptr)) return;
219    edje_object_part_geometry_get(ptr->o_ptr, "e.swallow.hotspot", 
220                                  &x, &y, NULL, NULL);
221    _e_pointer_hot_update(ptr, x, y);
222 }
223
224 static void 
225 _e_pointer_cb_hot_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
226 {
227    E_Pointer *ptr;
228    int x = 0, y = 0;
229
230    if (!(ptr = data)) return;
231    edje_object_part_geometry_get(ptr->o_ptr, "e.swallow.hotspot", 
232                                  &x, &y, NULL, NULL);
233    _e_pointer_hot_update(ptr, x, y);
234 }
235
236 static void 
237 _e_pointer_canvas_del(E_Pointer *ptr)
238 {
239    E_FREE_FUNC(ptr->o_hot, evas_object_del);
240    E_FREE_FUNC(ptr->o_ptr, evas_object_del);
241    if (ptr->evas) evas_free(ptr->evas);
242    ptr->evas = NULL;
243    E_FREE(ptr->pixels);
244 }
245
246 static void 
247 _e_pointer_canvas_add(E_Pointer *ptr)
248 {
249    Evas_Engine_Info_Buffer *einfo;
250    int method = 0;
251
252    /* try to create new canvas */
253    if (!(ptr->evas = evas_new())) goto err;
254
255    method = evas_render_method_lookup("buffer");
256    evas_output_method_set(ptr->evas, method);
257    evas_output_size_set(ptr->evas, ptr->w, ptr->h);
258    evas_output_viewport_set(ptr->evas, 0, 0, ptr->w, ptr->h);
259
260    /* try to allocate space for pixels */
261    if (!(ptr->pixels = malloc(ptr->w * ptr->h * sizeof(int))))
262      goto err;
263
264    /* try to get the buffer engine info */
265    einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ptr->evas);
266    if (!einfo) goto err;
267
268    /* fill in buffer engine info */
269    einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
270    einfo->info.dest_buffer = ptr->pixels;
271    einfo->info.dest_buffer_row_bytes = (ptr->w * sizeof(int));
272    einfo->info.use_color_key = 0;
273    einfo->info.alpha_threshold = 0;
274    einfo->info.func.new_update_region = NULL;
275    einfo->info.func.free_update_region = NULL;
276
277    /* set buffer engine info */
278    evas_engine_info_set(ptr->evas, (Evas_Engine_Info *)einfo);
279
280    /* create pointer object */
281    ptr->o_ptr = edje_object_add(ptr->evas);
282
283    /* create hotspot object */
284    ptr->o_hot = evas_object_rectangle_add(ptr->evas);
285    evas_object_color_set(ptr->o_hot, 0, 0, 0, 0);
286
287    evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_MOVE, 
288                                   _e_pointer_cb_hot_move, ptr);
289    evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_SHOW, 
290                                   _e_pointer_cb_hot_show, ptr);
291
292    evas_object_move(ptr->o_ptr, 0, 0);
293    evas_object_resize(ptr->o_ptr, ptr->w, ptr->h);
294
295    return;
296
297 err:
298    _e_pointer_canvas_del(ptr);
299 }
300
301 static void 
302 _e_pointer_canvas_resize(E_Pointer *ptr, int w, int h)
303 {
304    Evas_Engine_Info_Buffer *einfo;
305
306    if ((ptr->w == w) && (ptr->h == h)) return;
307    ptr->w = w;
308    ptr->h = h;
309    evas_output_size_set(ptr->evas, w, h);
310    evas_output_viewport_set(ptr->evas, 0, 0, w, h);
311
312    ptr->pixels = realloc(ptr->pixels, (ptr->w * ptr->h * sizeof(int)));
313
314    einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ptr->evas);
315    EINA_SAFETY_ON_NULL_RETURN(einfo);
316
317    einfo->info.dest_buffer = ptr->pixels;
318    einfo->info.dest_buffer_row_bytes = (ptr->w * sizeof(int));
319    evas_engine_info_set(ptr->evas, (Evas_Engine_Info *)einfo);
320
321    evas_object_move(ptr->o_ptr, 0, 0);
322    evas_object_resize(ptr->o_ptr, ptr->w, ptr->h);
323 }
324
325 static void 
326 _e_pointer_stack_free(E_Pointer_Stack *stack)
327 {
328    if (stack->type) eina_stringshare_del(stack->type);
329    free(stack);
330 }
331
332 static void 
333 _e_pointer_cb_free(E_Pointer *ptr)
334 {
335    _ptrs = eina_list_remove(_ptrs, ptr);
336
337    E_FREE_LIST(ptr->stack, _e_pointer_stack_free);
338
339    eina_stringshare_del(ptr->type);
340
341    E_FREE_FUNC(ptr->idle_tmr, ecore_timer_del);
342    E_FREE_FUNC(ptr->idle_poll, ecore_poller_del);
343
344    if (!ptr->canvas) _e_pointer_canvas_del(ptr);
345
346    free(ptr);
347 }
348
349 static void 
350 _e_pointer_type_set(E_Pointer *ptr, const char *type)
351 {
352    /* check if pointer type is already set */
353    if (!e_util_strcmp(ptr->type, type)) return;
354
355    eina_stringshare_replace(&ptr->type, type);
356
357    /* don't show cursor if in hidden mode */
358    if (!e_config->show_cursor)
359      {
360         e_pointer_hide(ptr);
361         return;
362      }
363
364    if (ptr->e_cursor)
365      {
366         char cursor[1024];
367         int x = 0, y = 0;
368
369         /* create a pointer canvas if we need to */
370         if ((!ptr->evas) && (!ptr->canvas)) _e_pointer_canvas_add(ptr);
371
372         if (ptr->color)
373           snprintf(cursor, sizeof(cursor), 
374                    "e/pointer/enlightenment/%s/color", type);
375         else
376           snprintf(cursor, sizeof(cursor), 
377                    "e/pointer/enlightenment/%s/mono", type);
378
379         /* try to set the edje object theme */
380         if (!e_theme_edje_object_set(ptr->o_ptr, "base/theme/pointer", cursor))
381           goto fallback;
382
383         edje_object_part_swallow(ptr->o_ptr, "e.swallow.hotspot", ptr->o_hot);
384
385         edje_object_part_geometry_get(ptr->o_ptr, "e.swallow.hotspot", 
386                                       &x, &y, NULL, NULL);
387         _e_pointer_hot_update(ptr, x, y);
388
389         if (ptr->canvas)
390           e_pointer_object_set(ptr, NULL, 0, 0);
391         else
392           evas_object_show(ptr->o_ptr);
393
394         return;
395      }
396
397 fallback:
398    if ((ptr->evas) && (!ptr->canvas)) _e_pointer_canvas_del(ptr);
399 #ifndef HAVE_WAYLAND_ONLY
400    Ecore_X_Cursor cursor = 0;
401
402    if (!strcmp(type, "move"))
403      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_FLEUR);
404 # if 0
405    else if (!strcmp(type, "resize"))
406      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_SIZING);
407 # endif
408    else if (!strcmp(type, "resize_tl"))
409      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_LEFT_CORNER);
410    else if (!strcmp(type, "resize_t"))
411      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_SIDE);
412    else if (!strcmp(type, "resize_tr"))
413      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_RIGHT_CORNER);
414    else if (!strcmp(type, "resize_r"))
415      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_RIGHT_SIDE);
416    else if (!strcmp(type, "resize_br"))
417      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER);
418    else if (!strcmp(type, "resize_b"))
419      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_SIDE);
420    else if (!strcmp(type, "resize_bl"))
421      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_LEFT_CORNER);
422    else if (!strcmp(type, "resize_l"))
423      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_SIDE);
424    else if (!strcmp(type, "entry"))
425      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_XTERM);
426    else if (!strcmp(type, "default"))
427      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_PTR);
428    else if (!strcmp(type, "plus"))
429      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_PLUS);
430    else if (!strcmp(type, "hand"))
431      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_HAND1);
432    else if (!strcmp(type, "rotate"))
433      cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_EXCHANGE);
434    else
435      {
436         WRN("Unknown pointer type: %s\n", type);
437         cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_ARROW);
438      }
439    if (!cursor) WRN("X Cursor for %s is missing\n", type);
440    ecore_x_window_cursor_set(ptr->win, cursor);
441    if (cursor) ecore_x_cursor_free(cursor);
442 #endif
443    return;
444 }
445
446 EINTERN int 
447 e_pointer_init(void)
448 {
449    E_LIST_HANDLER_APPEND(_hdlrs, ECORE_EVENT_MOUSE_BUTTON_DOWN, 
450                          _e_pointer_cb_mouse_down, NULL);
451    E_LIST_HANDLER_APPEND(_hdlrs, ECORE_EVENT_MOUSE_BUTTON_UP, 
452                          _e_pointer_cb_mouse_up, NULL);
453    E_LIST_HANDLER_APPEND(_hdlrs, ECORE_EVENT_MOUSE_MOVE, 
454                          _e_pointer_cb_mouse_move, NULL);
455    E_LIST_HANDLER_APPEND(_hdlrs, ECORE_EVENT_MOUSE_WHEEL, 
456                          _e_pointer_cb_mouse_wheel, NULL);
457    _initted = EINA_TRUE;
458    return 1;
459 }
460
461 EINTERN int 
462 e_pointer_shutdown(void)
463 {
464    _initted = EINA_FALSE;
465    E_FREE_LIST(_hdlrs, ecore_event_handler_del);
466    return 1;
467 }
468
469 EAPI E_Pointer *
470 e_pointer_window_new(Ecore_Window win, Eina_Bool filled)
471 {
472    E_Pointer *ptr = NULL;
473
474    EINA_SAFETY_ON_FALSE_RETURN_VAL(win, NULL);
475    if (!_initted) return NULL;
476
477    /* allocate space for new pointer */
478    if (!(ptr = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_cb_free)))
479      return NULL;
480
481    /* set default pointer properties */
482    ptr->w = ptr->h = e_config->cursor_size;
483    ptr->e_cursor = e_config->use_e_cursor;
484    ptr->win = win;
485    ptr->color = EINA_FALSE;
486    if (e_comp->pointer)
487      ptr->color = e_comp->pointer->color;
488
489    /* set pointer default type */
490    if (filled) e_pointer_type_push(ptr, ptr, "default");
491
492    /* append this pointer to the list */
493    _ptrs = eina_list_append(_ptrs, ptr);
494
495    return ptr;
496 }
497
498 EAPI E_Pointer *
499 e_pointer_canvas_new(Ecore_Evas *ee, Eina_Bool filled)
500 {
501    E_Pointer *ptr = NULL;
502
503    EINA_SAFETY_ON_FALSE_RETURN_VAL(ee, NULL);
504    if (!_initted) return NULL;
505
506    /* allocate space for new pointer */
507    if (!(ptr = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_cb_free)))
508      return NULL;
509
510    /* set default pointer properties */
511    ptr->color = EINA_TRUE;
512    ptr->canvas = EINA_TRUE;
513    ptr->w = ptr->h = e_config->cursor_size;
514    ptr->e_cursor = e_config->use_e_cursor;
515
516    ptr->ee = ee;
517    ptr->evas = ecore_evas_get(ee);
518
519    ptr->o_ptr = edje_object_add(ptr->evas);
520
521    ptr->o_hot = evas_object_rectangle_add(ptr->evas);
522    evas_object_color_set(ptr->o_hot, 0, 0, 0, 0);
523    evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_MOVE, 
524                                   _e_pointer_cb_hot_move, ptr);
525    evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_SHOW, 
526                                   _e_pointer_cb_hot_show, ptr);
527
528    evas_object_move(ptr->o_ptr, 0, 0);
529    evas_object_resize(ptr->o_ptr, ptr->w, ptr->h);
530
531    /* set pointer default type */
532    if (filled) e_pointer_type_push(ptr, ptr, "default");
533
534      /* append this pointer to the list */
535    _ptrs = eina_list_append(_ptrs, ptr);
536
537    _e_pointer_active_handle(ptr);
538
539    return ptr;
540 }
541
542 EAPI void 
543 e_pointers_size_set(int size)
544 {
545    Eina_List *l;
546    E_Pointer *ptr;
547
548    if (!e_config->show_cursor) return;
549
550    EINA_LIST_FOREACH(_ptrs, l, ptr)
551      {
552         if ((ptr->w == size) && (ptr->h == size)) continue;
553         if ((ptr->evas) && (!ptr->canvas))
554           _e_pointer_canvas_resize(ptr, size, size);
555         else if (ptr->canvas)
556           {
557              ptr->w = size;
558              ptr->h = size;
559              evas_object_resize(ptr->o_ptr, size, size);
560           }
561
562 #ifndef HAVE_WAYLAND_ONLY
563         ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
564 #endif
565      }
566 }
567
568 EAPI void 
569 e_pointer_hide(E_Pointer *ptr)
570 {
571    EINA_SAFETY_ON_NULL_RETURN(ptr);
572
573    if ((ptr->evas) && (!ptr->canvas)) 
574      _e_pointer_canvas_del(ptr);
575    else if (ptr->canvas)
576      evas_object_hide(ptr->o_ptr);
577 #ifndef HAVE_WAYLAND_ONLY
578    ecore_x_window_cursor_set(ptr->win, 0);
579 #endif
580 }
581
582 EAPI void 
583 e_pointer_type_push(E_Pointer *ptr, void *obj, const char *type)
584 {
585    E_Pointer_Stack *stack;
586
587    EINA_SAFETY_ON_NULL_RETURN(ptr);
588
589    _e_pointer_type_set(ptr, type);
590
591    if (!(stack = E_NEW(E_Pointer_Stack, 1))) return;
592    stack->type = eina_stringshare_ref(ptr->type);
593    stack->obj = obj;
594    ptr->stack = eina_list_prepend(ptr->stack, stack);
595 }
596
597 EAPI void 
598 e_pointer_type_pop(E_Pointer *ptr, void *obj, const char *type)
599 {
600    Eina_List *l, *ll;
601    E_Pointer_Stack *stack;
602
603    EINA_SAFETY_ON_NULL_RETURN(ptr);
604
605    EINA_LIST_FOREACH_SAFE(ptr->stack, l, ll, stack)
606      {
607         if ((stack->obj == obj) && 
608             ((!type) || (!e_util_strcmp(stack->type, type))))
609           {
610              _e_pointer_stack_free(stack);
611              ptr->stack = eina_list_remove_list(ptr->stack, l);
612              if (type) break;
613           }
614      }
615
616    if (!ptr->stack)
617      {
618         e_pointer_hide(ptr);
619         eina_stringshare_replace(&ptr->type, NULL);
620         return;
621      }
622
623    if (!(stack = eina_list_data_get(ptr->stack))) return;
624
625    _e_pointer_type_set(ptr, stack->type);
626
627    eina_stringshare_refplace(&ptr->type, stack->type);
628 }
629
630 EAPI void 
631 e_pointer_mode_push(void *obj, E_Pointer_Mode mode)
632 {
633    E_Client *ec;
634    Evas_Object *o;
635
636    EINA_SAFETY_ON_NULL_RETURN(e_comp->pointer);
637
638    ecore_evas_cursor_get(e_comp->pointer->ee, &o, NULL, NULL, NULL);
639    if ((o != e_comp->pointer->o_ptr) && (ec = e_comp_object_client_get(o)))
640      return;
641
642    switch (mode)
643      {
644       case E_POINTER_RESIZE_TL:
645         e_pointer_type_push(e_comp->pointer, obj, "resize_tl");
646         break;
647
648       case E_POINTER_RESIZE_T:
649         e_pointer_type_push(e_comp->pointer, obj, "resize_t");
650         break;
651
652       case E_POINTER_RESIZE_TR:
653         e_pointer_type_push(e_comp->pointer, obj, "resize_tr");
654         break;
655
656       case E_POINTER_RESIZE_R:
657         e_pointer_type_push(e_comp->pointer, obj, "resize_r");
658         break;
659
660       case E_POINTER_RESIZE_BR:
661         e_pointer_type_push(e_comp->pointer, obj, "resize_br");
662         break;
663
664       case E_POINTER_RESIZE_B:
665         e_pointer_type_push(e_comp->pointer, obj, "resize_b");
666         break;
667
668       case E_POINTER_RESIZE_BL:
669         e_pointer_type_push(e_comp->pointer, obj, "resize_bl");
670         break;
671
672       case E_POINTER_RESIZE_L:
673         e_pointer_type_push(e_comp->pointer, obj, "resize_l");
674         break;
675
676       case E_POINTER_MOVE:
677         e_pointer_type_push(e_comp->pointer, obj, "move");
678         break;
679
680       default: break;
681      }
682 }
683
684 EAPI void 
685 e_pointer_mode_pop(void *obj, E_Pointer_Mode mode)
686 {
687    switch (mode)
688      {
689       case E_POINTER_RESIZE_TL:
690         e_pointer_type_pop(e_comp->pointer, obj, "resize_tl");
691         break;
692
693       case E_POINTER_RESIZE_T:
694         e_pointer_type_pop(e_comp->pointer, obj, "resize_t");
695         break;
696
697       case E_POINTER_RESIZE_TR:
698         e_pointer_type_pop(e_comp->pointer, obj, "resize_tr");
699         break;
700
701       case E_POINTER_RESIZE_R:
702         e_pointer_type_pop(e_comp->pointer, obj, "resize_r");
703         break;
704
705       case E_POINTER_RESIZE_BR:
706         e_pointer_type_pop(e_comp->pointer, obj, "resize_br");
707         break;
708
709       case E_POINTER_RESIZE_B:
710         e_pointer_type_pop(e_comp->pointer, obj, "resize_b");
711         break;
712
713       case E_POINTER_RESIZE_BL:
714         e_pointer_type_pop(e_comp->pointer, obj, "resize_bl");
715         break;
716
717       case E_POINTER_RESIZE_L:
718         e_pointer_type_pop(e_comp->pointer, obj, "resize_l");
719         break;
720
721       case E_POINTER_MOVE:
722         e_pointer_type_pop(e_comp->pointer, obj, "move");
723         break;
724
725       default: break;
726      }
727 }
728
729 EAPI void 
730 e_pointer_idler_before(void)
731 {
732    Eina_List *l;
733    E_Pointer *ptr;
734
735    if (!e_config->show_cursor) return;
736
737    EINA_LIST_FOREACH(_ptrs, l, ptr)
738      {
739         if ((!ptr->e_cursor) || (!ptr->evas)) continue;
740
741         if (ptr->hot.update)
742           _e_pointer_type_set(ptr, ptr->type);
743  
744         if (!ptr->canvas)
745           {
746              Eina_List *updates;
747
748              if ((updates = evas_render_updates(ptr->evas)))
749                {
750 #ifndef HAVE_WAYLAND_ONLY
751                   Ecore_X_Cursor cur;
752
753                   cur = ecore_x_cursor_new(ptr->win, ptr->pixels, ptr->w, 
754                                            ptr->h, ptr->hot.x, ptr->hot.y);
755                   ecore_x_window_cursor_set(ptr->win, cur);
756                   ecore_x_cursor_free(cur);
757 #endif
758                   evas_render_updates_free(updates);
759                }
760           }
761
762         ptr->hot.update = EINA_FALSE;
763      }
764 }
765
766 EAPI void
767 e_pointer_object_set(E_Pointer *ptr, Evas_Object *obj, int x, int y)
768 {
769    Evas_Object *o;
770    E_Client *ec;
771
772    EINA_SAFETY_ON_NULL_RETURN(ptr);
773
774    /* don't show cursor if in hidden mode */
775    if (!e_config->show_cursor)
776      {
777         if (obj) evas_object_hide(obj);
778         return;
779      }
780
781    ecore_evas_cursor_get(ptr->ee, &o, NULL, NULL, NULL);
782    if (o)
783      {
784         if (o == obj)
785           {
786              ecore_evas_object_cursor_set(ptr->ee, obj, EVAS_LAYER_MAX, x, y);
787              return;
788           }
789         ec = e_comp_object_client_get(o);
790         if (ec)
791           ec->hidden = 1;
792      }
793    ecore_evas_cursor_unset(ptr->ee);
794
795    if (obj)
796      {
797         ec = e_comp_object_client_get(obj);
798         if (ec)
799           ec->hidden = 1;
800         ecore_evas_object_cursor_set(ptr->ee, obj, EVAS_LAYER_MAX, x, y);
801      }
802    else if (ptr->o_ptr)
803      {
804         ecore_evas_object_cursor_set(ptr->ee, ptr->o_ptr, EVAS_LAYER_MAX, ptr->hot.x, ptr->hot.y);
805      }
806 }