diff --git a/include/wlr/xwayland/xwayland.h b/include/wlr/xwayland/xwayland.h index 1c52b3558..c3704aad1 100644 --- a/include/wlr/xwayland/xwayland.h +++ b/include/wlr/xwayland/xwayland.h @@ -17,6 +17,7 @@ #include struct wlr_box; +struct wlr_buffer; struct wlr_xwm; struct wlr_data_source; struct wlr_drag; @@ -41,7 +42,6 @@ struct wlr_xwayland { bool own_server; struct wlr_xwm *xwm; struct wlr_xwayland_shell_v1 *shell_v1; - struct wlr_xwayland_cursor *cursor; // Value the DISPLAY environment variable should be set to by the compositor const char *display_name; @@ -67,6 +67,11 @@ struct wlr_xwayland { void *data; struct { + struct wlr_buffer *cursor_buffer; + struct { + int32_t x, y; + } cursor_hotspot; + struct wl_listener server_start; struct wl_listener server_ready; struct wl_listener server_destroy; @@ -279,8 +284,7 @@ struct wlr_xwayland *wlr_xwayland_create_with_server(struct wl_display *display, void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland); void wlr_xwayland_set_cursor(struct wlr_xwayland *wlr_xwayland, - uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height, - int32_t hotspot_x, int32_t hotspot_y); + struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y); void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *surface, bool activated); diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 73f440d29..302518d39 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -169,8 +169,8 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd); void xwm_destroy(struct wlr_xwm *xwm); -void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, - uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y); +void xwm_set_cursor(struct wlr_xwm *xwm, struct wlr_buffer *buffer, + int32_t hotspot_x, int32_t hotspot_y); int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event); int xwm_handle_selection_client_message(struct wlr_xwm *xwm, diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index 3aa47bac2..39ca822dc 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -8,21 +8,13 @@ #include #include #include +#include #include #include #include #include #include "xwayland/xwm.h" -struct wlr_xwayland_cursor { - uint8_t *pixels; - uint32_t stride; - uint32_t width; - uint32_t height; - int32_t hotspot_x; - int32_t hotspot_y; -}; - static void handle_server_destroy(struct wl_listener *listener, void *data) { struct wlr_xwayland *xwayland = wl_container_of(listener, xwayland, server_destroy); @@ -53,10 +45,9 @@ static void xwayland_mark_ready(struct wlr_xwayland *xwayland) { xwm_set_seat(xwayland->xwm, xwayland->seat); } - if (xwayland->cursor != NULL) { - struct wlr_xwayland_cursor *cur = xwayland->cursor; - xwm_set_cursor(xwayland->xwm, cur->pixels, cur->stride, cur->width, - cur->height, cur->hotspot_x, cur->hotspot_y); + if (xwayland->cursor_buffer != NULL) { + xwm_set_cursor(xwayland->xwm, xwayland->cursor_buffer, + xwayland->cursor_hotspot.x, xwayland->cursor_hotspot.y); } wl_signal_emit_mutable(&xwayland->events.ready, NULL); @@ -95,7 +86,7 @@ void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) { wl_list_remove(&xwayland->server_start.link); wl_list_remove(&xwayland->server_ready.link); wl_list_remove(&xwayland->shell_destroy.link); - free(xwayland->cursor); + wlr_buffer_unlock(xwayland->cursor_buffer); wlr_xwayland_set_seat(xwayland, NULL); if (xwayland->own_server) { @@ -181,26 +172,16 @@ error_shell_v1: } void wlr_xwayland_set_cursor(struct wlr_xwayland *xwayland, - uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height, - int32_t hotspot_x, int32_t hotspot_y) { + struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y) { if (xwayland->xwm != NULL) { - xwm_set_cursor(xwayland->xwm, pixels, stride, width, height, - hotspot_x, hotspot_y); + xwm_set_cursor(xwayland->xwm, buffer, hotspot_x, hotspot_y); return; } - free(xwayland->cursor); - - xwayland->cursor = calloc(1, sizeof(*xwayland->cursor)); - if (xwayland->cursor == NULL) { - return; - } - xwayland->cursor->pixels = pixels; - xwayland->cursor->stride = stride; - xwayland->cursor->width = width; - xwayland->cursor->height = height; - xwayland->cursor->hotspot_x = hotspot_x; - xwayland->cursor->hotspot_y = hotspot_y; + wlr_buffer_unlock(xwayland->cursor_buffer); + xwayland->cursor_buffer = wlr_buffer_lock(xwayland->cursor_buffer); + xwayland->cursor_hotspot.x = hotspot_x; + xwayland->cursor_hotspot.y = hotspot_y; } static void xwayland_handle_seat_destroy(struct wl_listener *listener, diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 2bb4e4c64..08ce04394 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -1,6 +1,8 @@ #include +#include #include #include +#include #include #include #include @@ -2487,8 +2489,8 @@ static void xwm_get_render_format(struct wlr_xwm *xwm) { free(reply); } -void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, - uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y) { +void xwm_set_cursor(struct wlr_xwm *xwm, struct wlr_buffer *buffer, + int32_t hotspot_x, int32_t hotspot_y) { if (!xwm->render_format_id) { wlr_log(WLR_ERROR, "Cannot set xwm cursor: no render format available"); return; @@ -2497,11 +2499,24 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, xcb_free_cursor(xwm->xcb_conn, xwm->cursor); } + void *pixels = NULL; + uint32_t format = DRM_FORMAT_INVALID; + size_t stride = 0; + if (!wlr_buffer_begin_data_ptr_access(buffer, WLR_BUFFER_DATA_PTR_ACCESS_READ, + &pixels, &format, &stride)) { + return; + } + + if (format != DRM_FORMAT_ARGB8888) { + wlr_buffer_end_data_ptr_access(buffer); + wlr_log(WLR_ERROR, "Only ARGB8888 is supported for Xwayland cursors"); + return; + } int depth = 32; xcb_pixmap_t pix = xcb_generate_id(xwm->xcb_conn); - xcb_create_pixmap(xwm->xcb_conn, depth, pix, xwm->screen->root, width, - height); + xcb_create_pixmap(xwm->xcb_conn, depth, pix, xwm->screen->root, buffer->width, + buffer->height); xcb_render_picture_t pic = xcb_generate_id(xwm->xcb_conn); xcb_render_create_picture(xwm->xcb_conn, pic, pix, xwm->render_format_id, @@ -2511,10 +2526,12 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, xcb_create_gc(xwm->xcb_conn, gc, pix, 0, NULL); xcb_put_image(xwm->xcb_conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pix, gc, - width, height, 0, 0, 0, depth, stride * height * sizeof(uint8_t), + buffer->width, buffer->height, 0, 0, 0, depth, stride * buffer->height, pixels); xcb_free_gc(xwm->xcb_conn, gc); + wlr_buffer_end_data_ptr_access(buffer); + xwm->cursor = xcb_generate_id(xwm->xcb_conn); xcb_render_create_cursor(xwm->xcb_conn, xwm->cursor, pic, hotspot_x, hotspot_y);