compositor-x11: Handle keyboard focus correctly so we avoid stuck modifiers
This commit is contained in:
parent
ac5c5e7853
commit
3ba4858c4b
|
@ -1015,6 +1015,7 @@ window_handle_keyboard_focus(void *data,
|
||||||
input->keyboard_focus = NULL;
|
input->keyboard_focus = NULL;
|
||||||
|
|
||||||
end = keys->data + keys->size;
|
end = keys->data + keys->size;
|
||||||
|
input->modifiers = 0;
|
||||||
for (k = keys->data; k < end; k++)
|
for (k = keys->data; k < end; k++)
|
||||||
input->modifiers |= d->xkb->map->modmap[*k];
|
input->modifiers |= d->xkb->map->modmap[*k];
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct x11_compositor {
|
||||||
xcb_cursor_t null_cursor;
|
xcb_cursor_t null_cursor;
|
||||||
int dri2_major;
|
int dri2_major;
|
||||||
int dri2_minor;
|
int dri2_minor;
|
||||||
|
struct wl_array keys;
|
||||||
struct wl_event_source *xcb_source;
|
struct wl_event_source *xcb_source;
|
||||||
struct {
|
struct {
|
||||||
xcb_atom_t wm_protocols;
|
xcb_atom_t wm_protocols;
|
||||||
|
@ -381,7 +382,9 @@ x11_compositor_create_output(struct x11_compositor *c, int width, int height)
|
||||||
XCB_EVENT_MASK_EXPOSURE |
|
XCB_EVENT_MASK_EXPOSURE |
|
||||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
||||||
XCB_EVENT_MASK_ENTER_WINDOW |
|
XCB_EVENT_MASK_ENTER_WINDOW |
|
||||||
XCB_EVENT_MASK_LEAVE_WINDOW,
|
XCB_EVENT_MASK_LEAVE_WINDOW |
|
||||||
|
XCB_EVENT_MASK_KEYMAP_STATE |
|
||||||
|
XCB_EVENT_MASK_FOCUS_CHANGE,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -550,9 +553,13 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
|
||||||
xcb_enter_notify_event_t *enter_notify;
|
xcb_enter_notify_event_t *enter_notify;
|
||||||
xcb_key_press_event_t *key_press;
|
xcb_key_press_event_t *key_press;
|
||||||
xcb_button_press_event_t *button_press;
|
xcb_button_press_event_t *button_press;
|
||||||
|
xcb_keymap_notify_event_t *keymap_notify;
|
||||||
|
xcb_focus_in_event_t *focus_in;
|
||||||
xcb_expose_event_t *expose;
|
xcb_expose_event_t *expose;
|
||||||
xcb_rectangle_t *r;
|
xcb_rectangle_t *r;
|
||||||
xcb_atom_t atom;
|
xcb_atom_t atom;
|
||||||
|
uint32_t *k;
|
||||||
|
int i, set;
|
||||||
|
|
||||||
loop = wl_display_get_event_loop(c->base.wl_display);
|
loop = wl_display_get_event_loop(c->base.wl_display);
|
||||||
while (event = xcb_poll_for_event (c->conn), event != NULL) {
|
while (event = xcb_poll_for_event (c->conn), event != NULL) {
|
||||||
|
@ -630,13 +637,44 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
|
||||||
if (atom == c->atom.wm_delete_window)
|
if (atom == c->atom.wm_delete_window)
|
||||||
wl_display_terminate(c->base.wl_display);
|
wl_display_terminate(c->base.wl_display);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
|
|
||||||
|
case XCB_FOCUS_IN:
|
||||||
|
focus_in = (xcb_focus_in_event_t *) event;
|
||||||
|
if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED)
|
||||||
|
break;
|
||||||
|
|
||||||
|
output = x11_compositor_find_output(c, focus_in->event);
|
||||||
|
notify_keyboard_focus(c->base.input_device,
|
||||||
|
get_time(),
|
||||||
|
&output->base, &c->keys);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_FOCUS_OUT:
|
||||||
|
focus_in = (xcb_focus_in_event_t *) event;
|
||||||
|
if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED)
|
||||||
|
break;
|
||||||
|
notify_keyboard_focus(c->base.input_device,
|
||||||
|
get_time(), NULL, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_KEYMAP_NOTIFY:
|
||||||
|
keymap_notify = (xcb_keymap_notify_event_t *) event;
|
||||||
|
c->keys.size = 0;
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(keymap_notify->keys) * 8; i++) {
|
||||||
|
set = keymap_notify->keys[i >> 3] &
|
||||||
|
(1 << (i & 7));
|
||||||
|
if (set) {
|
||||||
|
k = wl_array_add(&c->keys, sizeof *k);
|
||||||
|
*k = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (event);
|
free (event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define F(field) offsetof(struct x11_compositor, field)
|
#define F(field) offsetof(struct x11_compositor, field)
|
||||||
|
@ -719,6 +757,7 @@ x11_compositor_create(struct wl_display *display, int width, int height)
|
||||||
|
|
||||||
s = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
|
s = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
|
||||||
c->screen = s.data;
|
c->screen = s.data;
|
||||||
|
wl_array_init(&c->keys);
|
||||||
|
|
||||||
x11_compositor_get_resources(c);
|
x11_compositor_get_resources(c);
|
||||||
|
|
||||||
|
|
|
@ -840,6 +840,28 @@ notify_pointer_focus(struct wl_input_device *device,
|
||||||
wlsc_compositor_schedule_repaint(compositor);
|
wlsc_compositor_schedule_repaint(compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notify_keyboard_focus(struct wl_input_device *device_base,
|
||||||
|
uint32_t time, struct wlsc_output *output,
|
||||||
|
struct wl_array *keys)
|
||||||
|
{
|
||||||
|
struct wlsc_input_device *device =
|
||||||
|
(struct wlsc_input_device *) device_base;
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
wl_array_copy(&device->input_device.keys, keys);
|
||||||
|
wl_input_device_set_keyboard_focus(&device->input_device,
|
||||||
|
device->saved_keyboard_focus,
|
||||||
|
time);
|
||||||
|
} else {
|
||||||
|
device->saved_keyboard_focus =
|
||||||
|
device->input_device.keyboard_focus;
|
||||||
|
wl_input_device_set_keyboard_focus(&device->input_device,
|
||||||
|
NULL, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_device_attach(struct wl_client *client,
|
input_device_attach(struct wl_client *client,
|
||||||
struct wl_input_device *device_base,
|
struct wl_input_device *device_base,
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct wlsc_input_device {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
uint32_t modifier_state;
|
uint32_t modifier_state;
|
||||||
struct wl_selection *selection;
|
struct wl_selection *selection;
|
||||||
|
struct wl_surface *saved_keyboard_focus;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlsc_drm {
|
struct wlsc_drm {
|
||||||
|
@ -161,6 +162,11 @@ notify_pointer_focus(struct wl_input_device *device,
|
||||||
struct wlsc_output *output,
|
struct wlsc_output *output,
|
||||||
int32_t x, int32_t y);
|
int32_t x, int32_t y);
|
||||||
|
|
||||||
|
void
|
||||||
|
notify_keyboard_focus(struct wl_input_device *device,
|
||||||
|
uint32_t time, struct wlsc_output *output,
|
||||||
|
struct wl_array *keys);
|
||||||
|
|
||||||
void
|
void
|
||||||
wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs);
|
wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs);
|
||||||
void
|
void
|
||||||
|
|
|
@ -113,3 +113,11 @@ wl_array_add(struct wl_array *array, int size)
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WL_EXPORT void
|
||||||
|
wl_array_copy(struct wl_array *array, struct wl_array *source)
|
||||||
|
{
|
||||||
|
array->size = 0;
|
||||||
|
wl_array_add(array, source->size);
|
||||||
|
memcpy(array->data, source->data, source->size);
|
||||||
|
}
|
||||||
|
|
|
@ -148,6 +148,7 @@ struct wl_array {
|
||||||
void wl_array_init(struct wl_array *array);
|
void wl_array_init(struct wl_array *array);
|
||||||
void wl_array_release(struct wl_array *array);
|
void wl_array_release(struct wl_array *array);
|
||||||
void *wl_array_add(struct wl_array *array, int size);
|
void *wl_array_add(struct wl_array *array, int size);
|
||||||
|
void wl_array_copy(struct wl_array *array, struct wl_array *source);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue