Implement input method keyboard grab
This commit is contained in:
parent
585abdb357
commit
e5913f8106
|
@ -28,7 +28,10 @@ struct sway_input_method_relay {
|
||||||
|
|
||||||
struct wl_listener input_method_new;
|
struct wl_listener input_method_new;
|
||||||
struct wl_listener input_method_commit;
|
struct wl_listener input_method_commit;
|
||||||
|
struct wl_listener input_method_grab_keyboard;
|
||||||
struct wl_listener input_method_destroy;
|
struct wl_listener input_method_destroy;
|
||||||
|
|
||||||
|
struct wl_listener input_method_keyboard_grab_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sway_text_input {
|
struct sway_text_input {
|
||||||
|
|
|
@ -378,6 +378,28 @@ static void update_keyboard_state(struct sway_keyboard *keyboard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get keyboard grab of the seat from sway_keyboard if we should forward events
|
||||||
|
* to it.
|
||||||
|
*
|
||||||
|
* Returns NULL if the keyboard is not grabbed by an input method,
|
||||||
|
* or if event is from virtual keyboard of the same client as grab.
|
||||||
|
* TODO: see swaywm/wlroots#2322
|
||||||
|
*/
|
||||||
|
static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab(
|
||||||
|
struct sway_keyboard *keyboard) {
|
||||||
|
struct wlr_input_method_v2 *input_method = keyboard->seat_device->
|
||||||
|
sway_seat->im_relay.input_method;
|
||||||
|
struct wlr_virtual_keyboard_v1 *virtual_keyboard =
|
||||||
|
wlr_input_device_get_virtual_keyboard(keyboard->seat_device->input_device->wlr_device);
|
||||||
|
if (!input_method || !input_method->keyboard_grab || (virtual_keyboard &&
|
||||||
|
wl_resource_get_client(virtual_keyboard->resource) ==
|
||||||
|
wl_resource_get_client(input_method->keyboard_grab->resource))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return input_method->keyboard_grab;
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_key_event(struct sway_keyboard *keyboard,
|
static void handle_key_event(struct sway_keyboard *keyboard,
|
||||||
struct wlr_event_keyboard_key *event) {
|
struct wlr_event_keyboard_key *event) {
|
||||||
struct sway_seat *seat = keyboard->seat_device->sway_seat;
|
struct sway_seat *seat = keyboard->seat_device->sway_seat;
|
||||||
|
@ -488,17 +510,42 @@ static void handle_key_event(struct sway_keyboard *keyboard,
|
||||||
keyinfo.raw_keysyms_len);
|
keyinfo.raw_keysyms_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handled || event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||||
|
// If the pressed event was sent to a client, also send the released
|
||||||
|
// event. In particular, don't send the released event to the IM grab.
|
||||||
bool pressed_sent = update_shortcut_state(
|
bool pressed_sent = update_shortcut_state(
|
||||||
&keyboard->state_pressed_sent, event->keycode, event->state,
|
&keyboard->state_pressed_sent, event->keycode,
|
||||||
keyinfo.keycode, 0);
|
event->state, keyinfo.keycode, 0);
|
||||||
if (pressed_sent || event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
if (pressed_sent) {
|
||||||
wlr_seat_set_keyboard(wlr_seat, wlr_device);
|
wlr_seat_set_keyboard(wlr_seat, wlr_device);
|
||||||
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
|
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
|
||||||
event->keycode, event->state);
|
event->keycode, event->state);
|
||||||
|
handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard);
|
||||||
|
|
||||||
|
if (kb_grab) {
|
||||||
|
wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab,
|
||||||
|
wlr_device->keyboard);
|
||||||
|
wlr_input_method_keyboard_grab_v2_send_key(kb_grab,
|
||||||
|
event->time_msec, event->keycode, event->state);
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled && event->state != WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||||
|
// If a released event failed pressed sent test, and not in sent to
|
||||||
|
// keyboard grab, it is still not handled. Don't handle released here.
|
||||||
|
update_shortcut_state(
|
||||||
|
&keyboard->state_pressed_sent, event->keycode, event->state,
|
||||||
|
keyinfo.keycode, 0);
|
||||||
|
wlr_seat_set_keyboard(wlr_seat, wlr_device);
|
||||||
|
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
|
||||||
|
event->keycode, event->state);
|
||||||
|
}
|
||||||
|
|
||||||
free(device_identifier);
|
free(device_identifier);
|
||||||
}
|
}
|
||||||
|
@ -614,10 +661,19 @@ static void handle_modifier_event(struct sway_keyboard *keyboard) {
|
||||||
struct wlr_input_device *wlr_device =
|
struct wlr_input_device *wlr_device =
|
||||||
keyboard->seat_device->input_device->wlr_device;
|
keyboard->seat_device->input_device->wlr_device;
|
||||||
if (!wlr_device->keyboard->group) {
|
if (!wlr_device->keyboard->group) {
|
||||||
struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat;
|
struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard);
|
||||||
wlr_seat_set_keyboard(wlr_seat, wlr_device);
|
|
||||||
wlr_seat_keyboard_notify_modifiers(wlr_seat,
|
if (kb_grab) {
|
||||||
&wlr_device->keyboard->modifiers);
|
wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab,
|
||||||
|
wlr_device->keyboard);
|
||||||
|
wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab,
|
||||||
|
&wlr_device->keyboard->modifiers);
|
||||||
|
} else {
|
||||||
|
struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat;
|
||||||
|
wlr_seat_set_keyboard(wlr_seat, wlr_device);
|
||||||
|
wlr_seat_keyboard_notify_modifiers(wlr_seat,
|
||||||
|
&wlr_device->keyboard->modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard);
|
uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard);
|
||||||
determine_bar_visibility(modifiers);
|
determine_bar_visibility(modifiers);
|
||||||
|
|
|
@ -55,6 +55,37 @@ static void handle_im_commit(struct wl_listener *listener, void *data) {
|
||||||
wlr_text_input_v3_send_done(text_input->input);
|
wlr_text_input_v3_send_done(text_input->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
|
||||||
|
input_method_keyboard_grab_destroy);
|
||||||
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||||
|
wl_list_remove(&relay->input_method_keyboard_grab_destroy.link);
|
||||||
|
|
||||||
|
if (keyboard_grab->keyboard) {
|
||||||
|
// send modifier state to original client
|
||||||
|
wlr_seat_keyboard_notify_modifiers(keyboard_grab->input_method->seat,
|
||||||
|
&keyboard_grab->keyboard->modifiers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) {
|
||||||
|
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
|
||||||
|
input_method_grab_keyboard);
|
||||||
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||||
|
|
||||||
|
// send modifier state to grab
|
||||||
|
struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat);
|
||||||
|
wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,
|
||||||
|
active_keyboard);
|
||||||
|
wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab,
|
||||||
|
&active_keyboard->modifiers);
|
||||||
|
|
||||||
|
wl_signal_add(&keyboard_grab->events.destroy,
|
||||||
|
&relay->input_method_keyboard_grab_destroy);
|
||||||
|
relay->input_method_keyboard_grab_destroy.notify =
|
||||||
|
handle_im_keyboard_grab_destroy;
|
||||||
|
}
|
||||||
|
|
||||||
static void text_input_set_pending_focused_surface(
|
static void text_input_set_pending_focused_surface(
|
||||||
struct sway_text_input *text_input, struct wlr_surface *surface) {
|
struct sway_text_input *text_input, struct wlr_surface *surface) {
|
||||||
wl_list_remove(&text_input->pending_focused_surface_destroy.link);
|
wl_list_remove(&text_input->pending_focused_surface_destroy.link);
|
||||||
|
@ -245,6 +276,9 @@ static void relay_handle_input_method(struct wl_listener *listener,
|
||||||
wl_signal_add(&relay->input_method->events.commit,
|
wl_signal_add(&relay->input_method->events.commit,
|
||||||
&relay->input_method_commit);
|
&relay->input_method_commit);
|
||||||
relay->input_method_commit.notify = handle_im_commit;
|
relay->input_method_commit.notify = handle_im_commit;
|
||||||
|
wl_signal_add(&relay->input_method->events.grab_keyboard,
|
||||||
|
&relay->input_method_grab_keyboard);
|
||||||
|
relay->input_method_grab_keyboard.notify = handle_im_grab_keyboard;
|
||||||
wl_signal_add(&relay->input_method->events.destroy,
|
wl_signal_add(&relay->input_method->events.destroy,
|
||||||
&relay->input_method_destroy);
|
&relay->input_method_destroy);
|
||||||
relay->input_method_destroy.notify = handle_im_destroy;
|
relay->input_method_destroy.notify = handle_im_destroy;
|
||||||
|
|
Loading…
Reference in a new issue