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,
182 E_Pointer_Stack *stack;
185 EINA_LIST_FOREACH(p->stack, l, 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);
244 /* local subsystem functions */
246 _e_pointer_canvas_add(E_Pointer *p)
248 Evas_Engine_Info_Buffer *einfo;
253 p->w = e_config->cursor_size;
254 p->h = e_config->cursor_size;
257 p->evas = evas_new();
260 e_object_del(E_OBJECT(p));
263 rmethod = evas_render_method_lookup("buffer");
264 evas_output_method_set(p->evas, rmethod);
265 evas_output_size_set(p->evas, p->w, p->h);
266 evas_output_viewport_set(p->evas, 0, 0, p->w, p->h);
268 p->pixels = malloc(p->w * p->h * sizeof(int));
271 _e_pointer_canvas_del(p);
274 einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas);
277 _e_pointer_canvas_del(p);
280 einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
281 einfo->info.dest_buffer = p->pixels;
282 einfo->info.dest_buffer_row_bytes = p->w * sizeof(int);
283 einfo->info.use_color_key = 0;
284 einfo->info.alpha_threshold = 0;
285 einfo->info.func.new_update_region = NULL;
286 einfo->info.func.free_update_region = NULL;
287 evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo);
289 /* set the pointer edje */
290 o = edje_object_add(p->evas);
291 p->pointer_object = o;
292 /* Create the hotspot object */
293 o = evas_object_rectangle_add(p->evas);
294 evas_object_color_set(o, 0, 0, 0, 0);
296 evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
297 _e_pointer_cb_move, p);
299 evas_object_move(p->pointer_object, 0, 0);
300 evas_object_resize(p->pointer_object, p->w, p->h);
301 evas_object_show(p->pointer_object);
305 _e_pointer_canvas_del(E_Pointer *p)
308 if (p->pointer_object) evas_object_del(p->pointer_object);
309 if (p->hot_object) evas_object_del(p->hot_object);
310 if (p->evas) evas_free(p->evas);
311 if (p->pixels) free(p->pixels);
312 p->pointer_object = NULL;
313 p->hot_object = NULL;
319 _e_pointer_cb_move(void *data,
321 Evas_Object *obj __UNUSED__,
322 void *event_info __UNUSED__)
327 if (!e_config->show_cursor) return;
329 if (!(p = data)) return;
330 if (!p->e_cursor) return;
331 edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
333 if ((p->hot.x != x) || (p->hot.y != y))
342 _e_pointer_free(E_Pointer *p)
345 _e_pointers = eina_list_remove(_e_pointers, p);
347 _e_pointer_canvas_del(p);
349 E_FREE_LIST(p->stack, _e_pointer_stack_free);
351 if (p->type) eina_stringshare_del(p->type);
352 if (p->idle_timer) ecore_timer_del(p->idle_timer);
353 if (p->idle_poller) ecore_poller_del(p->idle_poller);
356 p->idle_timer = NULL;
357 p->idle_poller = NULL;
362 _e_pointer_stack_free(E_Pointer_Stack *elem)
364 if (elem->type) eina_stringshare_del(elem->type);
369 _e_pointer_type_set(E_Pointer *p,
374 /* Check if this pointer is already set */
375 if ((p->type) && (!strcmp(p->type, type))) return;
377 eina_stringshare_replace(&p->type, type);
379 /* Do not set type if in "hidden mode" */
380 if (!e_config->show_cursor)
382 ecore_x_window_cursor_set(p->win, 0);
391 if (!p->evas) _e_pointer_canvas_add(p);
393 snprintf(cursor, sizeof(cursor),
394 "e/pointer/enlightenment/%s/color", type);
396 snprintf(cursor, sizeof(cursor),
397 "e/pointer/enlightenment/%s/mono", type);
398 if (!e_theme_edje_object_set(p->pointer_object,
399 "base/theme/pointer", cursor))
401 edje_object_part_swallow(p->pointer_object, "e.swallow.hotspot",
403 edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot",
405 if ((p->hot.x != x) || (p->hot.y != y))
415 Ecore_X_Cursor cursor = 0;
417 if (p->evas) _e_pointer_canvas_del(p);
418 if (!strcmp(type, "move"))
419 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_FLEUR);
421 else if (!strcmp(type, "resize"))
422 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_SIZING);
424 else if (!strcmp(type, "resize_tl"))
425 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_LEFT_CORNER);
426 else if (!strcmp(type, "resize_t"))
427 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_SIDE);
428 else if (!strcmp(type, "resize_tr"))
429 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_RIGHT_CORNER);
430 else if (!strcmp(type, "resize_r"))
431 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_RIGHT_SIDE);
432 else if (!strcmp(type, "resize_br"))
433 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER);
434 else if (!strcmp(type, "resize_b"))
435 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_SIDE);
436 else if (!strcmp(type, "resize_bl"))
437 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_LEFT_CORNER);
438 else if (!strcmp(type, "resize_l"))
439 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_SIDE);
440 else if (!strcmp(type, "entry"))
441 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_XTERM);
442 else if (!strcmp(type, "default"))
443 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_PTR);
444 else if (!strcmp(type, "plus"))
445 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_PLUS);
446 else if (!strcmp(type, "hand"))
447 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_HAND1);
450 printf("Unknown pointer type: %s\n", type);
451 cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_ARROW);
453 if (!cursor) printf("X Cursor for %s is missing\n", type);
454 ecore_x_window_cursor_set(p->win, cursor);
455 if (cursor) ecore_x_cursor_free(cursor);
460 _e_pointer_active_handle(E_Pointer *p)
464 /* we got some mouse event - if there was an idle timer emit an active
465 * signal as we WERE idle, NOW we are active */
468 ecore_timer_del(p->idle_timer);
469 p->idle_timer = NULL;
473 ecore_poller_del(p->idle_poller);
474 p->idle_poller = NULL;
478 if (p->pointer_object)
479 edje_object_signal_emit(p->pointer_object, "e,state,mouse,active", "e");
482 if (e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) return;
483 /* and schedule a pre-idle check in 1 second if no more events happen */
484 if (!e_config->idle_cursor) return;
485 p->idle_timer = ecore_timer_loop_add(1.0, _e_pointer_cb_idle_timer_pre, p);
489 _e_pointer_cb_mouse_down(void *data __UNUSED__,
491 void *event __UNUSED__)
496 EINA_LIST_FOREACH(_e_pointers, l, p)
498 _e_pointer_active_handle(p);
499 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
501 if (p->pointer_object)
502 edje_object_signal_emit(p->pointer_object,
503 "e,action,mouse,down", "e");
506 return ECORE_CALLBACK_PASS_ON;
510 _e_pointer_cb_mouse_up(void *data __UNUSED__,
512 void *event __UNUSED__)
517 EINA_LIST_FOREACH(_e_pointers, l, p)
519 _e_pointer_active_handle(p);
520 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
522 if (p->pointer_object)
523 edje_object_signal_emit(p->pointer_object,
524 "e,action,mouse,up", "e");
527 return ECORE_CALLBACK_PASS_ON;
531 _e_pointer_cb_mouse_move(void *data __UNUSED__,
533 void *event __UNUSED__)
538 EINA_LIST_FOREACH(_e_pointers, l, p)
540 _e_pointer_active_handle(p);
541 if (e_powersave_mode_get() < E_POWERSAVE_MODE_HIGH)
543 if (p->pointer_object)
544 edje_object_signal_emit(p->pointer_object,
545 "e,action,mouse,move", "e");
548 return ECORE_CALLBACK_PASS_ON;
552 _e_pointer_cb_mouse_wheel(void *data __UNUSED__,
554 void *event __UNUSED__)
559 EINA_LIST_FOREACH(_e_pointers, l, p)
561 _e_pointer_active_handle(p);
562 if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME)
564 if (p->pointer_object)
565 edje_object_signal_emit(p->pointer_object,
566 "e,action,mouse,wheel", "e");
569 return ECORE_CALLBACK_PASS_ON;
573 _e_pointer_cb_idle_timer_pre(void *data)
578 if (!(p = data)) return ECORE_CALLBACK_RENEW;
579 ecore_x_pointer_xy_get(p->win, &x, &y);
582 p->idle_timer = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_timer_wait, p);
583 return ECORE_CALLBACK_CANCEL;
587 _e_pointer_cb_idle_timer_wait(void *data)
591 if (!(p = data)) return ECORE_CALLBACK_RENEW;
592 if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
593 (!e_config->idle_cursor))
595 if (p->idle_poller) ecore_poller_del(p->idle_poller);
596 p->idle_poller = NULL;
597 p->idle_timer = NULL;
598 return ECORE_CALLBACK_CANCEL;
601 p->idle_poller = ecore_poller_add(ECORE_POLLER_CORE, 64,
602 _e_pointer_cb_idle_poller, p);
603 p->idle_timer = NULL;
604 return ECORE_CALLBACK_CANCEL;
608 _e_pointer_cb_idle_poller(void *data)
613 if (!(p = data)) return ECORE_CALLBACK_RENEW;
614 if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) ||
615 (!e_config->idle_cursor))
617 p->idle_poller = NULL;
618 return ECORE_CALLBACK_CANCEL;
620 /* check if pointer actually moved since the 1 second post-mouse move idle
621 * pre-timer that fetches the position */
622 ecore_x_pointer_xy_get(p->win, &x, &y);
623 if ((x != p->x) || (y != p->y))
625 /* it moved - so we are not idle yet - record position and wait
631 if (p->pointer_object)
632 edje_object_signal_emit(p->pointer_object,
633 "e,state,mouse,active", "e");
636 /* use poller to check from now on */
637 return ECORE_CALLBACK_RENEW;
639 /* we are idle - report it if not idle before */
642 if (p->pointer_object)
643 edje_object_signal_emit(p->pointer_object, "e,state,mouse,idle", "e");
646 return ECORE_CALLBACK_RENEW;