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