diff --git a/backend/meson.build b/backend/meson.build index a74ea024..df12d703 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -51,6 +51,7 @@ endif if conf_data.get('WLR_HAS_X11_BACKEND', false) backend_files += files('x11/backend.c') + backend_deps += xcb_xkb endif if conf_data.get('WLR_HAS_ELOGIND', false) diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 36d72d9e..79b896fe 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef __linux__ #include #elif __FreeBSD__ @@ -30,6 +31,10 @@ static const struct wlr_backend_impl backend_impl; static const struct wlr_output_impl output_impl; static const struct wlr_input_device_impl input_device_impl = { 0 }; +// TODO: remove global state +static uint8_t xkb_base_event; +static uint8_t xkb_base_error; + static uint32_t xcb_button_to_wl(uint32_t button) { switch (button) { case XCB_BUTTON_INDEX_1: return BTN_LEFT; @@ -157,6 +162,12 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e break; } default: + if (event->response_type == 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); + } break; } @@ -225,6 +236,28 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { x11->screen->root, 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, x11->screen->root_visual, mask, values); + const xcb_query_extension_reply_t *reply = + xcb_get_extension_data(x11->xcb_conn, &xcb_xkb_id); + if (reply->present) { + xkb_base_event = reply->first_event; + 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 && reply->supported) { + 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); + } + } + output->surf = wlr_egl_create_surface(&x11->egl, &output->win); if (!output->surf) { wlr_log(L_ERROR, "Failed to create EGL surface"); diff --git a/meson.build b/meson.build index 7740b416..a48984c1 100644 --- a/meson.build +++ b/meson.build @@ -82,35 +82,36 @@ if elogind.found() and get_option('enable_elogind') != 'false' endif if get_option('enable_x11_backend') or get_option('enable_xwayland') - xcb = dependency('xcb') - xcb_composite = dependency('xcb-composite') - xcb_xfixes = dependency('xcb-xfixes') - xcb_image = dependency('xcb-image') - xcb_render = dependency('xcb-render') - x11_xcb = dependency('x11-xcb') + xcb = dependency('xcb') + xcb_composite = dependency('xcb-composite') + xcb_xfixes = dependency('xcb-xfixes') + xcb_xkb = dependency('xcb-xkb') # TODO: make this optional + xcb_image = dependency('xcb-image') + xcb_render = dependency('xcb-render') + x11_xcb = dependency('x11-xcb') - xcb_icccm = dependency('xcb-icccm', required: false) - xcb_errors = dependency('xcb-errors', required: get_option('enable_xcb_errors') == 'true') + xcb_icccm = dependency('xcb-icccm', required: false) + xcb_errors = dependency('xcb-errors', required: get_option('enable_xcb_errors') == 'true') - if xcb_icccm.found() - conf_data.set('WLR_HAS_XCB_ICCCM', true) - endif + if xcb_icccm.found() + conf_data.set('WLR_HAS_XCB_ICCCM', true) + endif - if xcb_errors.found() and get_option('enable_xcb_errors') != 'false' - conf_data.set('WLR_HAS_XCB_ERRORS', true) - endif + if xcb_errors.found() and get_option('enable_xcb_errors') != 'false' + conf_data.set('WLR_HAS_XCB_ERRORS', true) + endif - wlr_deps += [ - xcb, - xcb_composite, - x11_xcb, - ] + wlr_deps += [ + xcb, + xcb_composite, + x11_xcb, + ] else - add_project_arguments('-DMESA_EGL_NO_X11_HEADERS', language: 'c') + add_project_arguments('-DMESA_EGL_NO_X11_HEADERS', language: 'c') endif if get_option('enable_x11_backend') - conf_data.set('WLR_HAS_X11_BACKEND', true) + conf_data.set('WLR_HAS_X11_BACKEND', true) endif if get_option('enable_xwayland')