diff options
| author | emersion <contact@emersion.fr> | 2018-11-13 07:53:43 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-13 07:53:43 +0100 | 
| commit | df7d4a71fb52d47279a93ee398220ff63d916ab7 (patch) | |
| tree | 29d08a6cfdd92ed2b12ebf1139164fbb79f7ce78 | |
| parent | 4aff85cc8e6f90e60522a7a830424e41a6f06b77 (diff) | |
| parent | d3ee69f76bbc8b71a79840c047fa7a6144ddc628 (diff) | |
| download | wlroots-df7d4a71fb52d47279a93ee398220ff63d916ab7.tar.xz | |
Merge pull request #1368 from ascent12/x11_backend
X11 backend improvements
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | backend/x11/backend.c | 183 | ||||
| -rw-r--r-- | backend/x11/input_device.c | 261 | ||||
| -rw-r--r-- | backend/x11/meson.build | 15 | ||||
| -rw-r--r-- | backend/x11/output.c | 57 | ||||
| -rw-r--r-- | include/backend/x11.h | 26 | ||||
| -rw-r--r-- | include/wlr/backend/x11.h | 2 | ||||
| -rw-r--r-- | include/wlr/config.h.in | 1 | ||||
| -rw-r--r-- | meson.build | 1 | ||||
| -rw-r--r-- | meson_options.txt | 1 | 
10 files changed, 303 insertions, 246 deletions
@@ -62,12 +62,12 @@ If you choose to enable X11 support:  * xcb  * xcb-composite  * xcb-xfixes +* xcb-xinput  * xcb-image  * xcb-render  * x11-xcb  * xcb-errors (optional, for improved error reporting)  * x11-icccm (optional, for improved Xwayland introspection) -* xcb-xkb (optional, for improved keyboard handling on the X11 backend)  Run these commands: diff --git a/backend/x11/backend.c b/backend/x11/backend.c index cd7986a0..38715631 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -1,25 +1,29 @@  #define _POSIX_C_SOURCE 200112L +  #include <assert.h>  #include <limits.h>  #include <stdbool.h>  #include <stdio.h>  #include <stdlib.h>  #include <time.h> + +#include <wlr/config.h> + +#include <X11/Xlib-xcb.h>  #include <wayland-server.h> +#include <xcb/xcb.h> +#include <xcb/xfixes.h> +#include <xcb/xinput.h> +  #include <wlr/backend/interface.h>  #include <wlr/backend/x11.h> -#include <wlr/config.h>  #include <wlr/interfaces/wlr_input_device.h>  #include <wlr/interfaces/wlr_keyboard.h>  #include <wlr/interfaces/wlr_pointer.h>  #include <wlr/render/egl.h> -#include <wlr/render/gles2.h> +#include <wlr/render/wlr_renderer.h>  #include <wlr/util/log.h> -#include <X11/Xlib-xcb.h> -#include <xcb/xcb.h> -#if WLR_HAS_XCB_XKB -#include <xcb/xkb.h> -#endif +  #include "backend/x11.h"  #include "util/signal.h" @@ -36,8 +40,6 @@ struct wlr_x11_output *get_x11_output_from_window_id(  static void handle_x11_event(struct wlr_x11_backend *x11,  		xcb_generic_event_t *event) { -	handle_x11_input_event(x11, event); -  	switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) {  	case XCB_EXPOSE: {  		xcb_expose_event_t *ev = (xcb_expose_event_t *)event; @@ -69,6 +71,12 @@ static void handle_x11_event(struct wlr_x11_backend *x11,  		}  		break;  	} +	case XCB_GE_GENERIC: { +		xcb_ge_generic_event_t *ev = (xcb_ge_generic_event_t *)event; +		if (ev->extension == x11->xinput_opcode) { +			handle_x11_xinput_event(x11, ev); +		} +	}  	}  } @@ -81,7 +89,7 @@ static int x11_event(int fd, uint32_t mask, void *data) {  	}  	xcb_generic_event_t *e; -	while ((e = xcb_poll_for_event(x11->xcb_conn))) { +	while ((e = xcb_poll_for_event(x11->xcb))) {  		handle_x11_event(x11, e);  		free(e);  	} @@ -99,83 +107,6 @@ static bool backend_start(struct wlr_backend *backend) {  	struct wlr_x11_backend *x11 = get_x11_backend_from_backend(backend);  	x11->started = true; -	struct { -		const char *name; -		xcb_intern_atom_cookie_t cookie; -		xcb_atom_t *atom; -	} atom[] = { -		{ -			.name = "WM_PROTOCOLS", -			.atom = &x11->atoms.wm_protocols, -		}, -		{ -			.name = "WM_DELETE_WINDOW", -			.atom = &x11->atoms.wm_delete_window, -		}, -		{ -			.name = "_NET_WM_NAME", -			.atom = &x11->atoms.net_wm_name, -		}, -		{ -			.name = "UTF8_STRING", -			.atom = &x11->atoms.utf8_string, -		}, -	}; - -	for (size_t i = 0; i < sizeof(atom) / sizeof(atom[0]); ++i) { -		atom[i].cookie = xcb_intern_atom(x11->xcb_conn, -			true, strlen(atom[i].name), atom[i].name); -	} - -	for (size_t i = 0; i < sizeof(atom) / sizeof(atom[0]); ++i) { -		xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply( -			x11->xcb_conn, atom[i].cookie, NULL); - -		if (reply) { -			*atom[i].atom = reply->atom; -			free(reply); -		} else { -			*atom[i].atom = XCB_ATOM_NONE; -		} -	} - -	// create a blank cursor -	xcb_pixmap_t pix = xcb_generate_id(x11->xcb_conn); -	xcb_create_pixmap(x11->xcb_conn, 1, pix, x11->screen->root, 1, 1); - -	x11->cursor = xcb_generate_id(x11->xcb_conn); -	xcb_create_cursor(x11->xcb_conn, x11->cursor, pix, pix, 0, 0, 0, 0, 0, 0, -		0, 0); -	xcb_free_pixmap(x11->xcb_conn, pix); - -#if WLR_HAS_XCB_XKB -		const xcb_query_extension_reply_t *reply = -			xcb_get_extension_data(x11->xcb_conn, &xcb_xkb_id); -		if (reply != NULL && reply->present) { -			x11->xkb_base_event = reply->first_event; -			x11->xkb_base_error = reply->first_error; - -			xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension( -				x11->xcb_conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); -			xcb_xkb_use_extension_reply_t *reply = -				xcb_xkb_use_extension_reply(x11->xcb_conn, cookie, NULL); -			if (reply != NULL && reply->supported) { -				x11->xkb_supported = true; - -				xcb_xkb_select_events(x11->xcb_conn, -					XCB_XKB_ID_USE_CORE_KBD, -					XCB_XKB_EVENT_TYPE_STATE_NOTIFY, -					0, -					XCB_XKB_EVENT_TYPE_STATE_NOTIFY, -					0, -					0, -					0); - -				free(reply); -			} -		} -#endif -  	wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard_dev);  	for (size_t i = 0; i < x11->requested_outputs; ++i) { @@ -209,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_conn, x11->cursor); -	}  	if (x11->xlib_conn) {  		XCloseDisplay(x11->xlib_conn);  	} @@ -258,15 +186,82 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,  		goto error_x11;  	} -	x11->xcb_conn = XGetXCBConnection(x11->xlib_conn); -	if (!x11->xcb_conn || xcb_connection_has_error(x11->xcb_conn)) { +	x11->xcb = XGetXCBConnection(x11->xlib_conn); +	if (!x11->xcb || xcb_connection_has_error(x11->xcb)) {  		wlr_log(WLR_ERROR, "Failed to open xcb connection");  		goto error_display;  	}  	XSetEventQueueOwner(x11->xlib_conn, XCBOwnsEventQueue); -	int fd = xcb_get_file_descriptor(x11->xcb_conn); +	struct { +		const char *name; +		xcb_intern_atom_cookie_t cookie; +		xcb_atom_t *atom; +	} atom[] = { +		{ .name = "WM_PROTOCOLS", .atom = &x11->atoms.wm_protocols }, +		{ .name = "WM_DELETE_WINDOW", .atom = &x11->atoms.wm_delete_window }, +		{ .name = "_NET_WM_NAME", .atom = &x11->atoms.net_wm_name }, +		{ .name = "UTF8_STRING", .atom = &x11->atoms.utf8_string }, +	}; + +	for (size_t i = 0; i < sizeof(atom) / sizeof(atom[0]); ++i) { +		atom[i].cookie = xcb_intern_atom(x11->xcb, +			true, strlen(atom[i].name), atom[i].name); +	} + +	for (size_t i = 0; i < sizeof(atom) / sizeof(atom[0]); ++i) { +		xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply( +			x11->xcb, atom[i].cookie, NULL); + +		if (reply) { +			*atom[i].atom = reply->atom; +			free(reply); +		} else { +			*atom[i].atom = XCB_ATOM_NONE; +		} +	} + +	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; +	} +	x11->xinput_opcode = ext->major_opcode; + +	xcb_input_xi_query_version_cookie_t xi_cookie = +		xcb_input_xi_query_version(x11->xcb, 2, 0); +	xcb_input_xi_query_version_reply_t *xi_reply = +		xcb_input_xi_query_version_reply(x11->xcb, xi_cookie, NULL); + +	if (!xi_reply || xi_reply->major_version < 2) { +		wlr_log(WLR_ERROR, "X11 does not support required Xinput version"); +		free(xi_reply); +		goto error_display; +	} +	free(xi_reply); + +	int fd = xcb_get_file_descriptor(x11->xcb);  	struct wl_event_loop *ev = wl_display_get_event_loop(display);  	uint32_t events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;  	x11->event_source = wl_event_loop_add_fd(ev, fd, events, x11_event, x11); @@ -276,7 +271,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,  	}  	wl_event_source_check(x11->event_source); -	x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb_conn)).data; +	x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb)).data;  	if (!create_renderer_func) {  		create_renderer_func = wlr_renderer_autocreate; diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index 5b108ffb..a50f478a 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -1,140 +1,201 @@  #include <stdlib.h> +  #include <wlr/config.h> -#include <wlr/interfaces/wlr_input_device.h> -#include <wlr/interfaces/wlr_keyboard.h> -#include <wlr/interfaces/wlr_pointer.h> -#include <wlr/util/log.h> -#include <xcb/xcb.h> +  #ifdef __linux__  #include <linux/input-event-codes.h>  #elif __FreeBSD__  #include <dev/evdev/input-event-codes.h>  #endif -#if WLR_HAS_XCB_XKB -#include <xcb/xkb.h> -#endif + +#include <xcb/xcb.h> +#include <xcb/xfixes.h> +#include <xcb/xinput.h> + +#include <wlr/interfaces/wlr_input_device.h> +#include <wlr/interfaces/wlr_keyboard.h> +#include <wlr/interfaces/wlr_pointer.h> +#include <wlr/util/log.h> +  #include "backend/x11.h"  #include "util/signal.h" -static uint32_t xcb_button_to_wl(uint32_t button) { -	switch (button) { -	case XCB_BUTTON_INDEX_1: return BTN_LEFT; -	case XCB_BUTTON_INDEX_2: return BTN_MIDDLE; -	case XCB_BUTTON_INDEX_3: return BTN_RIGHT; -	// XXX: I'm not sure the scroll-wheel direction is right -	case XCB_BUTTON_INDEX_4: return BTN_GEAR_UP; -	case XCB_BUTTON_INDEX_5: return BTN_GEAR_DOWN; -	default: return 0; -	} +static void send_key_event(struct wlr_x11_backend *x11, uint32_t key, +		enum wlr_key_state st, xcb_timestamp_t time) { +	struct wlr_event_keyboard_key ev = { +		.time_msec = time, +		.keycode = key, +		.state = st, +		.update_state = true, +	}; +	wlr_keyboard_notify_key(&x11->keyboard, &ev);  } -static void x11_handle_pointer_position(struct wlr_x11_output *output, -		int16_t x, int16_t y, xcb_timestamp_t time) { -	struct wlr_x11_backend *x11 = output->x11; -	struct wlr_output *wlr_output = &output->wlr_output; -	struct wlr_event_pointer_motion_absolute event = { +static void send_button_event(struct wlr_x11_output *output, uint32_t key, +		enum wlr_button_state st, xcb_timestamp_t time) { +	struct wlr_event_pointer_button ev = { +		.device = &output->pointer_dev, +		.time_msec = time, +		.button = key, +		.state = st, +	}; +	wlr_signal_emit_safe(&output->pointer.events.button, &ev); +} + +static void send_axis_event(struct wlr_x11_output *output, int32_t delta, +		xcb_timestamp_t time) { +	struct wlr_event_pointer_axis ev = {  		.device = &output->pointer_dev,  		.time_msec = time, -		.x = (double)x / wlr_output->width, -		.y = (double)y / wlr_output->height, +		.source = WLR_AXIS_SOURCE_WHEEL, +		.orientation = WLR_AXIS_ORIENTATION_VERTICAL, +		// 15 is a typical value libinput sends for one scroll +		.delta = delta * 15, +		.delta_discrete = delta,  	}; -	wlr_signal_emit_safe(&output->pointer.events.motion_absolute, &event); +	wlr_signal_emit_safe(&output->pointer.events.axis, &ev); +} -	x11->time = time; +static void send_pointer_position_event(struct wlr_x11_output *output, +		int16_t x, int16_t y, xcb_timestamp_t time) { +	struct wlr_event_pointer_motion_absolute ev = { +		.device = &output->pointer_dev, +		.time_msec = time, +		.x = (double)x / output->wlr_output.width, +		.y = (double)y / output->wlr_output.height, +	}; +	wlr_signal_emit_safe(&output->pointer.events.motion_absolute, &ev);  } -void handle_x11_input_event(struct wlr_x11_backend *x11, -		xcb_generic_event_t *event) { -	switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { -	case XCB_KEY_PRESS: -	case XCB_KEY_RELEASE: { -		xcb_key_press_event_t *ev = (xcb_key_press_event_t *)event; -		struct wlr_event_keyboard_key key = { -			.time_msec = ev->time, -			.keycode = ev->detail - 8, -			.state = event->response_type == XCB_KEY_PRESS ? -				WLR_KEY_PRESSED : WLR_KEY_RELEASED, -			.update_state = true, -		}; - -		// TODO use xcb-xkb for more precise modifiers state? -		wlr_keyboard_notify_key(&x11->keyboard, &key); +void handle_x11_xinput_event(struct wlr_x11_backend *x11, +		xcb_ge_generic_event_t *event) { +	struct wlr_x11_output *output; + +	switch (event->event_type) { +	case XCB_INPUT_KEY_PRESS: { +		xcb_input_key_press_event_t *ev = +			(xcb_input_key_press_event_t *)event; + +		wlr_keyboard_notify_modifiers(&x11->keyboard, ev->mods.base, +			ev->mods.latched, ev->mods.locked, ev->mods.effective); +		send_key_event(x11, ev->detail - 8, WLR_KEY_PRESSED, ev->time);  		x11->time = ev->time; -		return; +		break;  	} -	case XCB_BUTTON_PRESS: { -		xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; +	case XCB_INPUT_KEY_RELEASE: { +		xcb_input_key_release_event_t *ev = +			(xcb_input_key_release_event_t *)event; -		struct wlr_x11_output *output = -			get_x11_output_from_window_id(x11, ev->event); -		if (output == NULL) { -			break; +		wlr_keyboard_notify_modifiers(&x11->keyboard, ev->mods.base, +			ev->mods.latched, ev->mods.locked, ev->mods.effective); +		send_key_event(x11, ev->detail - 8, WLR_KEY_RELEASED, ev->time); +		x11->time = ev->time; +		break; +	} +	case XCB_INPUT_BUTTON_PRESS: { +		xcb_input_button_press_event_t *ev = +			(xcb_input_button_press_event_t *)event; + +		output = get_x11_output_from_window_id(x11, ev->event); +		if (!output) { +			return;  		} -		if (ev->detail == XCB_BUTTON_INDEX_4 || -				ev->detail == XCB_BUTTON_INDEX_5) { -			int32_t delta_discrete = ev->detail == XCB_BUTTON_INDEX_4 ? -1 : 1; -			struct wlr_event_pointer_axis axis = { -				.device = &output->pointer_dev, -				.time_msec = ev->time, -				.source = WLR_AXIS_SOURCE_WHEEL, -				.orientation = WLR_AXIS_ORIENTATION_VERTICAL, -				// 15 is a typical value libinput sends for one scroll -				.delta = delta_discrete * 15, -				.delta_discrete = delta_discrete, -			}; -			wlr_signal_emit_safe(&output->pointer.events.axis, &axis); -			x11->time = ev->time; +		switch (ev->detail) { +		case XCB_BUTTON_INDEX_1: +			send_button_event(output, BTN_LEFT, WLR_BUTTON_PRESSED, +				ev->time); +			break; +		case XCB_BUTTON_INDEX_2: +			send_button_event(output, BTN_MIDDLE, WLR_BUTTON_PRESSED, +				ev->time); +			break; +		case XCB_BUTTON_INDEX_3: +			send_button_event(output, BTN_RIGHT, WLR_BUTTON_PRESSED, +				ev->time); +			break; +		case XCB_BUTTON_INDEX_4: +			send_axis_event(output, -1, ev->time); +			break; +		case XCB_BUTTON_INDEX_5: +			send_axis_event(output, 1, ev->time);  			break;  		} + +		x11->time = ev->time; +		break;  	} -	/* fallthrough */ -	case XCB_BUTTON_RELEASE: { -		xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; +	case XCB_INPUT_BUTTON_RELEASE: { +		xcb_input_button_release_event_t *ev = +			(xcb_input_button_release_event_t *)event; -		struct wlr_x11_output *output = -			get_x11_output_from_window_id(x11, ev->event); -		if (output == NULL) { +		output = get_x11_output_from_window_id(x11, ev->event); +		if (!output) { +			return; +		} + +		switch (ev->detail) { +		case XCB_BUTTON_INDEX_1: +			send_button_event(output, BTN_LEFT, WLR_BUTTON_RELEASED, +				ev->time); +			break; +		case XCB_BUTTON_INDEX_2: +			send_button_event(output, BTN_MIDDLE, WLR_BUTTON_RELEASED, +				ev->time); +			break; +		case XCB_BUTTON_INDEX_3: +			send_button_event(output, BTN_RIGHT, WLR_BUTTON_RELEASED, +				ev->time);  			break;  		} -		if (ev->detail != XCB_BUTTON_INDEX_4 && -				ev->detail != XCB_BUTTON_INDEX_5) { -			struct wlr_event_pointer_button button = { -				.device = &output->pointer_dev, -				.time_msec = ev->time, -				.button = xcb_button_to_wl(ev->detail), -				.state = event->response_type == XCB_BUTTON_PRESS ? -					WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED, -			}; - -			wlr_signal_emit_safe(&output->pointer.events.button, &button); +		x11->time = ev->time; +		break; +	} +	case XCB_INPUT_MOTION: { +		xcb_input_motion_event_t *ev = (xcb_input_motion_event_t *)event; + +		output = get_x11_output_from_window_id(x11, ev->event); +		if (!output) { +			return;  		} + +		send_pointer_position_event(output, ev->event_x >> 16, +			ev->event_y >> 16, ev->time);  		x11->time = ev->time; -		return; +		break;  	} -	case XCB_MOTION_NOTIFY: { -		xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event; +	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; +		} -		struct wlr_x11_output *output = -			get_x11_output_from_window_id(x11, ev->event); -		if (output != NULL) { -			x11_handle_pointer_position(output, ev->event_x, ev->event_y, ev->time); +		if (!output->cursor_hidden) { +			xcb_xfixes_hide_cursor(x11->xcb, output->win); +			xcb_flush(x11->xcb); +			output->cursor_hidden = true;  		} -		return; +		break;  	} -	default: -#if WLR_HAS_XCB_XKB -		if (x11->xkb_supported && event->response_type == x11->xkb_base_event) { -			xcb_xkb_state_notify_event_t *ev = -				(xcb_xkb_state_notify_event_t *)event; -			wlr_keyboard_notify_modifiers(&x11->keyboard, ev->baseMods, -				ev->latchedMods, ev->lockedMods, ev->lockedGroup); +	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;  		} -#endif + +		if (output->cursor_hidden) { +			xcb_xfixes_show_cursor(x11->xcb, output->win); +			xcb_flush(x11->xcb); +			output->cursor_hidden = false; +		}  		break;  	} +	}  }  static void input_device_destroy(struct wlr_input_device *wlr_device) { @@ -166,14 +227,14 @@ void update_x11_pointer_position(struct wlr_x11_output *output,  	struct wlr_x11_backend *x11 = output->x11;  	xcb_query_pointer_cookie_t cookie = -		xcb_query_pointer(x11->xcb_conn, output->win); +		xcb_query_pointer(x11->xcb, output->win);  	xcb_query_pointer_reply_t *reply = -		xcb_query_pointer_reply(x11->xcb_conn, cookie, NULL); +		xcb_query_pointer_reply(x11->xcb, cookie, NULL);  	if (!reply) {  		return;  	} -	x11_handle_pointer_position(output, reply->win_x, reply->win_y, time); +	send_pointer_position_event(output, reply->win_x, reply->win_y, time);  	free(reply);  } diff --git a/backend/x11/meson.build b/backend/x11/meson.build index fa51e3d7..19e873ab 100644 --- a/backend/x11/meson.build +++ b/backend/x11/meson.build @@ -1,10 +1,9 @@  x11_libs = []  x11_required = [ -	'xcb',  	'x11-xcb', -] -x11_optional = [ -	'xcb-xkb', +	'xcb', +	'xcb-xinput', +	'xcb-xfixes',  ]  foreach lib : x11_required @@ -16,14 +15,6 @@ foreach lib : x11_required  	x11_libs += dep  endforeach -foreach lib : x11_optional -	dep = dependency(lib, required: get_option(lib)) -	if dep.found() -		x11_libs += dep -		conf_data.set10('WLR_HAS_' + lib.underscorify().to_upper(), true) -	endif -endforeach -  lib_wlr_backend_x11 = static_library(  	'wlr_backend_x11',  	files( diff --git a/backend/x11/output.c b/backend/x11/output.c index 1ac12a8d..6f98c590 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -1,10 +1,16 @@  #define _POSIX_C_SOURCE 200809L +  #include <assert.h>  #include <stdlib.h>  #include <string.h> + +#include <xcb/xcb.h> +#include <xcb/xinput.h> +  #include <wlr/interfaces/wlr_output.h>  #include <wlr/interfaces/wlr_pointer.h>  #include <wlr/util/log.h> +  #include "backend/x11.h"  #include "util/signal.h" @@ -16,8 +22,8 @@ static int signal_frame(void *data) {  }  static void parse_xcb_setup(struct wlr_output *output, -		xcb_connection_t *xcb_conn) { -	const xcb_setup_t *xcb_setup = xcb_get_setup(xcb_conn); +		xcb_connection_t *xcb) { +	const xcb_setup_t *xcb_setup = xcb_get_setup(xcb);  	snprintf(output->make, sizeof(output->make), "%.*s",  			xcb_setup_vendor_length(xcb_setup), @@ -55,11 +61,11 @@ static bool output_set_custom_mode(struct wlr_output *wlr_output,  	const uint32_t values[] = { width, height };  	xcb_void_cookie_t cookie = xcb_configure_window_checked( -		x11->xcb_conn, output->win, +		x11->xcb, output->win,  		XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);  	xcb_generic_error_t *error; -	if ((error = xcb_request_check(x11->xcb_conn, cookie))) { +	if ((error = xcb_request_check(x11->xcb, cookie))) {  		wlr_log(WLR_ERROR, "Could not set window size to %dx%d\n",  			width, height);  		free(error); @@ -84,8 +90,8 @@ static void output_destroy(struct wlr_output *wlr_output) {  	wl_list_remove(&output->link);  	wl_event_source_remove(output->frame_timer);  	wlr_egl_destroy_surface(&x11->egl, output->surf); -	xcb_destroy_window(x11->xcb_conn, output->win); -	xcb_flush(x11->xcb_conn); +	xcb_destroy_window(x11->xcb, output->win); +	xcb_flush(x11->xcb);  	free(output);  } @@ -142,21 +148,32 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {  	snprintf(wlr_output->name, sizeof(wlr_output->name), "X11-%d",  		wl_list_length(&x11->outputs) + 1); -	parse_xcb_setup(wlr_output, x11->xcb_conn); +	parse_xcb_setup(wlr_output, x11->xcb);  	uint32_t mask = XCB_CW_EVENT_MASK;  	uint32_t values[] = { -		XCB_EVENT_MASK_EXPOSURE | -		XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | -		XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | -		XCB_EVENT_MASK_POINTER_MOTION | -		XCB_EVENT_MASK_STRUCTURE_NOTIFY +		XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY  	}; -	output->win = xcb_generate_id(x11->xcb_conn); -	xcb_create_window(x11->xcb_conn, XCB_COPY_FROM_PARENT, output->win, +	output->win = xcb_generate_id(x11->xcb); +	xcb_create_window(x11->xcb, XCB_COPY_FROM_PARENT, output->win,  		x11->screen->root, 0, 0, wlr_output->width, wlr_output->height, 1,  		XCB_WINDOW_CLASS_INPUT_OUTPUT, x11->screen->root_visual, mask, values); +	struct { +		xcb_input_event_mask_t head; +		xcb_input_xi_event_mask_t mask; +	} xinput_mask = { +		.head = { .deviceid = XCB_INPUT_DEVICE_ALL_MASTER, .mask_len = 1 }, +		.mask = XCB_INPUT_XI_EVENT_MASK_KEY_PRESS | +			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_ENTER | +			XCB_INPUT_XI_EVENT_MASK_LEAVE, +	}; +	xcb_input_xi_select_events(x11->xcb, output->win, 1, &xinput_mask.head); +  	output->surf = wlr_egl_create_surface(&x11->egl, &output->win);  	if (!output->surf) {  		wlr_log(WLR_ERROR, "Failed to create EGL surface"); @@ -164,23 +181,19 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {  		return NULL;  	} -	xcb_change_property(x11->xcb_conn, XCB_PROP_MODE_REPLACE, output->win, +	xcb_change_property(x11->xcb, XCB_PROP_MODE_REPLACE, output->win,  		x11->atoms.wm_protocols, XCB_ATOM_ATOM, 32, 1,  		&x11->atoms.wm_delete_window);  	char title[32];  	if (snprintf(title, sizeof(title), "wlroots - %s", wlr_output->name)) { -		xcb_change_property(x11->xcb_conn, XCB_PROP_MODE_REPLACE, output->win, +		xcb_change_property(x11->xcb, XCB_PROP_MODE_REPLACE, output->win,  			x11->atoms.net_wm_name, x11->atoms.utf8_string, 8,  			strlen(title), title);  	} -	uint32_t cursor_values[] = { x11->cursor }; -	xcb_change_window_attributes(x11->xcb_conn, output->win, XCB_CW_CURSOR, -		cursor_values); - -	xcb_map_window(x11->xcb_conn, output->win); -	xcb_flush(x11->xcb_conn); +	xcb_map_window(x11->xcb, output->win); +	xcb_flush(x11->xcb);  	struct wl_event_loop *ev = wl_display_get_event_loop(x11->wl_display);  	output->frame_timer = wl_event_loop_add_timer(ev, signal_frame, output); diff --git a/include/backend/x11.h b/include/backend/x11.h index 06803768..1a8341f6 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -2,14 +2,17 @@  #define BACKEND_X11_H  #include <stdbool.h> + +#include <X11/Xlib-xcb.h>  #include <wayland-server.h> -#include <wlr/config.h> +#include <xcb/xcb.h> +  #include <wlr/backend/x11.h> +#include <wlr/config.h>  #include <wlr/interfaces/wlr_input_device.h>  #include <wlr/interfaces/wlr_output.h>  #include <wlr/render/egl.h> -#include <X11/Xlib-xcb.h> -#include <xcb/xcb.h> +#include <wlr/render/wlr_renderer.h>  #define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f @@ -30,6 +33,8 @@ struct wlr_x11_output {  	struct wl_event_source *frame_timer;  	int frame_delay; + +	bool cursor_hidden;  };  struct wlr_x11_backend { @@ -38,7 +43,7 @@ struct wlr_x11_backend {  	bool started;  	Display *xlib_conn; -	xcb_connection_t *xcb_conn; +	xcb_connection_t *xcb;  	xcb_screen_t *screen;  	size_t requested_outputs; @@ -61,14 +66,7 @@ struct wlr_x11_backend {  	// The time we last received an event  	xcb_timestamp_t time; -	// A blank cursor -	xcb_cursor_t cursor; - -#if WLR_HAS_XCB_XKB -	bool xkb_supported; -	uint8_t xkb_base_event; -	uint8_t xkb_base_error; -#endif +	uint8_t xinput_opcode;  	struct wl_listener display_destroy;  }; @@ -82,8 +80,8 @@ extern const struct wlr_keyboard_impl keyboard_impl;  extern const struct wlr_pointer_impl pointer_impl;  extern const struct wlr_input_device_impl input_device_impl; -void handle_x11_input_event(struct wlr_x11_backend *x11, -	xcb_generic_event_t *event); +void handle_x11_xinput_event(struct wlr_x11_backend *x11, +		xcb_ge_generic_event_t *event);  void update_x11_pointer_position(struct wlr_x11_output *output,  	xcb_timestamp_t time); diff --git a/include/wlr/backend/x11.h b/include/wlr/backend/x11.h index 56360bf7..5793a3b9 100644 --- a/include/wlr/backend/x11.h +++ b/include/wlr/backend/x11.h @@ -2,7 +2,9 @@  #define WLR_BACKEND_X11_H  #include <stdbool.h> +  #include <wayland-server.h> +  #include <wlr/backend.h>  #include <wlr/types/wlr_input_device.h>  #include <wlr/types/wlr_output.h> diff --git a/include/wlr/config.h.in b/include/wlr/config.h.in index 17277c07..94273fac 100644 --- a/include/wlr/config.h.in +++ b/include/wlr/config.h.in @@ -12,6 +12,5 @@  #mesondefine WLR_HAS_XCB_ERRORS  #mesondefine WLR_HAS_XCB_ICCCM -#mesondefine WLR_HAS_XCB_XKB  #endif diff --git a/meson.build b/meson.build index 7017e4b5..3d96d052 100644 --- a/meson.build +++ b/meson.build @@ -35,7 +35,6 @@ conf_data.set10('WLR_HAS_X11_BACKEND', false)  conf_data.set10('WLR_HAS_XWAYLAND', false)  conf_data.set10('WLR_HAS_XCB_ERRORS', false)  conf_data.set10('WLR_HAS_XCB_ICCCM', false) -conf_data.set10('WLR_HAS_XCB_XKB', false)  wlr_inc = include_directories('.', 'include') diff --git a/meson_options.txt b/meson_options.txt index 360c6f6a..19a6cad7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,7 +3,6 @@ option('logind', type: 'feature', value: 'auto', description: 'Enable support fo  option('logind-provider', type: 'combo', choices: ['systemd', 'elogind'], value: 'systemd', description: 'Provider of logind support library')  option('xcb-errors', type: 'feature', value: 'auto', description: 'Use xcb-errors util library')  option('xcb-icccm', type: 'feature', value: 'auto', description: 'Use xcb-icccm util library') -option('xcb-xkb', type: 'feature', value: 'auto', description: 'Use xcb-xkb util library')  option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')  option('x11-backend', type: 'feature', value: 'auto', description: 'Enable X11 backend')  option('rootston', type: 'boolean', value: true, description: 'Build the rootston example compositor')  | 
