redo e_pointer to support xwayland cursors

this requires that both canvas cursors and window cursors be present for the same
E_Pointer object, even though only the canvas cursor is actually visible

 #kansas
This commit is contained in:
Mike Blumenkrantz 2015-07-09 14:42:55 -04:00
parent cc5aa9153d
commit 20d281d9d3
3 changed files with 82 additions and 76 deletions

View File

@ -5183,6 +5183,8 @@ _e_comp_x_setup(Ecore_X_Window root, int w, int h)
e_pointer_type_push(e_comp->pointer, e_comp->pointer, "default");
ecore_x_icccm_state_set(ecore_evas_window_get(e_comp->ee), ECORE_X_WINDOW_STATE_HINT_NORMAL);
}
else
e_comp->pointer->win = e_comp->root;
_e_comp_x_manage_windows();
{

View File

@ -55,12 +55,12 @@ _e_pointer_cb_idle_poller(void *data)
return ECORE_CALLBACK_CANCEL;
}
#ifndef HAVE_WAYLAND_ONLY
if (!ptr->canvas)
ecore_x_pointer_xy_get(ptr->win, &x, &y);
else
#endif
if (ptr->canvas)
ecore_evas_pointer_xy_get(ptr->ee, &x, &y);
#ifndef HAVE_WAYLAND_ONLY
else
ecore_x_pointer_xy_get(ptr->win, &x, &y);
#endif
if ((ptr->x != x) || (ptr->y != y))
{
@ -103,12 +103,12 @@ _e_pointer_cb_idle_pre(void *data)
if (!(ptr = data)) return ECORE_CALLBACK_RENEW;
#ifndef HAVE_WAYLAND_ONLY
if (!ptr->canvas)
ecore_x_pointer_xy_get(ptr->win, &ptr->x, &ptr->y);
else
#endif
if (ptr->canvas)
ecore_evas_pointer_xy_get(ptr->ee, &ptr->x, &ptr->y);
#ifndef HAVE_WAYLAND_ONLY
else
ecore_x_pointer_xy_get(ptr->win, &ptr->x, &ptr->y);
#endif
ptr->idle_tmr = ecore_timer_loop_add(4.0, _e_pointer_cb_idle_wait, ptr);
@ -209,10 +209,9 @@ _e_pointer_cb_mouse_wheel(void *data EINA_UNUSED, int type EINA_UNUSED, void *ev
static void
_e_pointer_cb_hot_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
E_Pointer *ptr;
E_Pointer *ptr = data;
int x = 0, y = 0;
if (!(ptr = data)) return;
if (!ptr->e_cursor) return;
if (!evas_object_visible_get(ptr->o_ptr)) return;
edje_object_part_geometry_get(ptr->o_ptr, "e.swallow.hotspot",
@ -223,22 +222,40 @@ _e_pointer_cb_hot_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA
static void
_e_pointer_cb_hot_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
E_Pointer *ptr;
E_Pointer *ptr = data;
int x = 0, y = 0;
if (!(ptr = data)) return;
if (!ptr->e_cursor) return;
edje_object_part_geometry_get(ptr->o_ptr, "e.swallow.hotspot",
&x, &y, NULL, NULL);
_e_pointer_hot_update(ptr, x, y);
}
static void
_e_pointer_pointer_canvas_init(E_Pointer *ptr, Evas *e, Evas_Object **o_ptr, Evas_Object **o_hot)
{
/* create pointer object */
*o_ptr = edje_object_add(e);
/* create hotspot object */
*o_hot = evas_object_rectangle_add(e);
evas_object_color_set(*o_hot, 0, 0, 0, 0);
evas_object_event_callback_add(*o_hot, EVAS_CALLBACK_MOVE,
_e_pointer_cb_hot_move, ptr);
evas_object_event_callback_add(*o_hot, EVAS_CALLBACK_SHOW,
_e_pointer_cb_hot_show, ptr);
evas_object_move(*o_ptr, 0, 0);
evas_object_resize(*o_ptr, ptr->w, ptr->h);
}
static void
_e_pointer_canvas_del(E_Pointer *ptr)
{
E_FREE_FUNC(ptr->o_hot, evas_object_del);
E_FREE_FUNC(ptr->o_ptr, evas_object_del);
if (ptr->evas) evas_free(ptr->evas);
ptr->evas = NULL;
E_FREE_FUNC(ptr->buffer_o_hot, evas_object_del);
E_FREE_FUNC(ptr->buffer_o_ptr, evas_object_del);
E_FREE_FUNC(ptr->buffer_evas, evas_free);
E_FREE(ptr->pixels);
}
@ -249,19 +266,19 @@ _e_pointer_canvas_add(E_Pointer *ptr)
int method = 0;
/* try to create new canvas */
if (!(ptr->evas = evas_new())) goto err;
if (!(ptr->buffer_evas = evas_new())) goto err;
method = evas_render_method_lookup("buffer");
evas_output_method_set(ptr->evas, method);
evas_output_size_set(ptr->evas, ptr->w, ptr->h);
evas_output_viewport_set(ptr->evas, 0, 0, ptr->w, ptr->h);
evas_output_method_set(ptr->buffer_evas, method);
evas_output_size_set(ptr->buffer_evas, ptr->w, ptr->h);
evas_output_viewport_set(ptr->buffer_evas, 0, 0, ptr->w, ptr->h);
/* try to allocate space for pixels */
if (!(ptr->pixels = malloc(ptr->w * ptr->h * sizeof(int))))
goto err;
/* try to get the buffer engine info */
einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ptr->evas);
einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ptr->buffer_evas);
if (!einfo) goto err;
/* fill in buffer engine info */
@ -274,23 +291,15 @@ _e_pointer_canvas_add(E_Pointer *ptr)
einfo->info.func.free_update_region = NULL;
/* set buffer engine info */
evas_engine_info_set(ptr->evas, (Evas_Engine_Info *)einfo);
/* create pointer object */
ptr->o_ptr = edje_object_add(ptr->evas);
/* create hotspot object */
ptr->o_hot = evas_object_rectangle_add(ptr->evas);
evas_object_color_set(ptr->o_hot, 0, 0, 0, 0);
evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_MOVE,
_e_pointer_cb_hot_move, ptr);
evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_SHOW,
_e_pointer_cb_hot_show, ptr);
evas_object_move(ptr->o_ptr, 0, 0);
evas_object_resize(ptr->o_ptr, ptr->w, ptr->h);
evas_engine_info_set(ptr->buffer_evas, (Evas_Engine_Info *)einfo);
_e_pointer_pointer_canvas_init(ptr, ptr->buffer_evas, &ptr->buffer_o_ptr, &ptr->buffer_o_hot);
if (!ptr->evas)
{
ptr->evas = ptr->buffer_evas;
ptr->o_ptr = ptr->buffer_o_ptr;
ptr->o_hot = ptr->buffer_o_hot;
}
return;
err:
@ -305,20 +314,20 @@ _e_pointer_canvas_resize(E_Pointer *ptr, int w, int h)
if ((ptr->w == w) && (ptr->h == h)) return;
ptr->w = w;
ptr->h = h;
evas_output_size_set(ptr->evas, w, h);
evas_output_viewport_set(ptr->evas, 0, 0, w, h);
evas_output_size_set(ptr->buffer_evas, w, h);
evas_output_viewport_set(ptr->buffer_evas, 0, 0, w, h);
ptr->pixels = realloc(ptr->pixels, (ptr->w * ptr->h * sizeof(int)));
einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ptr->evas);
einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ptr->buffer_evas);
EINA_SAFETY_ON_NULL_RETURN(einfo);
einfo->info.dest_buffer = ptr->pixels;
einfo->info.dest_buffer_row_bytes = (ptr->w * sizeof(int));
evas_engine_info_set(ptr->evas, (Evas_Engine_Info *)einfo);
evas_engine_info_set(ptr->buffer_evas, (Evas_Engine_Info *)einfo);
evas_object_move(ptr->o_ptr, 0, 0);
evas_object_resize(ptr->o_ptr, ptr->w, ptr->h);
evas_object_move(ptr->buffer_o_ptr, 0, 0);
evas_object_resize(ptr->buffer_o_ptr, ptr->w, ptr->h);
}
static void
@ -340,7 +349,7 @@ _e_pointer_cb_free(E_Pointer *ptr)
E_FREE_FUNC(ptr->idle_tmr, ecore_timer_del);
E_FREE_FUNC(ptr->idle_poll, ecore_poller_del);
if (!ptr->canvas) _e_pointer_canvas_del(ptr);
if (ptr->buffer_evas) _e_pointer_canvas_del(ptr);
free(ptr);
}
@ -366,7 +375,7 @@ _e_pointer_type_set(E_Pointer *ptr, const char *type)
int x = 0, y = 0;
/* create a pointer canvas if we need to */
if ((!ptr->evas) && (!ptr->canvas)) _e_pointer_canvas_add(ptr);
if ((!ptr->buffer_evas) && ptr->win) _e_pointer_canvas_add(ptr);
if (ptr->color)
snprintf(cursor, sizeof(cursor),
@ -378,8 +387,11 @@ _e_pointer_type_set(E_Pointer *ptr, const char *type)
/* try to set the edje object theme */
if (!e_theme_edje_object_set(ptr->o_ptr, "base/theme/pointer", cursor))
goto fallback;
edje_object_part_swallow(ptr->o_ptr, "e.swallow.hotspot", ptr->o_hot);
if (ptr->buffer_o_ptr && (ptr->buffer_o_ptr != ptr->o_ptr))
{
e_theme_edje_object_set(ptr->buffer_o_ptr, "base/theme/pointer", cursor);
edje_object_part_swallow(ptr->buffer_o_ptr, "e.swallow.hotspot", ptr->buffer_o_hot);
}
edje_object_part_geometry_get(ptr->o_ptr, "e.swallow.hotspot",
&x, &y, NULL, NULL);
@ -394,8 +406,9 @@ _e_pointer_type_set(E_Pointer *ptr, const char *type)
}
fallback:
if ((ptr->evas) && (!ptr->canvas)) _e_pointer_canvas_del(ptr);
if (ptr->buffer_evas) _e_pointer_canvas_del(ptr);
#ifndef HAVE_WAYLAND_ONLY
if (!e_comp_util_has_x()) return;
Ecore_X_Cursor cursor = 0;
if (!strcmp(type, "move"))
@ -439,7 +452,6 @@ fallback:
ecore_x_window_cursor_set(ptr->win, cursor);
if (cursor) ecore_x_cursor_free(cursor);
#endif
return;
}
EINTERN int
@ -510,18 +522,7 @@ e_pointer_canvas_new(Ecore_Evas *ee, Eina_Bool filled)
ptr->ee = ee;
ptr->evas = ecore_evas_get(ee);
ptr->o_ptr = edje_object_add(ptr->evas);
ptr->o_hot = evas_object_rectangle_add(ptr->evas);
evas_object_color_set(ptr->o_hot, 0, 0, 0, 0);
evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_MOVE,
_e_pointer_cb_hot_move, ptr);
evas_object_event_callback_add(ptr->o_hot, EVAS_CALLBACK_SHOW,
_e_pointer_cb_hot_show, ptr);
evas_object_move(ptr->o_ptr, 0, 0);
evas_object_resize(ptr->o_ptr, ptr->w, ptr->h);
_e_pointer_pointer_canvas_init(ptr, ptr->evas, &ptr->o_ptr, &ptr->o_hot);
/* set pointer default type */
if (filled) e_pointer_type_push(ptr, ptr, "default");
@ -545,30 +546,31 @@ e_pointers_size_set(int size)
EINA_LIST_FOREACH(_ptrs, l, ptr)
{
if ((ptr->w == size) && (ptr->h == size)) continue;
if ((ptr->evas) && (!ptr->canvas))
if (ptr->buffer_evas)
_e_pointer_canvas_resize(ptr, size, size);
else if (ptr->canvas)
if (ptr->canvas)
{
ptr->w = size;
ptr->h = size;
evas_object_resize(ptr->o_ptr, size, size);
}
#ifndef HAVE_WAYLAND_ONLY
ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
#endif
}
#ifndef HAVE_WAYLAND_ONLY
if (e_comp_util_has_x())
ecore_x_cursor_size_set(e_config->cursor_size * 3 / 4);
#endif
}
E_API void
e_pointer_hide(E_Pointer *ptr)
{
if ((ptr->evas) && (!ptr->canvas))
if (ptr->buffer_evas)
_e_pointer_canvas_del(ptr);
else if (ptr->canvas)
if (ptr->canvas)
evas_object_hide(ptr->o_ptr);
#ifndef HAVE_WAYLAND_ONLY
ecore_x_window_cursor_set(ptr->win, 0);
if (ptr->win)
ecore_x_window_cursor_set(ptr->win, 0);
#endif
}
@ -720,16 +722,16 @@ e_pointer_idler_before(void)
EINA_LIST_FOREACH(_ptrs, l, ptr)
{
if ((!ptr->e_cursor) || (!ptr->evas)) continue;
if ((!ptr->e_cursor) || (!ptr->buffer_evas)) continue;
if (ptr->hot.update)
_e_pointer_type_set(ptr, ptr->type);
if (!ptr->canvas)
if (ptr->buffer_evas)
{
Eina_List *updates;
if ((updates = evas_render_updates(ptr->evas)))
if ((updates = evas_render_updates(ptr->buffer_evas)))
{
#ifndef HAVE_WAYLAND_ONLY
Ecore_X_Cursor cur;

View File

@ -29,10 +29,12 @@ struct _E_Pointer
Evas *evas;
Ecore_Evas *ee;
Evas *buffer_evas;
Evas_Object *o_ptr;
Evas_Object *o_hot;
Evas_Object *buffer_o_ptr;
Evas_Object *buffer_o_hot;
// E_Pixmap *pixmap;
Ecore_Window win;
int *pixels;