From 2ec808f9d85014f682a5faded13df41d9efdeb2b Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 11 Sep 2013 13:03:31 +0100 Subject: [PATCH] wl pointers done pointers in E now come in two flavors, one for each protocol that we currently support. each is created from the owner compositor backend: X pointers still work as usual Wayland pointers are actually surfaces that we dump image data into periodically to render them as evas images some small amounts of hack is necessary to make this work, namely blocking X pointers when a Wayland one is in use if we're running a multi-protocol compositor --- src/bin/e_comp_canvas.c | 1 - src/bin/e_comp_wl.c | 66 +- src/bin/e_comp_x.c | 2 + src/bin/e_pointer.c | 1158 ++++++++++++--------- src/bin/e_pointer.h | 13 +- src/bin/e_win.c | 10 +- src/modules/wl_desktop_shell/e_mod_main.c | 29 +- src/modules/wl_fb/e_mod_main.c | 1 + src/modules/wl_x11/e_mod_main.c | 2 +- 9 files changed, 742 insertions(+), 540 deletions(-) diff --git a/src/bin/e_comp_canvas.c b/src/bin/e_comp_canvas.c index b6571087d..22a904205 100644 --- a/src/bin/e_comp_canvas.c +++ b/src/bin/e_comp_canvas.c @@ -128,7 +128,6 @@ e_comp_canvas_init(E_Comp *c) evas_event_callback_add(c->evas, EVAS_CALLBACK_RENDER_POST, _e_comp_canvas_render_post, c); c->ee_win = ecore_evas_window_get(c->ee); - c->pointer = e_pointer_window_new(c->man->root, 1); for (layer = 0; layer <= e_comp_canvas_layer_map(E_LAYER_MAX); layer++) { diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index 8c94fc85b..31c56ef56 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -1738,6 +1738,10 @@ _e_comp_wl_cb_surface_destroy(struct wl_resource *resource) buffer->ews = NULL; ews->buffers = eina_inlist_remove(ews->buffers, EINA_INLIST_GET(buffer)); } + if (e_comp_get(NULL)->pointer->pixmap == ews->pixmap) + { + e_pointer_image_set(e_comp_get(NULL)->pointer, NULL, 0, 0, 0, 0); + } e_pixmap_parent_window_set(ews->pixmap, NULL); e_pixmap_free(ews->pixmap); @@ -2277,53 +2281,17 @@ _e_comp_wl_pointer_configure(E_Wayland_Surface *ews, Evas_Coord x, Evas_Coord y, /* do we have a focused surface ? */ if (!input->wl.seat.pointer->focus) return; - if ((focus = wl_resource_get_user_data(input->wl.seat.pointer->focus))) - { - /* NB: Ideally, I wanted to use the e_pointer methods here so that - * the cursor would match the E theme, however Wayland currently - * provides NO Method to get the cursor name :( so we are stuck - * using the pixels from their cursor surface */ + focus = wl_resource_get_user_data(input->wl.seat.pointer->focus); + if (!focus) return; + /* NB: Ideally, I wanted to use the e_pointer methods here so that + * the cursor would match the E theme, however Wayland currently + * provides NO Method to get the cursor name :( so we are stuck + * using the pixels from their cursor surface */ - /* is it mapped ? */ - if ((focus->mapped) && (focus->ec)) - { - Ecore_Window win; - - /* try to get the ecore_window */ -#warning CURSOR BROKEN -#if 0 - if ((win = ecore_evas_window_get(focus->ee))) - { - E_Wayland_Buffer_Reference *ref; - struct wl_shm_buffer *shm_buffer; - void *pixels; - - ref = &ews->buffer_reference; - - shm_buffer = wl_shm_buffer_get(ref->buffer->wl.resource); - - /* grab the pixels from the cursor surface */ - if ((pixels = wl_shm_buffer_get_data(shm_buffer))) - { - Ecore_X_Cursor cur; - - /* create the new X cursor with this image */ - cur = ecore_x_cursor_new(win, pixels, w, h, - input->pointer.hot.x, - input->pointer.hot.y); - - /* set the cursor on this window */ - ecore_x_window_cursor_set(win, cur); - - /* free the cursor */ - ecore_x_cursor_free(cur); - } - else - ecore_x_window_cursor_set(win, 0); - } -#endif - } - } + /* is it mapped ? */ + if ((!focus->mapped) || (!focus->ec)) return; + e_pixmap_dirty(ews->pixmap); + e_pointer_image_set(focus->ec->comp->pointer, ews->pixmap, w, h, input->pointer.hot.x, input->pointer.hot.y); } static void @@ -2404,7 +2372,11 @@ _e_comp_wl_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *r input->pointer.surface = ews; /* if we don't have a pointer surface, we are done here */ - if (!ews) return; + if (!ews) + { + e_pointer_hide(e_comp_get(NULL)->pointer); + return; + } /* set the destroy listener */ wl_signal_add(&ews->wl.destroy_signal, diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index 279f20a2c..ca959af38 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -4651,6 +4651,8 @@ _e_comp_x_setup(E_Comp *c, Ecore_X_Window root, int w, int h) } ecore_evas_lower(c->ee); + c->pointer = e_pointer_window_new(c->man->root, 1); + c->pointer->color = c->pointer->e_cursor && ecore_x_cursor_color_supported_get(); _e_comp_x_manage_windows(c); return !!c->bg_blank_object; diff --git a/src/bin/e_pointer.c b/src/bin/e_pointer.c index 87ccaa1d8..5529c39b7 100644 --- a/src/bin/e_pointer.c +++ b/src/bin/e_pointer.c @@ -17,54 +17,519 @@ struct _E_Pointer_Stack static Eina_List *_e_pointers = NULL; static Eina_List *handlers = NULL; -static void _e_pointer_canvas_add(E_Pointer *p); static void _e_pointer_canvas_del(E_Pointer *p); -static void _e_pointer_cb_move(void *data, - Evas *e __UNUSED__, - Evas_Object *obj __UNUSED__, - void *event_info); static void _e_pointer_free(E_Pointer *p); static void _e_pointer_stack_free(E_Pointer_Stack *elem); static void _e_pointer_type_set(E_Pointer *p, const char *type); static void _e_pointer_active_handle(E_Pointer *p); -static Eina_Bool _e_pointer_cb_mouse_down(void *data, - int type, - void *event); -static Eina_Bool _e_pointer_cb_mouse_up(void *data, - int type, - void *event); -static Eina_Bool _e_pointer_cb_mouse_move(void *data, - int type, - void *event); -static Eina_Bool _e_pointer_cb_mouse_wheel(void *data, - int type, - void *event); static Eina_Bool _e_pointer_cb_idle_timer_pre(void *data); static Eina_Bool _e_pointer_cb_idle_timer_wait(void *data); static Eina_Bool _e_pointer_cb_idle_poller(void *data); + +static void +_e_pointer_hot_update(E_Pointer *p, int x, int y) +{ + if ((p->hot.x != x) || (p->hot.y != y)) + { + p->hot.x = x; + p->hot.y = y; + p->hot.update = 1; + } +} + +static void +_e_pointer_active(E_Pointer *p) +{ + if (!p->idle) return; + if (p->pointer_object) + edje_object_signal_emit(p->pointer_object, + "e,state,mouse,active", "e"); + p->idle = 0; +} + +static void +_e_pointer_idle(E_Pointer *p) +{ + if (p->idle) return; + if (p->pointer_object) + edje_object_signal_emit(p->pointer_object, "e,state,mouse,idle", "e"); + p->idle = 1; +} + +static void +_e_pointer_cb_show(void *data, + Evas *e __UNUSED__, + Evas_Object *obj, + void *event_info __UNUSED__) +{ + int x, y; + edje_object_part_geometry_get(obj, "e.swallow.hotspot", + &x, &y, NULL, NULL); + _e_pointer_hot_update(data, x, y); +} + +static void +_e_pointer_cb_move(void *data, + Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + E_Pointer *p; + Evas_Coord x, y; + + if (!e_config->show_cursor) return; + if (!(p = data)) return; + if (!p->e_cursor) return; + if (!evas_object_visible_get(p->pointer_object)) return; + edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot", + &x, &y, NULL, NULL); + _e_pointer_hot_update(p, x, y); +} + +static void +_e_pointer_canvas_resize(E_Pointer *p, int w, int h) +{ + Evas_Engine_Info_Buffer *einfo; + + if ((p->w == w) && (p->h == h)) return; + p->w = w, p->h = h; + evas_output_size_set(p->evas, p->w, p->h); + evas_output_viewport_set(p->evas, 0, 0, p->w, p->h); + + p->pixels = realloc(p->pixels, p->w * p->h * sizeof(int)); + + einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas); + + EINA_SAFETY_ON_NULL_RETURN(einfo); + einfo->info.dest_buffer = p->pixels; + einfo->info.dest_buffer_row_bytes = p->w * sizeof(int); + evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo); + + evas_object_move(p->pointer_object, 0, 0); + evas_object_resize(p->pointer_object, p->w, p->h); + if (p->pointer_image) evas_object_resize(p->pointer_image, p->w, p->h); +} + +/* local subsystem functions */ +static void +_e_pointer_canvas_add(E_Pointer *p) +{ + Evas_Engine_Info_Buffer *einfo; + Evas_Object *o; + int rmethod; + + if (!p) return; + p->w = e_config->cursor_size; + p->h = e_config->cursor_size; + + /* create evas */ + p->evas = evas_new(); + if (!p->evas) + { + e_object_del(E_OBJECT(p)); + return; + } + rmethod = evas_render_method_lookup("buffer"); + evas_output_method_set(p->evas, rmethod); + evas_output_size_set(p->evas, p->w, p->h); + evas_output_viewport_set(p->evas, 0, 0, p->w, p->h); + + p->pixels = malloc(p->w * p->h * sizeof(int)); + if (!p->pixels) + { + _e_pointer_canvas_del(p); + return; + } + einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas); + if (!einfo) + { + _e_pointer_canvas_del(p); + return; + } + einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32; + einfo->info.dest_buffer = p->pixels; + einfo->info.dest_buffer_row_bytes = p->w * sizeof(int); + einfo->info.use_color_key = 0; + einfo->info.alpha_threshold = 0; + einfo->info.func.new_update_region = NULL; + einfo->info.func.free_update_region = NULL; + evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo); + + /* set the pointer edje */ + o = edje_object_add(p->evas); + p->pointer_object = o; + /* Create the hotspot object */ + o = evas_object_rectangle_add(p->evas); + evas_object_color_set(o, 0, 0, 0, 0); + p->hot_object = o; + evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, + _e_pointer_cb_move, p); + evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, + _e_pointer_cb_show, p); + /* init edje */ + evas_object_move(p->pointer_object, 0, 0); + evas_object_resize(p->pointer_object, p->w, p->h); + evas_object_show(p->pointer_object); +} + +static void +_e_pointer_canvas_del(E_Pointer *p) +{ + if (!p) return; + E_FREE_FUNC(p->pointer_object, evas_object_del); + E_FREE_FUNC(p->hot_object, evas_object_del); + if (p->evas && (!p->canvas)) evas_free(p->evas); + p->evas = NULL; + E_FREE(p->pixels); +} + +static void +_e_pointer_free(E_Pointer *p) +{ + if (!p) return; + _e_pointers = eina_list_remove(_e_pointers, p); + + _e_pointer_canvas_del(p); + E_FREE_FUNC(p->pointer_image, evas_object_del); + + E_FREE_LIST(p->stack, _e_pointer_stack_free); + + if (p->type) eina_stringshare_del(p->type); + if (p->idle_timer) ecore_timer_del(p->idle_timer); + if (p->idle_poller) ecore_poller_del(p->idle_poller); + + p->type = NULL; + p->idle_timer = NULL; + p->idle_poller = NULL; + E_FREE(p); +} + +static void +_e_pointer_stack_free(E_Pointer_Stack *elem) +{ + if (elem->type) eina_stringshare_del(elem->type); + free(elem); +} + +static void +_e_pointer_type_set(E_Pointer *p, + const char *type) +{ + if (!p) return; + + /* Check if this pointer is already set */ + if (!e_util_strcmp(p->type, type)) return; + + eina_stringshare_replace(&p->type, type); + + /* Do not set type if in "hidden mode" */ + if (!e_config->show_cursor) + { +#ifdef WAYLAND_ONLY + evas_object_hide(p->pointer_image); +#else + if (!p->canvas) + ecore_x_window_cursor_set(p->win, 0); +#endif + return; + } + + if (p->e_cursor) + { + char cursor[1024]; + Evas_Coord x, y; + + if (!p->evas) _e_pointer_canvas_add(p); + if (p->color) + snprintf(cursor, sizeof(cursor), + "e/pointer/enlightenment/%s/color", type); + else + snprintf(cursor, sizeof(cursor), + "e/pointer/enlightenment/%s/mono", type); + if (!e_theme_edje_object_set(p->pointer_object, + "base/theme/pointer", cursor)) + goto fallback; + edje_object_part_swallow(p->pointer_object, "e.swallow.hotspot", + p->hot_object); + edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot", + &x, &y, NULL, NULL); + if ((p->hot.x != x) || (p->hot.y != y)) + { + p->hot.x = x; + p->hot.y = y; + } + p->hot.update = 1; + evas_object_show(p->pointer_object); + return; + } +fallback: +#ifndef WAYLAND_ONLY + if (p->canvas) return; + { + Ecore_X_Cursor cursor = 0; + + E_FREE_FUNC(p->pointer_image, evas_object_del); + if (p->evas) _e_pointer_canvas_del(p); + if (!strcmp(type, "move")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_FLEUR); +#if 0 + else if (!strcmp(type, "resize")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_SIZING); +#endif + else if (!strcmp(type, "resize_tl")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_LEFT_CORNER); + else if (!strcmp(type, "resize_t")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_SIDE); + else if (!strcmp(type, "resize_tr")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_RIGHT_CORNER); + else if (!strcmp(type, "resize_r")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_RIGHT_SIDE); + else if (!strcmp(type, "resize_br")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER); + else if (!strcmp(type, "resize_b")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_SIDE); + else if (!strcmp(type, "resize_bl")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_LEFT_CORNER); + else if (!strcmp(type, "resize_l")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_SIDE); + else if (!strcmp(type, "entry")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_XTERM); + else if (!strcmp(type, "default")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_PTR); + else if (!strcmp(type, "plus")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_PLUS); + else if (!strcmp(type, "hand")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_HAND1); + else if (!strcmp(type, "rotate")) + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_EXCHANGE); + else + { + printf("Unknown pointer type: %s\n", type); + cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_ARROW); + } + if (!cursor) printf("X Cursor for %s is missing\n", type); + ecore_x_window_cursor_set(p->win, cursor); + if (cursor) ecore_x_cursor_free(cursor); + } +#endif +} + +static void +_e_pointer_active_handle(E_Pointer *p) +{ + if (!p) return; + _e_pointer_active(p); + if (p->canvas) + { + ecore_timer_reset(p->idle_timer); + return; + } + + /* we got some mouse event - if there was an idle timer emit an active + * signal as we WERE idle, NOW we are active */ + E_FREE_FUNC(p->idle_timer, ecore_timer_del); + E_FREE_FUNC(p->idle_poller, ecore_poller_del); + if (e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) return; + /* and schedule a pre-idle check in 1 second if no more events happen */ + if (!e_config->idle_cursor) return; + p->idle_timer = ecore_timer_loop_add(1.0, _e_pointer_cb_idle_timer_pre, p); +} + +static Eina_Bool +_e_pointer_cb_mouse_down(void *data __UNUSED__, + int type __UNUSED__, + void *event __UNUSED__) +{ + Eina_List *l; + E_Pointer *p; + + EINA_LIST_FOREACH(_e_pointers, l, p) + { + _e_pointer_active_handle(p); + if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME) + { + if (p->pointer_object) + edje_object_signal_emit(p->pointer_object, + "e,action,mouse,down", "e"); + } + } + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_pointer_cb_mouse_up(void *data __UNUSED__, + int type __UNUSED__, + void *event __UNUSED__) +{ + Eina_List *l; + E_Pointer *p; + + EINA_LIST_FOREACH(_e_pointers, l, p) + { + _e_pointer_active_handle(p); + if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME) + { + if (p->pointer_object) + edje_object_signal_emit(p->pointer_object, + "e,action,mouse,up", "e"); + } + } + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_pointer_cb_mouse_move(void *data __UNUSED__, + int type __UNUSED__, + Ecore_Event_Mouse_Move *ev) +{ + Eina_List *l; + E_Pointer *p; + + EINA_LIST_FOREACH(_e_pointers, l, p) + { + _e_pointer_active_handle(p); + if (e_powersave_mode_get() < E_POWERSAVE_MODE_HIGH) + { + if (p->pointer_object) + edje_object_signal_emit(p->pointer_object, + "e,action,mouse,move", "e"); + } + if (p->canvas) + { + evas_object_move(p->pointer_image, + e_comp_canvas_x_root_adjust(e_comp_get(NULL), ev->root.x), + e_comp_canvas_y_root_adjust(e_comp_get(NULL), ev->root.y) + ); + } + } + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_pointer_cb_mouse_wheel(void *data __UNUSED__, + int type __UNUSED__, + void *event __UNUSED__) +{ + Eina_List *l; + E_Pointer *p; + + EINA_LIST_FOREACH(_e_pointers, l, p) + { + _e_pointer_active_handle(p); + if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME) + { + if (p->pointer_object) + edje_object_signal_emit(p->pointer_object, + "e,action,mouse,wheel", "e"); + } + } + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_pointer_idle_timer(void *data) +{ + E_Pointer *p = data; + + if (e_config->idle_cursor) + _e_pointer_idle(p); + + return EINA_TRUE; +} + +#ifndef WAYLAND_ONLY +static Eina_Bool +_e_pointer_cb_idle_timer_pre(void *data) +{ + E_Pointer *p; + int x, y; + + if (!(p = data)) return ECORE_CALLBACK_RENEW; + ecore_x_pointer_xy_get(p->win, &x, &y); + p->x = x; + p->y = y; + if (p->canvas) + evas_object_move(p->pointer_image, + e_comp_canvas_x_root_adjust(e_comp_get(NULL), x), + e_comp_canvas_y_root_adjust(e_comp_get(NULL), y) + ); + p->idle_timer = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_timer_wait, p); + return ECORE_CALLBACK_CANCEL; +} + + +static Eina_Bool +_e_pointer_cb_idle_timer_wait(void *data) +{ + E_Pointer *p; + + if (!(p = data)) return ECORE_CALLBACK_RENEW; + if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) || + (!e_config->idle_cursor)) + { + if (p->idle_poller) ecore_poller_del(p->idle_poller); + p->idle_poller = NULL; + p->idle_timer = NULL; + return ECORE_CALLBACK_CANCEL; + } + if (!p->idle_poller) + p->idle_poller = ecore_poller_add(ECORE_POLLER_CORE, 64, + _e_pointer_cb_idle_poller, p); + p->idle_timer = NULL; + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_e_pointer_cb_idle_poller(void *data) +{ + E_Pointer *p; + int x, y; + + if (!(p = data)) return ECORE_CALLBACK_RENEW; + if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) || + (!e_config->idle_cursor)) + { + p->idle_poller = NULL; + return ECORE_CALLBACK_CANCEL; + } + /* check if pointer actually moved since the 1 second post-mouse move idle + * pre-timer that fetches the position */ + ecore_x_pointer_xy_get(p->win, &x, &y); + if ((x != p->x) || (y != p->y)) + { + /* it moved - so we are not idle yet - record position and wait + * 4 secons more */ + p->x = x; + p->y = y; + if (p->idle) + _e_pointer_active(p); + + /* use poller to check from now on */ + return ECORE_CALLBACK_RENEW; + } + /* we are idle - report it if not idle before */ + if (!p->idle) + _e_pointer_idle(p); + return ECORE_CALLBACK_RENEW; +} +#endif + + /* externally accessible functions */ EINTERN int e_pointer_init(void) { - handlers = - eina_list_append(handlers, - ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, - _e_pointer_cb_mouse_down, NULL)); - handlers = - eina_list_append(handlers, - ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, - _e_pointer_cb_mouse_up, NULL)); - handlers = - eina_list_append(handlers, - ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, - _e_pointer_cb_mouse_move, NULL)); - handlers = - eina_list_append(handlers, - ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL, - _e_pointer_cb_mouse_wheel, NULL)); + E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, + _e_pointer_cb_mouse_down, NULL); + E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_UP, + _e_pointer_cb_mouse_up, NULL); + E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE, + _e_pointer_cb_mouse_move, NULL); + E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_WHEEL, + _e_pointer_cb_mouse_wheel, NULL); return 1; } @@ -76,27 +541,110 @@ e_pointer_shutdown(void) } EAPI E_Pointer * -e_pointer_window_new(Ecore_X_Window win, +e_pointer_window_new(Ecore_Window win, int filled) { E_Pointer *p = NULL; - if (!win) return NULL; + EINA_SAFETY_ON_FALSE_RETURN_VAL(win, NULL); p = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_free); if (!p) return NULL; p->e_cursor = e_config->use_e_cursor; p->win = win; p->color = 0; - if (e_config->use_e_cursor) - if (ecore_x_cursor_color_supported_get()) p->color = 1; +#ifndef WAYLAND_ONLY ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4); +#endif if (filled) e_pointer_type_push(p, p, "default"); _e_pointers = eina_list_append(_e_pointers, p); return p; } +EAPI E_Pointer * +e_pointer_canvas_new(Evas *e, int filled) +{ + E_Pointer *p = NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); + p = E_OBJECT_ALLOC(E_Pointer, E_POINTER_TYPE, _e_pointer_free); + if (!p) return NULL; + + p->e_cursor = p->canvas = 1; + p->color = 1; + p->w = p->h = e_config->cursor_size; + p->idle_timer = ecore_timer_loop_add(4.0, _e_pointer_idle_timer, p); + p->pointer_image = evas_object_image_filled_add(e); + evas_object_pass_events_set(p->pointer_image, 1); + evas_object_layer_set(p->pointer_image, EVAS_LAYER_MAX); + evas_object_image_alpha_set(p->pointer_image, 1); + evas_object_show(p->pointer_image); + + if (filled) e_pointer_type_push(p, p, "default"); + _e_pointers = eina_list_append(_e_pointers, p); + return p; +} + +EAPI void +e_pointer_image_set(E_Pointer *p, E_Pixmap *cp, int w, int h, int hot_x, int hot_y) +{ + void *img = NULL; + + EINA_SAFETY_ON_NULL_RETURN(p); + + p->pixmap = cp; + if (cp) + { + e_pixmap_refresh(cp); + e_pixmap_image_refresh(cp); + img = e_pixmap_image_data_get(cp); + } + else + { + Eina_Stringshare *type; + + type = p->type; + if (type) + { + p->type = NULL; + _e_pointer_type_set(p, type); + eina_stringshare_del(type); + } + } + _e_pointer_hot_update(p, hot_x, hot_y); + + if (p->evas) + { + /* e cursor: edje or image */ + if (!p->canvas) + _e_pointer_canvas_resize(p, w, h); + evas_object_hide(p->pointer_object); + if (!p->pointer_image) + { + p->pointer_image = evas_object_image_filled_add(p->evas); + evas_object_image_alpha_set(p->pointer_image, 1); + } + evas_object_image_size_set(p->pointer_image, w, h); + evas_object_image_data_set(p->pointer_image, img); + evas_object_resize(p->pointer_image, w, h); + evas_object_show(p->pointer_image); + } +#ifndef WAYLAND_ONLY + else + { + Ecore_X_Cursor cur; + + if (cp) + cur = ecore_x_cursor_new(p->win, img, w, h, + p->hot.x, p->hot.y); + ecore_x_window_cursor_set(p->win, cp ? cur : 0); + if (cp) + ecore_x_cursor_free(cur); + } +#endif +} + EAPI void e_pointers_size_set(int size) { @@ -106,39 +654,22 @@ e_pointers_size_set(int size) if (!e_config->show_cursor) return; EINA_LIST_FOREACH(_e_pointers, l, p) { - Evas_Engine_Info_Buffer *einfo; - + Eina_Stringshare *type; if (p->evas) { - p->w = p->h = size; - evas_output_size_set(p->evas, p->w, p->h); - evas_output_viewport_set(p->evas, 0, 0, p->w, p->h); - - p->pixels = realloc(p->pixels, p->w * p->h * sizeof(int)); - - einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas); - if (einfo) - { - einfo->info.dest_buffer = p->pixels; - einfo->info.dest_buffer_row_bytes = p->w * sizeof(int); - evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo); - } - - evas_object_move(p->pointer_object, 0, 0); - evas_object_resize(p->pointer_object, p->w, p->h); + if (!p->canvas) + _e_pointer_canvas_resize(p, size, size); } +#ifndef WAYLAND_ONLY else + ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4); +#endif + type = p->type; + if (type) { - const char *type; - - ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4); - type = p->type; - if (type) - { - p->type = NULL; - _e_pointer_type_set(p, type); - eina_stringshare_del(type); - } + p->type = NULL; + _e_pointer_type_set(p, type); + eina_stringshare_del(type); } } } @@ -147,7 +678,14 @@ EAPI void e_pointer_hide(E_Pointer *p) { if (!p) return; +#ifdef WAYLAND_ONLY +#else if (p->win) ecore_x_window_cursor_set(p->win, 0); +#endif + if (p->canvas) + evas_object_hide(p->pointer_image); + else + E_FREE_FUNC(p->pointer_image, evas_object_del); if (p->evas) _e_pointer_canvas_del(p); } @@ -161,17 +699,25 @@ e_pointer_type_push(E_Pointer *p, if (!p) return; p->e_cursor = e_config->use_e_cursor; + if (!p->canvas) + { + evas_object_hide(p->pointer_image); +#ifndef WAYLAND_ONLY + if (p->blocks) + { + ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4); + _e_pointer_canvas_resize(p, e_config->cursor_size, e_config->cursor_size); + } +#endif + } _e_pointer_type_set(p, type); p->obj = obj; stack = E_NEW(E_Pointer_Stack, 1); - if (stack) - { - stack->type = eina_stringshare_add(p->type); - stack->obj = p->obj; - p->stack = eina_list_prepend(p->stack, stack); - } + stack->type = eina_stringshare_ref(p->type); + stack->obj = p->obj; + p->stack = eina_list_prepend(p->stack, stack); } EAPI void @@ -185,7 +731,7 @@ e_pointer_type_pop(E_Pointer *p, if (!p) return; EINA_LIST_FOREACH_SAFE(p->stack, l, l_next, stack) { - if ((stack->obj == obj) && ((!type) || (!strcmp(stack->type, type)))) + if ((stack->obj == obj) && ((!type) || (!e_util_strcmp(stack->type, type)))) { _e_pointer_stack_free(stack); p->stack = eina_list_remove_list(p->stack, l); @@ -195,18 +741,29 @@ e_pointer_type_pop(E_Pointer *p, if (!p->stack) { - if (p->evas) _e_pointer_canvas_del(p); - ecore_x_window_cursor_set(p->win, 0); - if (p->type) eina_stringshare_del(p->type); - p->type = NULL; + e_pointer_hide(p); + eina_stringshare_replace(&p->type, NULL); return; } stack = eina_list_data_get(p->stack); _e_pointer_type_set(p, stack->type); + if ((p->blocks) && (stack->obj == p)) + { + evas_object_hide(p->pointer_object); + evas_object_show(p->pointer_image); +#ifndef WAYLAND_ONLY + if (!p->canvas) + { + int w, h; - if (p->type) eina_stringshare_del(p->type); - p->type = eina_stringshare_add(stack->type); + e_pixmap_size_get(p->pixmap, &w, &h); + _e_pointer_canvas_resize(p, w, h); + } +#endif + } + + eina_stringshare_refplace(&p->type, stack->type); p->obj = stack->obj; /* try the default cursor next time */ @@ -216,6 +773,7 @@ e_pointer_type_pop(E_Pointer *p, EAPI void e_pointer_idler_before(void) { +#ifndef WAYLAND_ONLY Eina_List *l; E_Pointer *p; @@ -226,21 +784,33 @@ e_pointer_idler_before(void) if (!p->e_cursor) continue; if (!p->evas) continue; - if (!p->win) continue; updates = evas_render_updates(p->evas); if ((updates) || (p->hot.update)) { - Ecore_X_Cursor cur; + if (p->canvas) + { + if (!p->blocks) + { + evas_object_resize(p->pointer_image, p->w, p->h); + evas_object_image_size_set(p->pointer_image, p->w, p->h); + evas_object_image_data_set(p->pointer_image, p->pixels); + } + } + else + { + Ecore_X_Cursor cur; - cur = ecore_x_cursor_new(p->win, p->pixels, p->w, p->h, - p->hot.x, p->hot.y); - ecore_x_window_cursor_set(p->win, cur); - ecore_x_cursor_free(cur); + cur = ecore_x_cursor_new(p->win, p->pixels, p->w, p->h, + p->hot.x, p->hot.y); + ecore_x_window_cursor_set(p->win, cur); + ecore_x_cursor_free(cur); + } evas_render_updates_free(updates); - p->hot.update = 0; } + p->hot.update = 0; } +#endif } /** @@ -337,410 +907,36 @@ e_pointer_mode_pop(void *obj, E_Pointer_Mode mode) } } -/* local subsystem functions */ -static void -_e_pointer_canvas_add(E_Pointer *p) +EAPI void +e_pointer_block_add(E_Pointer *p) { - Evas_Engine_Info_Buffer *einfo; - Evas_Object *o; - int rmethod; - - if (!p) return; - p->w = e_config->cursor_size; - p->h = e_config->cursor_size; - - /* create evas */ - p->evas = evas_new(); - if (!p->evas) + if (!p->blocks) { - e_object_del(E_OBJECT(p)); - return; - } - rmethod = evas_render_method_lookup("buffer"); - evas_output_method_set(p->evas, rmethod); - evas_output_size_set(p->evas, p->w, p->h); - evas_output_viewport_set(p->evas, 0, 0, p->w, p->h); + evas_object_hide(p->pointer_object); + if (p->pixmap) + { + int w, h; - p->pixels = malloc(p->w * p->h * sizeof(int)); - if (!p->pixels) - { - _e_pointer_canvas_del(p); - return; + e_pixmap_size_get(p->pixmap, &w, &h); + e_pointer_image_set(p, p->pixmap, w, h, p->hot.x, p->hot.y); + } } - einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(p->evas); - if (!einfo) - { - _e_pointer_canvas_del(p); - return; - } - einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32; - einfo->info.dest_buffer = p->pixels; - einfo->info.dest_buffer_row_bytes = p->w * sizeof(int); - einfo->info.use_color_key = 0; - einfo->info.alpha_threshold = 0; - einfo->info.func.new_update_region = NULL; - einfo->info.func.free_update_region = NULL; - evas_engine_info_set(p->evas, (Evas_Engine_Info *)einfo); - - /* set the pointer edje */ - o = edje_object_add(p->evas); - p->pointer_object = o; - /* Create the hotspot object */ - o = evas_object_rectangle_add(p->evas); - evas_object_color_set(o, 0, 0, 0, 0); - p->hot_object = o; - evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, - _e_pointer_cb_move, p); - /* init edje */ - evas_object_move(p->pointer_object, 0, 0); - evas_object_resize(p->pointer_object, p->w, p->h); - evas_object_show(p->pointer_object); + p->blocks++; + } -static void -_e_pointer_canvas_del(E_Pointer *p) +EAPI void +e_pointer_block_del(E_Pointer *p) { - if (!p) return; - if (p->pointer_object) evas_object_del(p->pointer_object); - if (p->hot_object) evas_object_del(p->hot_object); - if (p->evas) evas_free(p->evas); - free(p->pixels); - p->pointer_object = NULL; - p->hot_object = NULL; - p->evas = NULL; - p->pixels = NULL; -} - -static void -_e_pointer_cb_move(void *data, - Evas *e __UNUSED__, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) -{ - E_Pointer *p; - Evas_Coord x, y; - - if (!e_config->show_cursor) return; - - if (!(p = data)) return; - if (!p->e_cursor) return; - edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot", - &x, &y, NULL, NULL); - if ((p->hot.x != x) || (p->hot.y != y)) + if (!p->blocks) return; + p->blocks--; + if (p->blocks) return; + e_pointers_size_set(e_config->cursor_size); + if (p->pointer_image) { - p->hot.x = x; - p->hot.y = y; - p->hot.update = 1; - } -} - -static void -_e_pointer_free(E_Pointer *p) -{ - if (!p) return; - _e_pointers = eina_list_remove(_e_pointers, p); - - _e_pointer_canvas_del(p); - - E_FREE_LIST(p->stack, _e_pointer_stack_free); - - if (p->type) eina_stringshare_del(p->type); - if (p->idle_timer) ecore_timer_del(p->idle_timer); - if (p->idle_poller) ecore_poller_del(p->idle_poller); - - p->type = NULL; - p->idle_timer = NULL; - p->idle_poller = NULL; - E_FREE(p); -} - -static void -_e_pointer_stack_free(E_Pointer_Stack *elem) -{ - if (elem->type) eina_stringshare_del(elem->type); - free(elem); -} - -static void -_e_pointer_type_set(E_Pointer *p, - const char *type) -{ - if (!p) return; - - /* Check if this pointer is already set */ - if ((p->type) && (!strcmp(p->type, type))) return; - - eina_stringshare_replace(&p->type, type); - - /* Do not set type if in "hidden mode" */ - if (!e_config->show_cursor) - { - ecore_x_window_cursor_set(p->win, 0); - return; - } - - if (p->e_cursor) - { - char cursor[1024]; - Evas_Coord x, y; - - if (!p->evas) _e_pointer_canvas_add(p); - if (p->color) - snprintf(cursor, sizeof(cursor), - "e/pointer/enlightenment/%s/color", type); + if (p->canvas) + evas_object_resize(p->pointer_image, p->w, p->h); else - snprintf(cursor, sizeof(cursor), - "e/pointer/enlightenment/%s/mono", type); - if (!e_theme_edje_object_set(p->pointer_object, - "base/theme/pointer", cursor)) - goto fallback; - edje_object_part_swallow(p->pointer_object, "e.swallow.hotspot", - p->hot_object); - edje_object_part_geometry_get(p->pointer_object, "e.swallow.hotspot", - &x, &y, NULL, NULL); - if ((p->hot.x != x) || (p->hot.y != y)) - { - p->hot.x = x; - p->hot.y = y; - } - p->hot.update = 1; - return; + evas_object_hide(p->pointer_image); } -fallback: - { - Ecore_X_Cursor cursor = 0; - - if (p->evas) _e_pointer_canvas_del(p); - if (!strcmp(type, "move")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_FLEUR); -#if 0 - else if (!strcmp(type, "resize")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_SIZING); -#endif - else if (!strcmp(type, "resize_tl")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_LEFT_CORNER); - else if (!strcmp(type, "resize_t")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_SIDE); - else if (!strcmp(type, "resize_tr")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_TOP_RIGHT_CORNER); - else if (!strcmp(type, "resize_r")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_RIGHT_SIDE); - else if (!strcmp(type, "resize_br")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER); - else if (!strcmp(type, "resize_b")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_SIDE); - else if (!strcmp(type, "resize_bl")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_BOTTOM_LEFT_CORNER); - else if (!strcmp(type, "resize_l")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_SIDE); - else if (!strcmp(type, "entry")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_XTERM); - else if (!strcmp(type, "default")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_LEFT_PTR); - else if (!strcmp(type, "plus")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_PLUS); - else if (!strcmp(type, "hand")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_HAND1); - else if (!strcmp(type, "rotate")) - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_EXCHANGE); - else - { - printf("Unknown pointer type: %s\n", type); - cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_ARROW); - } - if (!cursor) printf("X Cursor for %s is missing\n", type); - ecore_x_window_cursor_set(p->win, cursor); - if (cursor) ecore_x_cursor_free(cursor); - } } - -static void -_e_pointer_active_handle(E_Pointer *p) -{ - if (!p) return; - - /* we got some mouse event - if there was an idle timer emit an active - * signal as we WERE idle, NOW we are active */ - if (p->idle_timer) - { - ecore_timer_del(p->idle_timer); - p->idle_timer = NULL; - } - if (p->idle_poller) - { - ecore_poller_del(p->idle_poller); - p->idle_poller = NULL; - } - if (p->idle) - { - if (p->pointer_object) - edje_object_signal_emit(p->pointer_object, "e,state,mouse,active", "e"); - p->idle = 0; - } - if (e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) return; - /* and schedule a pre-idle check in 1 second if no more events happen */ - if (!e_config->idle_cursor) return; - p->idle_timer = ecore_timer_loop_add(1.0, _e_pointer_cb_idle_timer_pre, p); -} - -static Eina_Bool -_e_pointer_cb_mouse_down(void *data __UNUSED__, - int type __UNUSED__, - void *event __UNUSED__) -{ - Eina_List *l; - E_Pointer *p; - - EINA_LIST_FOREACH(_e_pointers, l, p) - { - _e_pointer_active_handle(p); - if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME) - { - if (p->pointer_object) - edje_object_signal_emit(p->pointer_object, - "e,action,mouse,down", "e"); - } - } - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_e_pointer_cb_mouse_up(void *data __UNUSED__, - int type __UNUSED__, - void *event __UNUSED__) -{ - Eina_List *l; - E_Pointer *p; - - EINA_LIST_FOREACH(_e_pointers, l, p) - { - _e_pointer_active_handle(p); - if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME) - { - if (p->pointer_object) - edje_object_signal_emit(p->pointer_object, - "e,action,mouse,up", "e"); - } - } - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_e_pointer_cb_mouse_move(void *data __UNUSED__, - int type __UNUSED__, - void *event __UNUSED__) -{ - Eina_List *l; - E_Pointer *p; - - EINA_LIST_FOREACH(_e_pointers, l, p) - { - _e_pointer_active_handle(p); - if (e_powersave_mode_get() < E_POWERSAVE_MODE_HIGH) - { - if (p->pointer_object) - edje_object_signal_emit(p->pointer_object, - "e,action,mouse,move", "e"); - } - } - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_e_pointer_cb_mouse_wheel(void *data __UNUSED__, - int type __UNUSED__, - void *event __UNUSED__) -{ - Eina_List *l; - E_Pointer *p; - - EINA_LIST_FOREACH(_e_pointers, l, p) - { - _e_pointer_active_handle(p); - if (e_powersave_mode_get() < E_POWERSAVE_MODE_EXTREME) - { - if (p->pointer_object) - edje_object_signal_emit(p->pointer_object, - "e,action,mouse,wheel", "e"); - } - } - return ECORE_CALLBACK_PASS_ON; -} - -static Eina_Bool -_e_pointer_cb_idle_timer_pre(void *data) -{ - E_Pointer *p; - int x, y; - - if (!(p = data)) return ECORE_CALLBACK_RENEW; - ecore_x_pointer_xy_get(p->win, &x, &y); - p->x = x; - p->y = y; - p->idle_timer = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_timer_wait, p); - return ECORE_CALLBACK_CANCEL; -} - -static Eina_Bool -_e_pointer_cb_idle_timer_wait(void *data) -{ - E_Pointer *p; - - if (!(p = data)) return ECORE_CALLBACK_RENEW; - if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) || - (!e_config->idle_cursor)) - { - if (p->idle_poller) ecore_poller_del(p->idle_poller); - p->idle_poller = NULL; - p->idle_timer = NULL; - return ECORE_CALLBACK_CANCEL; - } - if (!p->idle_poller) - p->idle_poller = ecore_poller_add(ECORE_POLLER_CORE, 64, - _e_pointer_cb_idle_poller, p); - p->idle_timer = NULL; - return ECORE_CALLBACK_CANCEL; -} - -static Eina_Bool -_e_pointer_cb_idle_poller(void *data) -{ - E_Pointer *p; - int x, y; - - if (!(p = data)) return ECORE_CALLBACK_RENEW; - if ((e_powersave_mode_get() >= E_POWERSAVE_MODE_MEDIUM) || - (!e_config->idle_cursor)) - { - p->idle_poller = NULL; - return ECORE_CALLBACK_CANCEL; - } - /* check if pointer actually moved since the 1 second post-mouse move idle - * pre-timer that fetches the position */ - ecore_x_pointer_xy_get(p->win, &x, &y); - if ((x != p->x) || (y != p->y)) - { - /* it moved - so we are not idle yet - record position and wait - * 4 secons more */ - p->x = x; - p->y = y; - if (p->idle) - { - if (p->pointer_object) - edje_object_signal_emit(p->pointer_object, - "e,state,mouse,active", "e"); - p->idle = 0; - } - /* use poller to check from now on */ - return ECORE_CALLBACK_RENEW; - } - /* we are idle - report it if not idle before */ - if (!p->idle) - { - if (p->pointer_object) - edje_object_signal_emit(p->pointer_object, "e,state,mouse,idle", "e"); - p->idle = 1; - } - return ECORE_CALLBACK_RENEW; -} - diff --git a/src/bin/e_pointer.h b/src/bin/e_pointer.h index f96f6ba78..d808b17d3 100644 --- a/src/bin/e_pointer.h +++ b/src/bin/e_pointer.h @@ -31,16 +31,20 @@ struct _E_Pointer unsigned char e_cursor : 1; unsigned char color : 1; unsigned char idle : 1; + unsigned char canvas : 1; Evas *evas; + E_Pixmap *pixmap; Evas_Object *pointer_object; + Evas_Object *pointer_image; Evas_Object *hot_object; int *pixels; - Ecore_X_Window win; + Ecore_Window win; int w, h; Ecore_Timer *idle_timer; Ecore_Poller *idle_poller; int x, y; + unsigned int blocks; const char *type; void *obj; @@ -54,8 +58,10 @@ struct _E_Pointer EINTERN int e_pointer_init(void); EINTERN int e_pointer_shutdown(void); -EAPI E_Pointer *e_pointer_window_new(Ecore_X_Window win, int filled); +EAPI E_Pointer *e_pointer_window_new(Ecore_Window win, int filled); EAPI void e_pointer_hide(E_Pointer *p); +EAPI E_Pointer *e_pointer_canvas_new(Evas *e, int filled); +EAPI void e_pointer_image_set(E_Pointer *p, E_Pixmap *cp, int w, int h, int hot_x, int hot_y); EAPI void e_pointer_type_push(E_Pointer *p, void *obj, const char *type); EAPI void e_pointer_type_pop(E_Pointer *p, void *obj, const char *type); EAPI void e_pointers_size_set(int size); @@ -64,5 +70,8 @@ EAPI void e_pointer_idler_before(void); EAPI void e_pointer_mode_push(void *obj, E_Pointer_Mode mode); EAPI void e_pointer_mode_pop(void *obj, E_Pointer_Mode mode); +EAPI void e_pointer_block_add(E_Pointer *p); +EAPI void e_pointer_block_del(E_Pointer *p); + #endif #endif diff --git a/src/bin/e_win.c b/src/bin/e_win.c index ba65fb1bf..89246e44d 100644 --- a/src/bin/e_win.c +++ b/src/bin/e_win.c @@ -318,9 +318,13 @@ e_win_new(E_Comp *c) win->max_aspect = 0.0; wins = eina_list_append(wins, win); -#warning FIXME WL POINTERS - if (c->man->root) - win->pointer = e_pointer_window_new(win->evas_win, 1); +#ifndef WAYLAND_ONLY + if (c->comp_type == E_PIXMAP_TYPE_X) + { + win->pointer = e_pointer_window_new(win->evas_win, 1); + win->pointer->color = c->pointer->color; + } +#endif return win; } diff --git a/src/modules/wl_desktop_shell/e_mod_main.c b/src/modules/wl_desktop_shell/e_mod_main.c index f344b904d..d9d3ff24f 100644 --- a/src/modules/wl_desktop_shell/e_mod_main.c +++ b/src/modules/wl_desktop_shell/e_mod_main.c @@ -43,6 +43,7 @@ static void _e_wl_shell_shell_surface_cb_destroy(struct wl_listener *listener, v static int _e_wl_shell_shell_surface_cb_ping_timeout(void *data); static void _e_wl_shell_render_post(void *data, Evas *e EINA_UNUSED, void *event EINA_UNUSED); +static void _e_wl_shell_shell_surface_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event); static void _e_wl_shell_shell_surface_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event); static void _e_wl_shell_shell_surface_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event); static void _e_wl_shell_shell_surface_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event); @@ -625,6 +626,8 @@ _e_wl_shell_shell_surface_create_toplevel(E_Wayland_Surface *ews) EC_CHANGED(ews->ec); /* hook object callbacks */ + evas_object_event_callback_add(ews->ec->frame, EVAS_CALLBACK_MOUSE_IN, + _e_wl_shell_shell_surface_cb_mouse_in, ews); evas_object_event_callback_add(ews->ec->frame, EVAS_CALLBACK_MOUSE_OUT, _e_wl_shell_shell_surface_cb_mouse_out, ews); evas_object_event_callback_add(ews->ec->frame, EVAS_CALLBACK_MOUSE_MOVE, @@ -686,6 +689,8 @@ _e_wl_shell_shell_surface_create_popup(E_Wayland_Surface *ews) EC_CHANGED(ews->ec); /* hook object callbacks */ + evas_object_event_callback_add(ews->ec->frame, EVAS_CALLBACK_MOUSE_IN, + _e_wl_shell_shell_surface_cb_mouse_in, ews); evas_object_event_callback_add(ews->ec->frame, EVAS_CALLBACK_MOUSE_OUT, _e_wl_shell_shell_surface_cb_mouse_out, ews); evas_object_event_callback_add(ews->ec->frame, EVAS_CALLBACK_MOUSE_MOVE, @@ -913,8 +918,10 @@ _e_wl_shell_shell_surface_unmap(E_Wayland_Surface *ews) if (ews->ec) { - evas_object_event_callback_del_full(ews->ec->frame, EVAS_CALLBACK_MOUSE_OUT, - _e_wl_shell_shell_surface_cb_mouse_out, ews); + evas_object_event_callback_del_full(ews->ec->frame, EVAS_CALLBACK_MOUSE_IN, + _e_wl_shell_shell_surface_cb_mouse_in, ews); + //evas_object_event_callback_del_full(ews->ec->frame, EVAS_CALLBACK_MOUSE_OUT, + //_e_wl_shell_shell_surface_cb_mouse_out, ews); evas_object_event_callback_del_full(ews->ec->frame, EVAS_CALLBACK_MOUSE_MOVE, _e_wl_shell_shell_surface_cb_mouse_move, ews); evas_object_event_callback_del_full(ews->ec->frame, EVAS_CALLBACK_MOUSE_UP, @@ -1122,6 +1129,14 @@ _e_wl_shell_render_post(void *data EINA_UNUSED, Evas *e EINA_UNUSED, void *event } } +static void +_e_wl_shell_shell_surface_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) +{ + E_Wayland_Surface *ews = data; + + e_pointer_block_add(ews->ec->comp->pointer); +} + static void _e_wl_shell_shell_surface_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) { @@ -1131,6 +1146,9 @@ _e_wl_shell_shell_surface_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Obj /* try to cast data to our surface structure */ if (!(ews = data)) return; + if (ews->ec->cur_mouse_action || ews->ec->border_menu) return; + if (ews->ec->comp->pointer) e_pointer_block_del(ews->ec->comp->pointer); + if (e_object_is_del(E_OBJECT(ews->ec))) return; /* try to get the pointer from this input */ if ((ptr = _e_wl_comp->input->wl.seat.pointer)) @@ -1158,6 +1176,7 @@ _e_wl_shell_shell_surface_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Ob /* try to cast data to our surface structure */ if (!(ews = data)) return; + if (ews->ec->cur_mouse_action || ews->ec->border_menu) return; /* try to get the pointer from this input */ if ((ptr = _e_wl_comp->input->wl.seat.pointer)) @@ -1186,7 +1205,7 @@ _e_wl_shell_shell_surface_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Obje /* try to cast data to our surface structure */ if (!(ews = data)) return; - if (ews->ec && ews->ec->cur_mouse_action) return; + if (ews->ec->cur_mouse_action || ews->ec->border_menu) return; /* try to get the pointer from this input */ if ((ptr = _e_wl_comp->input->wl.seat.pointer)) @@ -1220,7 +1239,7 @@ _e_wl_shell_shell_surface_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Ob /* try to cast data to our surface structure */ if (!(ews = data)) return; - if (ews->ec && ews->ec->cur_mouse_action) return; + if (ews->ec->cur_mouse_action || ews->ec->border_menu) return; /* try to get the pointer from this input */ if ((ptr = _e_wl_comp->input->wl.seat.pointer)) @@ -1273,7 +1292,7 @@ _e_wl_shell_shell_surface_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_O /* try to cast data to our surface structure */ if (!(ews = data)) return; - if (ews->ec && ews->ec->cur_mouse_action) return; + if (ews->ec->cur_mouse_action || ews->ec->border_menu) return; /* try to get the pointer from this input */ if ((ptr = _e_wl_comp->input->wl.seat.pointer)) diff --git a/src/modules/wl_fb/e_mod_main.c b/src/modules/wl_fb/e_mod_main.c index e92f52c15..85a7e607d 100644 --- a/src/modules/wl_fb/e_mod_main.c +++ b/src/modules/wl_fb/e_mod_main.c @@ -42,6 +42,7 @@ e_modapi_init(E_Module *m) e_comp_wl_init(); e_comp_canvas_init(comp); e_comp_canvas_fake_layers_init(comp); + comp->pointer = e_pointer_canvas_new(comp->evas, 1); ecore_wl_init(NULL); ecore_wl_server_mode_set(1); diff --git a/src/modules/wl_x11/e_mod_main.c b/src/modules/wl_x11/e_mod_main.c index 3545dc710..297838636 100644 --- a/src/modules/wl_x11/e_mod_main.c +++ b/src/modules/wl_x11/e_mod_main.c @@ -44,10 +44,10 @@ e_modapi_init(E_Module *m) e_xinerama_screens_set(eina_list_append(NULL, screen)); } comp->man = e_manager_new(0, comp, SCREEN_W, SCREEN_H); - comp->pointer = e_pointer_window_new(comp->man->root, 1); e_comp_wl_init(); e_comp_canvas_init(comp); e_comp_canvas_fake_layers_init(comp); + comp->pointer = e_pointer_canvas_new(comp->evas, 1); ecore_evas_callback_delete_request_set(ee, _cb_delete_request);