compositor-x11: Attempt to track state without XKB

This isn't very pleasant, but it's pretty much the best we can do in the
absence of either XCB XKB support, or XCB XI2 bindings (argh!).

We get a state mask with most significant X11 events (which inexplicably
includes EnterNotify but not FocusIn), but unfortunately it's only a
single flat set of effective modifiers rather than the more granular
sets we want, so we still update the state with every key, but then also
use the core X11 state as a mask to make sure we don't get any stuck
modifiers.

Ugh.

Signed-off-by: Daniel Stone <daniel@fooishbar.org>
Daniel Stone 13 years ago committed by Kristian Høgsberg
parent e2faa120ef
commit 154c34c851
  1. 44
      src/compositor-x11.c

@ -610,7 +610,6 @@ x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window)
return NULL;
}
#ifdef HAVE_XCB_XKB
static uint32_t
get_xkb_mod_mask(struct x11_compositor *c, uint32_t in)
{
@ -637,6 +636,7 @@ get_xkb_mod_mask(struct x11_compositor *c, uint32_t in)
return ret;
}
#ifdef HAVE_XCB_XKB
static void
update_xkb_state(struct x11_compositor *c, xcb_xkb_state_notify_event_t *state)
{
@ -655,6 +655,34 @@ update_xkb_state(struct x11_compositor *c, xcb_xkb_state_notify_event_t *state)
}
#endif
/**
* This is monumentally unpleasant. If we don't have XCB-XKB bindings,
* the best we can do (given that XCB also lacks XI2 support), is to take
* the state from the core key events. Unfortunately that only gives us
* the effective (i.e. union of depressed/latched/locked) state, and we
* need the granularity.
*
* So we still update the state with every key event we see, but also use
* the state field from X11 events as a mask so we don't get any stuck
* modifiers.
*/
static void
update_xkb_state_from_core(struct x11_compositor *c, uint16_t x11_mask)
{
uint32_t mask = get_xkb_mod_mask(c, x11_mask);
struct wl_keyboard *keyboard = &c->base.seat->keyboard;
xkb_state_update_mask(c->base.seat->xkb_state.state,
keyboard->modifiers.mods_depressed & mask,
keyboard->modifiers.mods_latched & mask,
keyboard->modifiers.mods_locked & mask,
0,
0,
(x11_mask >> 13) & 3);
notify_modifiers(&c->base.seat->seat,
wl_display_next_serial(c->base.wl_display));
}
static void
x11_compositor_deliver_button_event(struct x11_compositor *c,
xcb_generic_event_t *event, int state)
@ -663,6 +691,9 @@ x11_compositor_deliver_button_event(struct x11_compositor *c,
(xcb_button_press_event_t *) event;
uint32_t button;
if (!c->has_xkb)
update_xkb_state_from_core(c, button_event->state);
switch (button_event->detail) {
default:
button = button_event->detail + BTN_LEFT - 1;
@ -767,6 +798,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
/* Deliver the held key release now
* and fall through and handle the new
* event below. */
update_xkb_state_from_core(c, key_release->state);
notify_key(&c->base.seat->seat,
weston_compositor_get_time(),
key_release->detail - 8,
@ -811,6 +843,8 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
switch (event->response_type & ~0x80) {
case XCB_KEY_PRESS:
key_press = (xcb_key_press_event_t *) event;
if (!c->has_xkb)
update_xkb_state_from_core(c, key_press->state);
notify_key(&c->base.seat->seat,
weston_compositor_get_time(),
key_press->detail - 8,
@ -840,6 +874,8 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
break;
case XCB_MOTION_NOTIFY:
motion_notify = (xcb_motion_notify_event_t *) event;
if (!c->has_xkb)
update_xkb_state_from_core(c, motion_notify->state);
output = x11_compositor_find_output(c, motion_notify->event);
x = wl_fixed_from_int(output->base.x + motion_notify->event_x);
y = wl_fixed_from_int(output->base.y + motion_notify->event_y);
@ -857,10 +893,11 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
enter_notify = (xcb_enter_notify_event_t *) event;
if (enter_notify->state >= Button1Mask)
break;
if (!c->has_xkb)
update_xkb_state_from_core(c, enter_notify->state);
output = x11_compositor_find_output(c, enter_notify->event);
x = wl_fixed_from_int(output->base.x + enter_notify->event_x);
y = wl_fixed_from_int(output->base.y + enter_notify->event_y);
/* XXX notify_modifiers() */
notify_pointer_focus(&c->base.seat->seat,
&output->base, x, y);
@ -870,6 +907,8 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
enter_notify = (xcb_enter_notify_event_t *) event;
if (enter_notify->state >= Button1Mask)
break;
if (!c->has_xkb)
update_xkb_state_from_core(c, enter_notify->state);
output = x11_compositor_find_output(c, enter_notify->event);
notify_pointer_focus(&c->base.seat->seat, NULL, 0, 0);
break;
@ -919,6 +958,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
switch (prev ? prev->response_type & ~0x80 : 0x80) {
case XCB_KEY_RELEASE:
key_release = (xcb_key_press_event_t *) prev;
update_xkb_state_from_core(c, key_release->state);
notify_key(&c->base.seat->seat,
weston_compositor_get_time(),
key_release->detail - 8,

Loading…
Cancel
Save