aboutsummaryrefslogtreecommitdiff
path: root/xwayland/xwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'xwayland/xwm.c')
-rw-r--r--xwayland/xwm.c88
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,