aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2017-11-02 12:28:31 -0400
committerGitHub <noreply@github.com>2017-11-02 12:28:31 -0400
commit62734d05535bd0137f3239f3d7639438961868fe (patch)
treec19f95400b1529ba32148755b038e7db386c8d8e
parent2d4e02969dd5ec208bbd36adab0ae1e6fc028638 (diff)
parent900fb326f7608695a160a2ce645db94f33df7f87 (diff)
Merge pull request #380 from emersion/xwayland-root-cursor
Set xwayland root cursor
-rw-r--r--.build.yml1
-rw-r--r--.travis.yml1
-rw-r--r--include/wlr/xwayland.h6
-rw-r--r--meson.build2
-rw-r--r--rootston/input.c9
-rw-r--r--xwayland/meson.build2
-rw-r--r--xwayland/xwayland.c40
-rw-r--r--xwayland/xwm.c86
-rw-r--r--xwayland/xwm.h9
9 files changed, 147 insertions, 9 deletions
diff --git a/.build.yml b/.build.yml
index 60412f0e..7ba5559c 100644
--- a/.build.yml
+++ b/.build.yml
@@ -6,6 +6,7 @@ packages:
- mesa
- libinput
- libxkbcommon
+ - xcb-util-image
- libcap
- pixman
- clang
diff --git a/.travis.yml b/.travis.yml
index 52d6eae4..f6bbd7f4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,6 +16,7 @@ arch:
- libinput
- pixman
- libxkbcommon
+ - xcb-util-image
- libcap
script:
- "meson build"
diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h
index 2d968133..bea97394 100644
--- a/include/wlr/xwayland.h
+++ b/include/wlr/xwayland.h
@@ -12,6 +12,7 @@
#endif
struct wlr_xwm;
+struct wlr_xwayland_cursor;
struct wlr_xwayland {
pid_t pid;
@@ -25,6 +26,7 @@ struct wlr_xwayland {
struct wl_event_source *sigusr1_source;
struct wl_listener destroy_listener;
struct wlr_xwm *xwm;
+ struct wlr_xwayland_cursor *cursor;
struct {
struct wl_signal new_surface;
@@ -148,6 +150,10 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_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);
+
void wlr_xwayland_surface_activate(struct wlr_xwayland *wlr_xwayland,
struct wlr_xwayland_surface *surface, bool activated);
diff --git a/meson.build b/meson.build
index 74bb6dcd..642dc38d 100644
--- a/meson.build
+++ b/meson.build
@@ -52,6 +52,8 @@ pixman = dependency('pixman-1')
xcb = dependency('xcb')
xcb_composite = dependency('xcb-composite')
xcb_xfixes = dependency('xcb-xfixes')
+xcb_image = dependency('xcb-image')
+xcb_render = dependency('xcb-render')
xcb_icccm = dependency('xcb-icccm', required: false)
x11_xcb = dependency('x11-xcb')
libcap = dependency('libcap', required: false)
diff --git a/rootston/input.c b/rootston/input.c
index 8109d2b6..5d367a5e 100644
--- a/rootston/input.c
+++ b/rootston/input.c
@@ -4,6 +4,7 @@
#include <wlr/types/wlr_cursor.h>
#include <wlr/util/log.h>
#include <wlr/xcursor.h>
+#include <wlr/xwayland.h>
#include "rootston/server.h"
#include "rootston/config.h"
#include "rootston/input.h"
@@ -96,6 +97,14 @@ struct roots_input *input_create(struct roots_server *server,
return NULL;
}
+ if (server->desktop->xwayland != NULL) {
+ struct wlr_xcursor_image *xcursor_image = xcursor->images[0];
+ wlr_xwayland_set_cursor(server->desktop->xwayland,
+ xcursor_image->buffer, xcursor_image->width, xcursor_image->width,
+ xcursor_image->height, xcursor_image->hotspot_x,
+ xcursor_image->hotspot_y);
+ }
+
input->wl_seat = wlr_seat_create(server->wl_display, "seat0");
if (input->wl_seat == NULL) {
wlr_log(L_ERROR, "Cannot create seat");
diff --git a/xwayland/meson.build b/xwayland/meson.build
index a05ae584..e92e042c 100644
--- a/xwayland/meson.build
+++ b/xwayland/meson.build
@@ -11,6 +11,8 @@ lib_wlr_xwayland = static_library(
xcb,
xcb_composite,
xcb_xfixes,
+ xcb_image,
+ xcb_render,
xcb_icccm,
pixman,
],
diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c
index 81bac2ce..0452f04c 100644
--- a/xwayland/xwayland.c
+++ b/xwayland/xwayland.c
@@ -29,6 +29,15 @@ static inline int clearenv(void) {
}
#endif
+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 safe_close(int fd) {
if (fd >= 0) {
close(fd);
@@ -190,6 +199,14 @@ static int xserver_handle_ready(int signal_number, void *data) {
wl_event_source_remove(wlr_xwayland->sigusr1_source);
wlr_xwayland->sigusr1_source = NULL;
+ if (wlr_xwayland->cursor != NULL) {
+ struct wlr_xwayland_cursor *cur = wlr_xwayland->cursor;
+ xwm_set_cursor(wlr_xwayland->xwm, cur->pixels, cur->stride, cur->width,
+ cur->height, cur->hotspot_x, cur->hotspot_y);
+ free(cur);
+ wlr_xwayland->cursor = NULL;
+ }
+
char display_name[16];
snprintf(display_name, sizeof(display_name), ":%d", wlr_xwayland->display);
setenv("DISPLAY", display_name, true);
@@ -298,3 +315,26 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
free(wlr_xwayland);
return NULL;
}
+
+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) {
+ if (wlr_xwayland->xwm != NULL) {
+ xwm_set_cursor(wlr_xwayland->xwm, pixels, stride, width, height,
+ hotspot_x, hotspot_y);
+ return;
+ }
+
+ free(wlr_xwayland->cursor);
+
+ wlr_xwayland->cursor = calloc(1, sizeof(struct wlr_xwayland_cursor));
+ if (wlr_xwayland->cursor == NULL) {
+ return;
+ }
+ wlr_xwayland->cursor->pixels = pixels;
+ wlr_xwayland->cursor->stride = stride;
+ wlr_xwayland->cursor->width = width;
+ wlr_xwayland->cursor->height = height;
+ wlr_xwayland->cursor->hotspot_x = hotspot_x;
+ wlr_xwayland->cursor->hotspot_y = hotspot_y;
+}
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index 4930d45c..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
@@ -1035,6 +1038,9 @@ 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);
}
@@ -1097,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) {
@@ -1170,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;
}
@@ -1183,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) {
@@ -1219,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,
diff --git a/xwayland/xwm.h b/xwayland/xwm.h
index 7d30d278..547cd5eb 100644
--- a/xwayland/xwm.h
+++ b/xwayland/xwm.h
@@ -1,5 +1,7 @@
#ifndef XWAYLAND_INTERNALS_H
#define XWAYLAND_INTERNALS_H
+
+#include <xcb/render.h>
#include <wayland-server-core.h>
#include <wlr/xwayland.h>
@@ -49,6 +51,8 @@ struct wlr_xwm {
xcb_window_t window;
xcb_visualid_t visual_id;
xcb_colormap_t colormap;
+ xcb_render_pictformat_t render_format_id;
+ xcb_cursor_t cursor;
struct wlr_xwayland_surface *focus_surface;
@@ -60,8 +64,11 @@ struct wlr_xwm {
struct wl_listener compositor_surface_create;
};
+struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland);
+
void xwm_destroy(struct wlr_xwm *xwm);
-struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland);
+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);
#endif