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, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
23 static void _e_pointer_free(E_Pointer *p);
24 static void _e_pointer_stack_free(E_Pointer_Stack *elem);
25 static void _e_pointer_type_set(E_Pointer *p, const char *type);
26 static void _e_pointer_active_handle(E_Pointer *p);
28 static Eina_Bool _e_pointer_cb_mouse_down(void *data, int type, void *event);
29 static Eina_Bool _e_pointer_cb_mouse_up(void *data, int type, void *event);
30 static Eina_Bool _e_pointer_cb_mouse_move(void *data, int type, void *event);
31 static Eina_Bool _e_pointer_cb_mouse_wheel(void *data, int type, void *event);
32 static Eina_Bool _e_pointer_cb_idle_timer_pre(void *data);
33 static Eina_Bool _e_pointer_cb_idle_timer_wait(void *data);
34 static Eina_Bool _e_pointer_cb_idle_poller(void *data);
36 /* externally accessible functions */
41 eina_list_append(handlers,
42 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
43 _e_pointer_cb_mouse_down, NULL));
45 eina_list_append(handlers,
46 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
47 _e_pointer_cb_mouse_up, NULL));
49 eina_list_append(handlers,
50 ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
51 _e_pointer_cb_mouse_move, NULL));
53 eina_list_append(handlers,
54 ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
55 _e_pointer_cb_mouse_wheel, NULL));
60 e_pointer_shutdown(void)
62 E_FREE_LIST(handlers, ecore_event_handler_del);
67 e_pointer_window_new(Ecore_X_Window win, int filled)
71 p = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_free);
74 p->e_cursor = e_config->use_e_cursor;
77 if (e_config->use_e_cursor)
78 if (ecore_x_cursor_color_supported_get()) p->color = 1;
80 ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
81 if (filled) e_pointer_type_push(p, p, "default");
82 _e_pointers = eina_list_append(_e_pointers, p);
87 e_pointers_size_set(int size)
92 if (!e_config->show_cursor) return;
93 EINA_LIST_FOREACH(_e_pointers, l, p)
95 Evas_Engine_Info_Buffer *einfo;
100 evas_output_size_set(p->evas, p->w, p->h);
101 evas_output_viewport_set(p->evas, 0, 0, p->w, p->h);
103 p->pixels = realloc(p->pixels, p->w * p->h * sizeof(int));
105 einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas);
108 einfo->info.dest_buffer = p->pixels;
109 einfo->info.dest_buffer_row_bytes = p->w * sizeof(int);
110 evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo);
113 evas_object_move(p->pointer_object, 0, 0);
114 evas_object_resize(p->pointer_object, p->w, p->h);
120 ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
125 _e_pointer_type_set(p, type);
126 eina_stringshare_del(type);
133 e_pointer_hide(E_Pointer *p)
135 if (p->win) ecore_x_window_cursor_set(p->win, 0);
136 if (p->evas) _e_pointer_canvas_del(p);
140 e_pointer_type_push(E_Pointer *p, void *obj, const char *type)
142 E_Pointer_Stack *stack;
144 p->e_cursor = e_config->use_e_cursor;
146 _e_pointer_type_set(p, type);
150 stack = E_NEW(E_Pointer_Stack, 1);
153 stack->type = eina_stringshare_add(p->type);
155 p->stack = eina_list_prepend(p->stack, stack);
160 e_pointer_type_pop(E_Pointer *p, void *obj, const char *type)
163 E_Pointer_Stack *stack;
165 EINA_LIST_FOREACH(p->stack, l, stack)
167 if ((stack->obj == obj) && ((!type) || (!strcmp(stack->type, type))))
169 _e_pointer_stack_free(stack);
170 p->stack = eina_list_remove_list(p->stack, l);
177 if (p->evas) _e_pointer_canvas_del(p);
178 ecore_x_window_cursor_set(p->win, 0);
179 if (p->type) eina_stringshare_del(p->type);
184 stack = eina_list_data_get(p->stack);
185 _e_pointer_type_set(p, stack->type);
187 if (p->type) eina_stringshare_del(p->type);
188 p->type = eina_stringshare_add(stack->type);
191 /* try the default cursor next time */
192 p->e_cursor = e_config->use_e_cursor;
196 e_pointer_idler_before(void)
201 if (!e_config->show_cursor) return;
202 EINA_LIST_FOREACH(_e_pointers, l, p)
206 if (!p->e_cursor) continue;
207 if (!p->evas) continue;
209 updates = evas_render_updates(p->evas);
210 if ((updates) || (p->hot.update))
214 cur = ecore_x_cursor_new(p->win, p->pixels, p->w, p->h,
216 ecore_x_window_cursor_set(p->win, cur);
217 ecore_x_cursor_free(cur);
218 evas_render_updates_free(updates);
224 /* local subsystem functions */
226 _e_pointer_canvas_add(E_Pointer *p)
228 Evas_Engine_Info_Buffer *einfo;
232 p->w = e_config->cursor_size;
233 p->h = e_config->cursor_size;
236 p->evas = evas_new();
239 e_object_del(E_OBJECT(p));
242 rmethod = evas_render_method_lookup("buffer");
243 evas_output_method_set(p->evas, rmethod);
244 evas_output_size_set(p->evas, p->w, p->h);
245 evas_output_viewport_set(p->evas, 0, 0, p->w, p->h);
247 p->pixels = malloc(p->w * p->h * sizeof(int));
250 _e_pointer_canvas_del(p);
253 einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas);
256 _e_pointer_canvas_del(p);
259 einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
260 einfo->info.dest_buffer = p->pixels;
261 einfo->info.dest_buffer_row_bytes = p->w * sizeof(int);
262 einfo->info.use_color_key = 0;
263 einfo->info.alpha_threshold = 0;
264 einfo->info.func.new_update_region = NULL;
265 einfo->info.func.free_update_region = NULL;
266 evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo);
268 /* set the pointer edje */
269 o = edje_object_add(p->evas);
270 p->pointer_object = o;
271 /* Create the hotspot object */
272 o = evas_object_rectangle_add(p->evas);
273 evas_object_color_set(o, 0, 0, 0, 0);
275 evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
276 _e_pointer_cb_move, p);
278 evas_object_move(p->pointer_object, 0, 0);
279 evas_object_resize(p->pointer_object, p->w, p->h);
280 evas_object_show(p->pointer_object);
284 _e_pointer_canvas_del(E_Pointer *p)
286 if (p->pointer_object) evas_object_del(p->pointer_object);
287 if (p->hot_object) evas_object_del(p->hot_object);
288 if (p->evas) evas_free(p->evas);
289 if (p->pixels) free(p->pixels);
290 p->pointer_object = NULL;
291 p->hot_object = NULL;
297 _e_pointer_cb_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
302 if (!e_config->show_cursor) return;
305 if (!p->e_cursor) return;
306 edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
308 if ((p->hot.x != x) || (p->hot.y != y))
317 _e_pointer_free(E_Pointer *p)
319 _e_pointers = eina_list_remove(_e_pointers, p);
321 _e_pointer_canvas_del(p);
323 E_FREE_LIST(p->stack, _e_pointer_stack_free);
325 if (p->type) eina_stringshare_del(p->type);
326 if (p->idle_timer) ecore_timer_del(p->idle_timer);
327 if (p->idle_poller) ecore_poller_del(p->idle_poller);
330 p->idle_timer = NULL;
331 p->idle_poller = NULL;
336 _e_pointer_stack_free(E_Pointer_Stack *elem)
338 if (elem->type) eina_stringshare_del(elem->type);
343 _e_pointer_type_set(E_Pointer *p, const char *type)
345 /* Check if this pointer is already set */
346 if ((p->type) && (!strcmp(p->type, type))) return;
348 if (p->type) eina_stringshare_del(p->type);
349 p->type = eina_stringshare_add(type);
351 /* Do not set type if in "hidden mode" */
352 if (!e_config->show_cursor)
354 ecore_x_window_cursor_set(p->win, 0);
363 if (!p->evas) _e_pointer_canvas_add(p);
365 snprintf(cursor, sizeof(cursor),
366 "e/pointer/enlightenment/%s/color", type);
368 snprintf(cursor, sizeof(cursor),
369 "e/pointer/enlightenment/%s/mono", type);
370 if (!e_theme_edje_object_set(p->pointer_object,
371 "base/theme/pointer", cursor))
373 edje_object_part_swallow(p->pointer_object, "e.swallow.hotspot",
375 edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
377 if ((p->hot.x != x) || (p->hot.y != y))
387 Ecore_X_Cursor cursor = 0;
389 if (p->evas) _e_pointer_canvas_del(p);
390 if (!strcmp(type, "move"))
391 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_FLEUR);
393 else if (!strcmp(type, "resize"))
394 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_SIZING);
396 else if (!strcmp(type, "resize_tl"))
397 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_LEFT_CORNER);
398 else if (!strcmp(type, "resize_t"))
399 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_SIDE);
400 else if (!strcmp(type, "resize_tr"))
401 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_RIGHT_CORNER);
402 else if (!strcmp(type, "resize_r"))
403 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_RIGHT_SIDE);
404 else if (!strcmp(type, "resize_br"))
405 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER);
406 else if (!strcmp(type, "resize_b"))
407 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_SIDE);
408 else if (!strcmp(type, "resize_bl"))
409 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_LEFT_CORNER);
410 else if (!strcmp(type, "resize_l"))
411 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_SIDE);
412 else if (!strcmp(type, "entry"))
413 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_XTERM);
414 else if (!strcmp(type, "default"))
415 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_PTR);
416 else if (!strcmp(type, "plus"))
417 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_PLUS);
420 printf("Unknown pointer type: %s\n", type);
421 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_ARROW);
423 if (!cursor) printf("X Cursor for %s is missing\n", type);
424 ecore_x_window_cursor_set(p->win, cursor);
425 if (cursor) ecore_x_cursor_free(cursor);
430 _e_pointer_active_handle(E_Pointer *p)
432 /* we got some mouse event - if there was an idle timer emit an active
433 * signal as we WERE idle, NOW we are active */
436 ecore_timer_del(p->idle_timer);
437 p->idle_timer = NULL;
441 ecore_poller_del(p->idle_poller);
442 p->idle_poller = NULL;
446 if (p->pointer_object)
447 edje_object_signal_emit(p->pointer_object, "e,state,mouse,active", "e");
450 if (e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) return;
451 /* and schedule a pre-idle check in 1 second if no more events happen */
452 if (!e_config->idle_cursor) return;
453 p->idle_timer = ecore_timer_loop_add(1.0, _e_pointer_cb_idle_timer_pre, p);
457 _e_pointer_cb_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
462 EINA_LIST_FOREACH(_e_pointers, l, p)
464 _e_pointer_active_handle(p);
465 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
467 if (p->pointer_object)
468 edje_object_signal_emit(p->pointer_object,
469 "e,action,mouse,down", "e");
472 return ECORE_CALLBACK_PASS_ON;
476 _e_pointer_cb_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
481 EINA_LIST_FOREACH(_e_pointers, l, p)
483 _e_pointer_active_handle(p);
484 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
486 if (p->pointer_object)
487 edje_object_signal_emit(p->pointer_object,
488 "e,action,mouse,up", "e");
491 return ECORE_CALLBACK_PASS_ON;
495 _e_pointer_cb_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
500 EINA_LIST_FOREACH(_e_pointers, l, p)
502 _e_pointer_active_handle(p);
503 if (e_powersave_mode_get() < E_POWERSAVE_MODE_HIGH)
505 if (p->pointer_object)
506 edje_object_signal_emit(p->pointer_object,
507 "e,action,mouse,move", "e");
510 return ECORE_CALLBACK_PASS_ON;
514 _e_pointer_cb_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
519 EINA_LIST_FOREACH(_e_pointers, l, p)
521 _e_pointer_active_handle(p);
522 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
524 if (p->pointer_object)
525 edje_object_signal_emit(p->pointer_object,
526 "e,action,mouse,wheel", "e");
529 return ECORE_CALLBACK_PASS_ON;
533 _e_pointer_cb_idle_timer_pre(void *data)
539 ecore_x_pointer_xy_get(p->win, &x, &y);
542 p->idle_timer = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_timer_wait, p);
543 return ECORE_CALLBACK_CANCEL;
547 _e_pointer_cb_idle_timer_wait(void *data)
552 if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
553 (!e_config->idle_cursor))
555 if (p->idle_poller) ecore_poller_del(p->idle_poller);
556 p->idle_poller = NULL;
557 p->idle_timer = NULL;
558 return ECORE_CALLBACK_CANCEL;
561 p->idle_poller = ecore_poller_add(ECORE_POLLER_CORE, 64,
562 _e_pointer_cb_idle_poller, p);
563 p->idle_timer = NULL;
564 return ECORE_CALLBACK_CANCEL;
568 _e_pointer_cb_idle_poller(void *data)
574 if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
575 (!e_config->idle_cursor))
577 p->idle_poller = NULL;
578 return ECORE_CALLBACK_CANCEL;
580 /* check if pointer actually moved since the 1 second post-mouse move idle
581 * pre-timer that fetches the position */
582 ecore_x_pointer_xy_get(p->win, &x, &y);
583 if ((x != p->x) || (y != p->y))
585 /* it moved - so we are not idle yet - record position and wait
591 if (p->pointer_object)
592 edje_object_signal_emit(p->pointer_object,
593 "e,state,mouse,active", "e");
596 /* use poller to check from now on */
597 return ECORE_CALLBACK_RENEW;
599 /* we are idle - report it if not idle before */
602 if (p->pointer_object)
603 edje_object_signal_emit(p->pointer_object, "e,state,mouse,idle", "e");
606 return ECORE_CALLBACK_RENEW;