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