Each xwl_tablet_tool gets a xwl_cursor, as on wayland each of those will get an independent cursor that can be set through zwp_tablet_tool.set_cursor.
However, all tools (and the pointer) share conceptually the same VCP on Xwayland, so have cursor changes trigger a xwl_cursor update on every tool (and the pointer, again). Maybe Xwayland could keep track of the most recent device and only update that cursor to get better visual results, but this is simpler, and it's going to be odd anyway... Signed-off-by: Carlos Garnacho <carl...@gnome.org> --- hw/xwayland/xwayland-cursor.c | 56 +++++++++++++++++++++++++++++++++++++++++++ hw/xwayland/xwayland-input.c | 18 ++++++++++++++ hw/xwayland/xwayland.h | 4 ++++ 3 files changed, 78 insertions(+) diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c index 1b854bf..2a9ce61 100644 --- a/hw/xwayland/xwayland-cursor.c +++ b/hw/xwayland/xwayland-cursor.c @@ -165,11 +165,62 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) wl_surface_commit(xwl_cursor->surface); } +void +xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool) +{ + struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat; + struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor; + PixmapPtr pixmap; + CursorPtr cursor; + int stride; + + if (!xwl_seat->x_cursor) { + zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool, + xwl_tablet_tool->proximity_in_serial, + NULL, 0, 0); + return; + } + + if (xwl_cursor->frame_cb) { + xwl_cursor->needs_update = TRUE; + return; + } + + cursor = xwl_seat->x_cursor; + pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); + if (!pixmap) + return; + + stride = cursor->bits->width * 4; + if (cursor->bits->argb) + memcpy(pixmap->devPrivate.ptr, + cursor->bits->argb, cursor->bits->height * stride); + else + expand_source_and_mask(cursor, pixmap->devPrivate.ptr); + + zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool, + xwl_tablet_tool->proximity_in_serial, + xwl_cursor->surface, + xwl_seat->x_cursor->bits->xhot, + xwl_seat->x_cursor->bits->yhot); + wl_surface_attach(xwl_cursor->surface, + xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0); + wl_surface_damage(xwl_cursor->surface, 0, 0, + xwl_seat->x_cursor->bits->width, + xwl_seat->x_cursor->bits->height); + + xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface); + wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor); + + wl_surface_commit(xwl_cursor->surface); +} + static void xwl_set_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor, int x, int y) { struct xwl_seat *xwl_seat; + struct xwl_tablet_tool *xwl_tablet_tool; Bool cursor_visibility_changed; xwl_seat = device->public.devicePrivate; @@ -184,6 +235,11 @@ xwl_set_cursor(DeviceIntPtr device, xwl_seat_cursor_visibility_changed(xwl_seat); xwl_seat_set_cursor(xwl_seat); + + xorg_list_for_each_entry(xwl_tablet_tool, &xwl_seat->tablet_tools, link) { + if (xwl_tablet_tool->proximity_in_serial != 0) + xwl_tablet_tool_set_cursor(xwl_tablet_tool); + } } static void diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index f736a0a..dd972b4 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -1390,6 +1390,7 @@ tablet_tool_handle_removed(void *data, struct zwp_tablet_tool_v2 *tool) struct xwl_tablet_tool *xwl_tablet_tool = data; xorg_list_del(&xwl_tablet_tool->link); + xwl_cursor_release(&xwl_tablet_tool->cursor); zwp_tablet_tool_v2_destroy(xwl_tablet_tool->tool); free(xwl_tablet_tool); } @@ -1402,8 +1403,12 @@ tablet_tool_handle_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool, struct xwl_tablet_tool *xwl_tablet_tool = data; struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat; + xwl_tablet_tool->proximity_in_serial = serial; + //FIXME: Do we need the same NULL check used by the pointer? xwl_seat->focus_window = wl_surface_get_user_data(wl_surface); + + xwl_tablet_tool_set_cursor(xwl_tablet_tool); } static void @@ -1412,6 +1417,7 @@ tablet_tool_handle_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool) struct xwl_tablet_tool *xwl_tablet_tool = data; struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat; + xwl_tablet_tool->proximity_in_serial = 0; xwl_seat->focus_window = NULL; } @@ -1666,10 +1672,20 @@ tablet_seat_handle_add_tablet(void *data, } static void +xwl_tablet_tool_update_cursor(struct xwl_cursor *xwl_cursor) +{ + struct xwl_tablet_tool *xwl_tablet_tool = wl_container_of(xwl_cursor, + xwl_tablet_tool, + cursor); + xwl_tablet_tool_set_cursor(xwl_tablet_tool); +} + +static void tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat, struct zwp_tablet_tool_v2 *tool) { struct xwl_seat *xwl_seat = data; + struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; struct xwl_tablet_tool *xwl_tablet_tool; xwl_tablet_tool = calloc(sizeof *xwl_tablet_tool, 1); @@ -1679,6 +1695,8 @@ tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat, } xwl_tablet_tool->tool = tool; xwl_tablet_tool->xwl_seat = xwl_seat; + xwl_cursor_init(&xwl_tablet_tool->cursor, xwl_screen, + xwl_tablet_tool_update_cursor); xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools); diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index 42e973e..8ac3d1d 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -200,6 +200,7 @@ struct xwl_tablet_tool { struct xwl_seat *xwl_seat; DeviceIntPtr xdevice; + uint32_t proximity_in_serial; uint32_t x; uint32_t y; float pressure; @@ -207,6 +208,8 @@ struct xwl_tablet_tool { float tilt_y; float rotation; float slider; + + struct xwl_cursor cursor; }; struct xwl_output { @@ -228,6 +231,7 @@ Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen); struct xwl_screen *xwl_screen_get(ScreenPtr screen); +void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool); void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); void xwl_seat_destroy(struct xwl_seat *xwl_seat); -- 2.9.3 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel