backend/x11: Hide cursor with Xfixes

This commit is contained in:
Scott Anderson 2018-11-11 14:51:22 +13:00
parent 70ae76304e
commit d3ee69f76b
5 changed files with 59 additions and 22 deletions

View File

@ -12,6 +12,7 @@
#include <X11/Xlib-xcb.h> #include <X11/Xlib-xcb.h>
#include <wayland-server.h> #include <wayland-server.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xfixes.h>
#include <xcb/xinput.h> #include <xcb/xinput.h>
#include <wlr/backend/interface.h> #include <wlr/backend/interface.h>
@ -106,15 +107,6 @@ static bool backend_start(struct wlr_backend *backend) {
struct wlr_x11_backend *x11 = get_x11_backend_from_backend(backend); struct wlr_x11_backend *x11 = get_x11_backend_from_backend(backend);
x11->started = true; 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); wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard_dev);
for (size_t i = 0; i < x11->requested_outputs; ++i) { 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_renderer_destroy(x11->renderer);
wlr_egl_finish(&x11->egl); wlr_egl_finish(&x11->egl);
if (x11->cursor) {
xcb_free_cursor(x11->xcb, x11->cursor);
}
if (x11->xlib_conn) { if (x11->xlib_conn) {
XCloseDisplay(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 = const xcb_query_extension_reply_t *ext;
xcb_get_extension_data(x11->xcb, &xcb_input_id);
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) { if (!ext || !ext->present) {
wlr_log(WLR_ERROR, "X11 does not support Xinput extension"); wlr_log(WLR_ERROR, "X11 does not support Xinput extension");
goto error_display; goto error_display;

View File

@ -9,6 +9,7 @@
#endif #endif
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xfixes.h>
#include <xcb/xinput.h> #include <xcb/xinput.h>
#include <wlr/interfaces/wlr_input_device.h> #include <wlr/interfaces/wlr_input_device.h>
@ -164,6 +165,36 @@ void handle_x11_xinput_event(struct wlr_x11_backend *x11,
x11->time = ev->time; x11->time = ev->time;
break; 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;
}
} }
} }

View File

@ -3,6 +3,7 @@ x11_required = [
'x11-xcb', 'x11-xcb',
'xcb', 'xcb',
'xcb-xinput', 'xcb-xinput',
'xcb-xfixes',
] ]
foreach lib : x11_required foreach lib : x11_required

View File

@ -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_KEY_RELEASE |
XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS | XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS |
XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE | 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); 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); 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_map_window(x11->xcb, output->win);
xcb_flush(x11->xcb); xcb_flush(x11->xcb);

View File

@ -33,6 +33,8 @@ struct wlr_x11_output {
struct wl_event_source *frame_timer; struct wl_event_source *frame_timer;
int frame_delay; int frame_delay;
bool cursor_hidden;
}; };
struct wlr_x11_backend { struct wlr_x11_backend {
@ -64,9 +66,6 @@ struct wlr_x11_backend {
// The time we last received an event // The time we last received an event
xcb_timestamp_t time; xcb_timestamp_t time;
// A blank cursor
xcb_cursor_t cursor;
uint8_t xinput_opcode; uint8_t xinput_opcode;
struct wl_listener display_destroy; struct wl_listener display_destroy;