From d3ee69f76bbc8b71a79840c047fa7a6144ddc628 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 11 Nov 2018 14:51:22 +1300 Subject: [PATCH] backend/x11: Hide cursor with Xfixes --- backend/x11/backend.c | 36 ++++++++++++++++++++++-------------- backend/x11/input_device.c | 31 +++++++++++++++++++++++++++++++ backend/x11/meson.build | 1 + backend/x11/output.c | 8 +++----- include/backend/x11.h | 5 ++--- 5 files changed, 59 insertions(+), 22 deletions(-) diff --git a/backend/x11/backend.c b/backend/x11/backend.c index ce747976..38715631 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -106,15 +107,6 @@ static bool backend_start(struct wlr_backend *backend) { struct wlr_x11_backend *x11 = get_x11_backend_from_backend(backend); x11->started = true; - // create a blank cursor - xcb_pixmap_t pix = xcb_generate_id(x11->xcb); - xcb_create_pixmap(x11->xcb, 1, pix, x11->screen->root, 1, 1); - - x11->cursor = xcb_generate_id(x11->xcb); - xcb_create_cursor(x11->xcb, x11->cursor, pix, pix, 0, 0, 0, 0, 0, 0, - 0, 0); - xcb_free_pixmap(x11->xcb, pix); - wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard_dev); for (size_t i = 0; i < x11->requested_outputs; ++i) { @@ -148,9 +140,6 @@ static void backend_destroy(struct wlr_backend *backend) { wlr_renderer_destroy(x11->renderer); wlr_egl_finish(&x11->egl); - if (x11->cursor) { - xcb_free_cursor(x11->xcb, x11->cursor); - } if (x11->xlib_conn) { XCloseDisplay(x11->xlib_conn); } @@ -233,8 +222,27 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, } } - const xcb_query_extension_reply_t *ext = - xcb_get_extension_data(x11->xcb, &xcb_input_id); + const xcb_query_extension_reply_t *ext; + + ext = xcb_get_extension_data(x11->xcb, &xcb_xfixes_id); + if (!ext || !ext->present) { + wlr_log(WLR_ERROR, "X11 does not support Xfixes extension"); + goto error_display; + } + + xcb_xfixes_query_version_cookie_t fixes_cookie = + xcb_xfixes_query_version(x11->xcb, 4, 0); + xcb_xfixes_query_version_reply_t *fixes_reply = + xcb_xfixes_query_version_reply(x11->xcb, fixes_cookie, NULL); + + if (!fixes_reply || fixes_reply->major_version < 4) { + wlr_log(WLR_ERROR, "X11 does not support required Xfixes version"); + free(fixes_reply); + goto error_display; + } + free(fixes_reply); + + ext = xcb_get_extension_data(x11->xcb, &xcb_input_id); if (!ext || !ext->present) { wlr_log(WLR_ERROR, "X11 does not support Xinput extension"); goto error_display; diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index 08d982e6..a50f478a 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -9,6 +9,7 @@ #endif #include +#include #include #include @@ -164,6 +165,36 @@ void handle_x11_xinput_event(struct wlr_x11_backend *x11, x11->time = ev->time; break; } + case XCB_INPUT_ENTER: { + xcb_input_enter_event_t *ev = (xcb_input_enter_event_t *)event; + + output = get_x11_output_from_window_id(x11, ev->event); + if (!output) { + return; + } + + if (!output->cursor_hidden) { + xcb_xfixes_hide_cursor(x11->xcb, output->win); + xcb_flush(x11->xcb); + output->cursor_hidden = true; + } + break; + } + case XCB_INPUT_LEAVE: { + xcb_input_leave_event_t *ev = (xcb_input_leave_event_t *)event; + + output = get_x11_output_from_window_id(x11, ev->event); + if (!output) { + return; + } + + if (output->cursor_hidden) { + xcb_xfixes_show_cursor(x11->xcb, output->win); + xcb_flush(x11->xcb); + output->cursor_hidden = false; + } + break; + } } } diff --git a/backend/x11/meson.build b/backend/x11/meson.build index d9fd8d91..19e873ab 100644 --- a/backend/x11/meson.build +++ b/backend/x11/meson.build @@ -3,6 +3,7 @@ x11_required = [ 'x11-xcb', 'xcb', 'xcb-xinput', + 'xcb-xfixes', ] foreach lib : x11_required diff --git a/backend/x11/output.c b/backend/x11/output.c index ba70d5cb..6f98c590 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -168,7 +168,9 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { XCB_INPUT_XI_EVENT_MASK_KEY_RELEASE | XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS | XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE | - XCB_INPUT_XI_EVENT_MASK_MOTION, + XCB_INPUT_XI_EVENT_MASK_MOTION | + XCB_INPUT_XI_EVENT_MASK_ENTER | + XCB_INPUT_XI_EVENT_MASK_LEAVE, }; xcb_input_xi_select_events(x11->xcb, output->win, 1, &xinput_mask.head); @@ -190,10 +192,6 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { strlen(title), title); } - uint32_t cursor_values[] = { x11->cursor }; - xcb_change_window_attributes(x11->xcb, output->win, XCB_CW_CURSOR, - cursor_values); - xcb_map_window(x11->xcb, output->win); xcb_flush(x11->xcb); diff --git a/include/backend/x11.h b/include/backend/x11.h index 94de129f..1a8341f6 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -33,6 +33,8 @@ struct wlr_x11_output { struct wl_event_source *frame_timer; int frame_delay; + + bool cursor_hidden; }; struct wlr_x11_backend { @@ -64,9 +66,6 @@ struct wlr_x11_backend { // The time we last received an event xcb_timestamp_t time; - // A blank cursor - xcb_cursor_t cursor; - uint8_t xinput_opcode; struct wl_listener display_destroy;