Skip to content
This repository has been archived by the owner on Jan 26, 2024. It is now read-only.

Commit

Permalink
implement input method keyboard grab
Browse files Browse the repository at this point in the history
  • Loading branch information
Shugyousha committed Jul 4, 2021
1 parent a644a4d commit 7e1e931
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions dwl.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ struct dwl_input_method_relay {
struct wl_listener input_method_commit;
struct wl_listener input_method_destroy;
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 {
Expand Down Expand Up @@ -372,6 +374,9 @@ void dwl_input_method_relay_set_focus(struct dwl_input_method_relay *relay,
struct dwl_text_input *dwl_text_input_create(
struct dwl_input_method_relay *relay,
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);

/* variables */
Expand Down Expand Up @@ -1307,6 +1312,26 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
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
keypress(struct wl_listener *listener, void *data)
{
Expand All @@ -1333,6 +1358,16 @@ keypress(struct wl_listener *listener, void *data)
handled = keybinding(mods, syms[i]) || 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. */
wlr_seat_set_keyboard(seat, kb->device);
wlr_seat_keyboard_notify_key(seat, event->time_msec,
Expand All @@ -1346,6 +1381,13 @@ keypressmod(struct wl_listener *listener, void *data)
/* This event is raised when a modifier key, such as shift or alt, is
* pressed. We simply communicate this to the client. */
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
* Wayland protocol - not wlroots. We assign all connected keyboards to the
Expand Down Expand Up @@ -1403,6 +1445,38 @@ mapnotify(struct wl_listener *listener, void *data)
applyrules(c);
}

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
monocle(Monitor *m)
{
Expand Down Expand Up @@ -2593,6 +2667,9 @@ static void relay_handle_input_method(struct wl_listener *listener,
wl_signal_add(&relay->input_method->events.new_popup_surface,
&relay->input_method_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,
&relay->input_method_destroy);
relay->input_method_destroy.notify = handle_im_destroy;
Expand Down

0 comments on commit 7e1e931

Please sign in to comment.