5 * - Make fallback user controlable.
6 * - Define the allowed signals?
9 typedef struct _E_Pointer_Stack E_Pointer_Stack;
11 struct _E_Pointer_Stack
17 static Eina_List *_e_pointers = NULL;
18 static Eina_List *handlers = NULL;
20 static void _e_pointer_canvas_add(E_Pointer *p);
21 static void _e_pointer_canvas_del(E_Pointer *p);
22 static void _e_pointer_cb_move(void *data,
24 Evas_Object *obj __UNUSED__,
26 static void _e_pointer_free(E_Pointer *p);
27 static void _e_pointer_stack_free(E_Pointer_Stack *elem);
28 static void _e_pointer_type_set(E_Pointer *p,
30 static void _e_pointer_active_handle(E_Pointer *p);
32 static Eina_Bool _e_pointer_cb_mouse_down(void *data,
35 static Eina_Bool _e_pointer_cb_mouse_up(void *data,
38 static Eina_Bool _e_pointer_cb_mouse_move(void *data,
41 static Eina_Bool _e_pointer_cb_mouse_wheel(void *data,
44 static Eina_Bool _e_pointer_cb_idle_timer_pre(void *data);
45 static Eina_Bool _e_pointer_cb_idle_timer_wait(void *data);
46 static Eina_Bool _e_pointer_cb_idle_poller(void *data);
48 /* externally accessible functions */
53 eina_list_append(handlers,
54 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
55 _e_pointer_cb_mouse_down, NULL));
57 eina_list_append(handlers,
58 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
59 _e_pointer_cb_mouse_up, NULL));
61 eina_list_append(handlers,
62 ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
63 _e_pointer_cb_mouse_move, NULL));
65 eina_list_append(handlers,
66 ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
67 _e_pointer_cb_mouse_wheel, NULL));
72 e_pointer_shutdown(void)
74 E_FREE_LIST(handlers, ecore_event_handler_del);
79 e_pointer_window_new(Ecore_X_Window win,
84 p = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_free);
87 p->e_cursor = e_config->use_e_cursor;
90 if (e_config->use_e_cursor)
91 if (ecore_x_cursor_color_supported_get()) p->color = 1;
93 ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
94 if (filled) e_pointer_type_push(p, p, "default");
95 _e_pointers = eina_list_append(_e_pointers, p);
100 e_pointers_size_set(int size)
105 if (!e_config->show_cursor) return;
106 EINA_LIST_FOREACH(_e_pointers, l, p)
108 Evas_Engine_Info_Buffer *einfo;
113 evas_output_size_set(p->evas, p->w, p->h);
114 evas_output_viewport_set(p->evas, 0, 0, p->w, p->h);
116 p->pixels = realloc(p->pixels, p->w * p->h * sizeof(int));
118 einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas);
121 einfo->info.dest_buffer = p->pixels;
122 einfo->info.dest_buffer_row_bytes = p->w * sizeof(int);
123 evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo);
126 evas_object_move(p->pointer_object, 0, 0);
127 evas_object_resize(p->pointer_object, p->w, p->h);
133 ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
138 _e_pointer_type_set(p, type);
139 eina_stringshare_del(type);
146 e_pointer_hide(E_Pointer *p)
149 if (p->win) ecore_x_window_cursor_set(p->win, 0);
150 if (p->evas) _e_pointer_canvas_del(p);
154 e_pointer_type_push(E_Pointer *p,
158 E_Pointer_Stack *stack;
161 p->e_cursor = e_config->use_e_cursor;
163 _e_pointer_type_set(p, type);
167 stack = E_NEW(E_Pointer_Stack, 1);
170 stack->type = eina_stringshare_add(p->type);
172 p->stack = eina_list_prepend(p->stack, stack);
177 e_pointer_type_pop(E_Pointer *p,
181 Eina_List *l, *l_next;
182 E_Pointer_Stack *stack;
185 EINA_LIST_FOREACH_SAFE(p->stack, l, l_next, stack)
187 if ((stack->obj == obj) && ((!type) || (!strcmp(stack->type, type))))
189 _e_pointer_stack_free(stack);
190 p->stack = eina_list_remove_list(p->stack, l);
197 if (p->evas) _e_pointer_canvas_del(p);
198 ecore_x_window_cursor_set(p->win, 0);
199 if (p->type) eina_stringshare_del(p->type);
204 stack = eina_list_data_get(p->stack);
205 _e_pointer_type_set(p, stack->type);
207 if (p->type) eina_stringshare_del(p->type);
208 p->type = eina_stringshare_add(stack->type);
211 /* try the default cursor next time */
212 p->e_cursor = e_config->use_e_cursor;
216 e_pointer_idler_before(void)
221 if (!e_config->show_cursor) return;
222 EINA_LIST_FOREACH(_e_pointers, l, p)
226 if (!p->e_cursor) continue;
227 if (!p->evas) continue;
229 updates = evas_render_updates(p->evas);
230 if ((updates) || (p->hot.update))
234 cur = ecore_x_cursor_new(p->win, p->pixels, p->w, p->h,
236 ecore_x_window_cursor_set(p->win, cur);
237 ecore_x_cursor_free(cur);
238 evas_render_updates_free(updates);
245 * mode_{push,pop} functions are ONLY for use with compositor objects.
246 * these functions should NEVER be used for setting internal window pointers!!!!
249 e_pointer_mode_push(void *obj, E_Pointer_Mode mode)
253 case E_POINTER_RESIZE_TL:
254 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_tl");
257 case E_POINTER_RESIZE_T:
258 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_t");
261 case E_POINTER_RESIZE_TR:
262 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_tr");
265 case E_POINTER_RESIZE_R:
266 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_r");
269 case E_POINTER_RESIZE_BR:
270 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_br");
273 case E_POINTER_RESIZE_B:
274 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_b");
277 case E_POINTER_RESIZE_BL:
278 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_bl");
281 case E_POINTER_RESIZE_L:
282 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "resize_l");
286 e_pointer_type_push(e_comp_get(obj)->pointer, obj, "move");
294 e_pointer_mode_pop(void *obj, E_Pointer_Mode mode)
298 case E_POINTER_RESIZE_TL:
299 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_tl");
302 case E_POINTER_RESIZE_T:
303 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_t");
306 case E_POINTER_RESIZE_TR:
307 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_tr");
310 case E_POINTER_RESIZE_R:
311 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_r");
314 case E_POINTER_RESIZE_BR:
315 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_br");
318 case E_POINTER_RESIZE_B:
319 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_b");
322 case E_POINTER_RESIZE_BL:
323 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_bl");
326 case E_POINTER_RESIZE_L:
327 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "resize_l");
331 e_pointer_type_pop(e_comp_get(obj)->pointer, obj, "move");
338 /* local subsystem functions */
340 _e_pointer_canvas_add(E_Pointer *p)
342 Evas_Engine_Info_Buffer *einfo;
347 p->w = e_config->cursor_size;
348 p->h = e_config->cursor_size;
351 p->evas = evas_new();
354 e_object_del(E_OBJECT(p));
357 rmethod = evas_render_method_lookup("buffer");
358 evas_output_method_set(p->evas, rmethod);
359 evas_output_size_set(p->evas, p->w, p->h);
360 evas_output_viewport_set(p->evas, 0, 0, p->w, p->h);
362 p->pixels = malloc(p->w * p->h * sizeof(int));
365 _e_pointer_canvas_del(p);
368 einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas);
371 _e_pointer_canvas_del(p);
374 einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
375 einfo->info.dest_buffer = p->pixels;
376 einfo->info.dest_buffer_row_bytes = p->w * sizeof(int);
377 einfo->info.use_color_key = 0;
378 einfo->info.alpha_threshold = 0;
379 einfo->info.func.new_update_region = NULL;
380 einfo->info.func.free_update_region = NULL;
381 evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo);
383 /* set the pointer edje */
384 o = edje_object_add(p->evas);
385 p->pointer_object = o;
386 /* Create the hotspot object */
387 o = evas_object_rectangle_add(p->evas);
388 evas_object_color_set(o, 0, 0, 0, 0);
390 evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
391 _e_pointer_cb_move, p);
393 evas_object_move(p->pointer_object, 0, 0);
394 evas_object_resize(p->pointer_object, p->w, p->h);
395 evas_object_show(p->pointer_object);
399 _e_pointer_canvas_del(E_Pointer *p)
402 if (p->pointer_object) evas_object_del(p->pointer_object);
403 if (p->hot_object) evas_object_del(p->hot_object);
404 if (p->evas) evas_free(p->evas);
406 p->pointer_object = NULL;
407 p->hot_object = NULL;
413 _e_pointer_cb_move(void *data,
415 Evas_Object *obj __UNUSED__,
416 void *event_info __UNUSED__)
421 if (!e_config->show_cursor) return;
423 if (!(p = data)) return;
424 if (!p->e_cursor) return;
425 edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
427 if ((p->hot.x != x) || (p->hot.y != y))
436 _e_pointer_free(E_Pointer *p)
439 _e_pointers = eina_list_remove(_e_pointers, p);
441 _e_pointer_canvas_del(p);
443 E_FREE_LIST(p->stack, _e_pointer_stack_free);
445 if (p->type) eina_stringshare_del(p->type);
446 if (p->idle_timer) ecore_timer_del(p->idle_timer);
447 if (p->idle_poller) ecore_poller_del(p->idle_poller);
450 p->idle_timer = NULL;
451 p->idle_poller = NULL;
456 _e_pointer_stack_free(E_Pointer_Stack *elem)
458 if (elem->type) eina_stringshare_del(elem->type);
463 _e_pointer_type_set(E_Pointer *p,
468 /* Check if this pointer is already set */
469 if ((p->type) && (!strcmp(p->type, type))) return;
471 eina_stringshare_replace(&p->type, type);
473 /* Do not set type if in "hidden mode" */
474 if (!e_config->show_cursor)
476 ecore_x_window_cursor_set(p->win, 0);
485 if (!p->evas) _e_pointer_canvas_add(p);
487 snprintf(cursor, sizeof(cursor),
488 "e/pointer/enlightenment/%s/color", type);
490 snprintf(cursor, sizeof(cursor),
491 "e/pointer/enlightenment/%s/mono", type);
492 if (!e_theme_edje_object_set(p->pointer_object,
493 "base/theme/pointer", cursor))
495 edje_object_part_swallow(p->pointer_object, "e.swallow.hotspot",
497 edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
499 if ((p->hot.x != x) || (p->hot.y != y))
509 Ecore_X_Cursor cursor = 0;
511 if (p->evas) _e_pointer_canvas_del(p);
512 if (!strcmp(type, "move"))
513 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_FLEUR);
515 else if (!strcmp(type, "resize"))
516 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_SIZING);
518 else if (!strcmp(type, "resize_tl"))
519 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_LEFT_CORNER);
520 else if (!strcmp(type, "resize_t"))
521 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_SIDE);
522 else if (!strcmp(type, "resize_tr"))
523 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_RIGHT_CORNER);
524 else if (!strcmp(type, "resize_r"))
525 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_RIGHT_SIDE);
526 else if (!strcmp(type, "resize_br"))
527 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER);
528 else if (!strcmp(type, "resize_b"))
529 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_SIDE);
530 else if (!strcmp(type, "resize_bl"))
531 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_LEFT_CORNER);
532 else if (!strcmp(type, "resize_l"))
533 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_SIDE);
534 else if (!strcmp(type, "entry"))
535 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_XTERM);
536 else if (!strcmp(type, "default"))
537 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_PTR);
538 else if (!strcmp(type, "plus"))
539 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_PLUS);
540 else if (!strcmp(type, "hand"))
541 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_HAND1);
542 else if (!strcmp(type, "rotate"))
543 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_EXCHANGE);
546 printf("Unknown pointer type: %s\n", type);
547 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_ARROW);
549 if (!cursor) printf("X Cursor for %s is missing\n", type);
550 ecore_x_window_cursor_set(p->win, cursor);
551 if (cursor) ecore_x_cursor_free(cursor);
556 _e_pointer_active_handle(E_Pointer *p)
560 /* we got some mouse event - if there was an idle timer emit an active
561 * signal as we WERE idle, NOW we are active */
564 ecore_timer_del(p->idle_timer);
565 p->idle_timer = NULL;
569 ecore_poller_del(p->idle_poller);
570 p->idle_poller = NULL;
574 if (p->pointer_object)
575 edje_object_signal_emit(p->pointer_object, "e,state,mouse,active", "e");
578 if (e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) return;
579 /* and schedule a pre-idle check in 1 second if no more events happen */
580 if (!e_config->idle_cursor) return;
581 p->idle_timer = ecore_timer_loop_add(1.0, _e_pointer_cb_idle_timer_pre, p);
585 _e_pointer_cb_mouse_down(void *data __UNUSED__,
587 void *event __UNUSED__)
592 EINA_LIST_FOREACH(_e_pointers, l, p)
594 _e_pointer_active_handle(p);
595 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
597 if (p->pointer_object)
598 edje_object_signal_emit(p->pointer_object,
599 "e,action,mouse,down", "e");
602 return ECORE_CALLBACK_PASS_ON;
606 _e_pointer_cb_mouse_up(void *data __UNUSED__,
608 void *event __UNUSED__)
613 EINA_LIST_FOREACH(_e_pointers, l, p)
615 _e_pointer_active_handle(p);
616 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
618 if (p->pointer_object)
619 edje_object_signal_emit(p->pointer_object,
620 "e,action,mouse,up", "e");
623 return ECORE_CALLBACK_PASS_ON;
627 _e_pointer_cb_mouse_move(void *data __UNUSED__,
629 void *event __UNUSED__)
634 EINA_LIST_FOREACH(_e_pointers, l, p)
636 _e_pointer_active_handle(p);
637 if (e_powersave_mode_get() < E_POWERSAVE_MODE_HIGH)
639 if (p->pointer_object)
640 edje_object_signal_emit(p->pointer_object,
641 "e,action,mouse,move", "e");
644 return ECORE_CALLBACK_PASS_ON;
648 _e_pointer_cb_mouse_wheel(void *data __UNUSED__,
650 void *event __UNUSED__)
655 EINA_LIST_FOREACH(_e_pointers, l, p)
657 _e_pointer_active_handle(p);
658 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
660 if (p->pointer_object)
661 edje_object_signal_emit(p->pointer_object,
662 "e,action,mouse,wheel", "e");
665 return ECORE_CALLBACK_PASS_ON;
669 _e_pointer_cb_idle_timer_pre(void *data)
674 if (!(p = data)) return ECORE_CALLBACK_RENEW;
675 ecore_x_pointer_xy_get(p->win, &x, &y);
678 p->idle_timer = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_timer_wait, p);
679 return ECORE_CALLBACK_CANCEL;
683 _e_pointer_cb_idle_timer_wait(void *data)
687 if (!(p = data)) return ECORE_CALLBACK_RENEW;
688 if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
689 (!e_config->idle_cursor))
691 if (p->idle_poller) ecore_poller_del(p->idle_poller);
692 p->idle_poller = NULL;
693 p->idle_timer = NULL;
694 return ECORE_CALLBACK_CANCEL;
697 p->idle_poller = ecore_poller_add(ECORE_POLLER_CORE, 64,
698 _e_pointer_cb_idle_poller, p);
699 p->idle_timer = NULL;
700 return ECORE_CALLBACK_CANCEL;
704 _e_pointer_cb_idle_poller(void *data)
709 if (!(p = data)) return ECORE_CALLBACK_RENEW;
710 if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
711 (!e_config->idle_cursor))
713 p->idle_poller = NULL;
714 return ECORE_CALLBACK_CANCEL;
716 /* check if pointer actually moved since the 1 second post-mouse move idle
717 * pre-timer that fetches the position */
718 ecore_x_pointer_xy_get(p->win, &x, &y);
719 if ((x != p->x) || (y != p->y))
721 /* it moved - so we are not idle yet - record position and wait
727 if (p->pointer_object)
728 edje_object_signal_emit(p->pointer_object,
729 "e,state,mouse,active", "e");
732 /* use poller to check from now on */
733 return ECORE_CALLBACK_RENEW;
735 /* we are idle - report it if not idle before */
738 if (p->pointer_object)
739 edje_object_signal_emit(p->pointer_object, "e,state,mouse,idle", "e");
742 return ECORE_CALLBACK_RENEW;