forked from mirror/dwl
implement input method keyboard grab
This commit is contained in:
parent
27bf627a97
commit
ac1aef7ead
1 changed files with 77 additions and 0 deletions
77
dwl.c
77
dwl.c
|
@ -227,6 +227,8 @@ struct dwl_input_method_relay {
|
||||||
struct wl_listener input_method_commit;
|
struct wl_listener input_method_commit;
|
||||||
struct wl_listener input_method_destroy;
|
struct wl_listener input_method_destroy;
|
||||||
struct wl_listener input_method_new_popup_surface;
|
struct wl_listener input_method_new_popup_surface;
|
||||||
|
struct wl_listener input_method_grab_keyboard;
|
||||||
|
struct wl_listener input_method_keyboard_grab_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dwl_text_input {
|
struct dwl_text_input {
|
||||||
|
@ -377,6 +379,9 @@ void dwl_input_method_relay_set_focus(struct dwl_input_method_relay *relay,
|
||||||
struct dwl_text_input *dwl_text_input_create(
|
struct dwl_text_input *dwl_text_input_create(
|
||||||
struct dwl_input_method_relay *relay,
|
struct dwl_input_method_relay *relay,
|
||||||
struct wlr_text_input_v3 *text_input);
|
struct wlr_text_input_v3 *text_input);
|
||||||
|
static void handle_im_grab_keyboard(struct wl_listener *listener, void *data);
|
||||||
|
static void handle_im_keyboard_grab_destroy(struct wl_listener *listener,
|
||||||
|
void *data);
|
||||||
static void zoom(const Arg *arg);
|
static void zoom(const Arg *arg);
|
||||||
|
|
||||||
/* variables */
|
/* variables */
|
||||||
|
@ -1369,6 +1374,26 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 https://github.com/swaywm/wlroots/issues/2322
|
||||||
|
*/
|
||||||
|
static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab(Keyboard* kb) {
|
||||||
|
struct wlr_input_method_v2 *input_method = input_relay->input_method;
|
||||||
|
struct wlr_virtual_keyboard_v1 *virtual_keyboard =
|
||||||
|
wlr_input_device_get_virtual_keyboard(kb->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;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
keypress(struct wl_listener *listener, void *data)
|
keypress(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
@ -1397,6 +1422,16 @@ keypress(struct wl_listener *listener, void *data)
|
||||||
handled = keybinding(mods, syms[i]) || handled;
|
handled = keybinding(mods, syms[i]) || handled;
|
||||||
|
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
|
/* if there is a keyboard grab, we send the key there */
|
||||||
|
struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(kb);
|
||||||
|
if (kb_grab) {
|
||||||
|
wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab,
|
||||||
|
kb->device->keyboard);
|
||||||
|
wlr_input_method_keyboard_grab_v2_send_key(kb_grab,
|
||||||
|
event->time_msec, event->keycode, event->state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pass unhandled keycodes along to the client. */
|
/* Pass unhandled keycodes along to the client. */
|
||||||
wlr_seat_set_keyboard(seat, kb->device);
|
wlr_seat_set_keyboard(seat, kb->device);
|
||||||
wlr_seat_keyboard_notify_key(seat, event->time_msec,
|
wlr_seat_keyboard_notify_key(seat, event->time_msec,
|
||||||
|
@ -1410,6 +1445,13 @@ keypressmod(struct wl_listener *listener, void *data)
|
||||||
/* This event is raised when a modifier key, such as shift or alt, is
|
/* This event is raised when a modifier key, such as shift or alt, is
|
||||||
* pressed. We simply communicate this to the client. */
|
* pressed. We simply communicate this to the client. */
|
||||||
Keyboard *kb = wl_container_of(listener, kb, modifiers);
|
Keyboard *kb = wl_container_of(listener, kb, modifiers);
|
||||||
|
struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(kb);
|
||||||
|
if (kb_grab) {
|
||||||
|
wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab,
|
||||||
|
&kb->device->keyboard->modifiers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A seat can only have one keyboard, but this is a limitation of the
|
* A seat can only have one keyboard, but this is a limitation of the
|
||||||
* Wayland protocol - not wlroots. We assign all connected keyboards to the
|
* Wayland protocol - not wlroots. We assign all connected keyboards to the
|
||||||
|
@ -1489,6 +1531,38 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
c->mon->un_map = 1;
|
c->mon->un_map = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) {
|
||||||
|
struct dwl_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(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 handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct dwl_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
monocle(Monitor *m)
|
monocle(Monitor *m)
|
||||||
{
|
{
|
||||||
|
@ -2487,6 +2561,9 @@ static void relay_handle_input_method(struct wl_listener *listener,
|
||||||
wl_signal_add(&relay->input_method->events.new_popup_surface,
|
wl_signal_add(&relay->input_method->events.new_popup_surface,
|
||||||
&relay->input_method_new_popup_surface);
|
&relay->input_method_new_popup_surface);
|
||||||
relay->input_method_new_popup_surface.notify = handle_im_new_popup_surface;
|
relay->input_method_new_popup_surface.notify = handle_im_new_popup_surface;
|
||||||
|
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