diff options
Diffstat (limited to 'xwayland/xwm.c')
-rw-r--r-- | xwayland/xwm.c | 88 |
1 files changed, 80 insertions, 8 deletions
diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 15a23797..f011587e 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -5,9 +5,12 @@ #include <unistd.h> #include <xcb/composite.h> #include <xcb/xfixes.h> +#include <xcb/xcb_image.h> +#include <xcb/render.h> #include "wlr/util/log.h" #include "wlr/types/wlr_surface.h" #include "wlr/xwayland.h" +#include "wlr/xcursor.h" #include "xwm.h" #ifdef HAS_XCB_ICCCM @@ -1027,12 +1030,17 @@ void wlr_xwayland_surface_close(struct wlr_xwayland *wlr_xwayland, } else { xcb_kill_client(xwm->xcb_conn, xsurface->window_id); } + + xcb_flush(xwm->xcb_conn); } void xwm_destroy(struct wlr_xwm *xwm) { if (!xwm) { return; } + if (xwm->cursor) { + xcb_free_cursor(xwm->xcb_conn, xwm->cursor); + } if (xwm->event_source) { wl_event_source_remove(xwm->event_source); } @@ -1095,7 +1103,6 @@ static void xwm_get_resources(struct wlr_xwm *xwm) { xfixes_reply->major_version, xfixes_reply->minor_version); free(xfixes_reply); - } static void xwm_create_wm_window(struct wlr_xwm *xwm) { @@ -1168,7 +1175,7 @@ static void xwm_get_visual_and_colormap(struct wlr_xwm *xwm) { } if (visualtype == NULL) { - wlr_log(L_DEBUG, "no 32 bit visualtype\n"); + wlr_log(L_DEBUG, "No 32 bit visualtype\n"); return; } @@ -1181,6 +1188,71 @@ static void xwm_get_visual_and_colormap(struct wlr_xwm *xwm) { xwm->visual_id); } +static void xwm_get_render_format(struct wlr_xwm *xwm) { + xcb_render_query_pict_formats_cookie_t cookie = + xcb_render_query_pict_formats(xwm->xcb_conn); + xcb_render_query_pict_formats_reply_t *reply = + xcb_render_query_pict_formats_reply(xwm->xcb_conn, cookie, NULL); + xcb_render_pictforminfo_iterator_t iter = + xcb_render_query_pict_formats_formats_iterator(reply); + xcb_render_pictforminfo_t *format = NULL; + while (iter.rem > 0) { + if (iter.data->depth == 32) { + format = iter.data; + break; + } + + xcb_render_pictforminfo_next(&iter); + } + + if (format == NULL) { + wlr_log(L_DEBUG, "No 32 bit render format"); + return; + } + + xwm->render_format_id = format->id; +} + +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) { + if (!xwm->render_format_id) { + wlr_log(L_ERROR, "Cannot set xwm cursor: no render format available"); + return; + } + if (xwm->cursor) { + xcb_free_cursor(xwm->xcb_conn, xwm->cursor); + } + + stride *= 4; + 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_render_picture_t pic = xcb_generate_id(xwm->xcb_conn); + xcb_render_create_picture(xwm->xcb_conn, pic, pix, xwm->render_format_id, + 0, 0); + + xcb_gcontext_t gc = xcb_generate_id(xwm->xcb_conn); + 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), + pixels); + xcb_free_gc(xwm->xcb_conn, gc); + + xwm->cursor = xcb_generate_id(xwm->xcb_conn); + xcb_render_create_cursor(xwm->xcb_conn, xwm->cursor, pic, hotspot_x, + hotspot_y); + xcb_free_pixmap(xwm->xcb_conn, pix); + + uint32_t values[] = {xwm->cursor}; + xcb_change_window_attributes(xwm->xcb_conn, xwm->screen->root, + XCB_CW_CURSOR, values); + xcb_flush(xwm->xcb_conn); +} + struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { struct wlr_xwm *xwm = calloc(1, sizeof(struct wlr_xwm)); if (xwm == NULL) { @@ -1217,16 +1289,16 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { xwm_get_resources(xwm); xwm_get_visual_and_colormap(xwm); + xwm_get_render_format(xwm); - uint32_t values[1]; - values[0] = + uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | - XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | - XCB_EVENT_MASK_PROPERTY_CHANGE; - + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_PROPERTY_CHANGE, + }; xcb_change_window_attributes(xwm->xcb_conn, xwm->screen->root, - XCB_CW_EVENT_MASK /* | XCB_CW_CURSOR */, + XCB_CW_EVENT_MASK, values); xcb_composite_redirect_subwindows(xwm->xcb_conn, |