mirror of
https://codeberg.org/dwl/dwl.git
synced 2025-12-17 18:33:20 +00:00
implement input method keyboard grab
Co-authored-by: Leonardo Hernández Hernández <leohdz172@protonmail.com>
This commit is contained in:
parent
ba92620324
commit
970bc744a8
82
dwl.c
82
dwl.c
@ -153,6 +153,8 @@ typedef struct {
|
|||||||
struct wl_listener commit;
|
struct wl_listener commit;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener new_popup;
|
struct wl_listener new_popup;
|
||||||
|
struct wl_listener grab_keyboard;
|
||||||
|
struct wl_listener keyboard_grab_destroy;
|
||||||
} IMRelay;
|
} IMRelay;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -300,6 +302,7 @@ static void createtextinput(struct wl_listener *listener, void *data);
|
|||||||
static void cursorframe(struct wl_listener *listener, void *data);
|
static void cursorframe(struct wl_listener *listener, void *data);
|
||||||
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
||||||
static void destroyinputmethod(struct wl_listener *listener, void *data);
|
static void destroyinputmethod(struct wl_listener *listener, void *data);
|
||||||
|
static void destroyimkeyboardgrab(struct wl_listener *listener, void *data);
|
||||||
static void destroyimpopup(struct wl_listener *listener, void *data);
|
static void destroyimpopup(struct wl_listener *listener, void *data);
|
||||||
static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
|
static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
static void destroynotify(struct wl_listener *listener, void *data);
|
static void destroynotify(struct wl_listener *listener, void *data);
|
||||||
@ -314,6 +317,8 @@ static void focusmon(const Arg *arg);
|
|||||||
static void focusstack(const Arg *arg);
|
static void focusstack(const Arg *arg);
|
||||||
static Client *focustop(Monitor *m);
|
static Client *focustop(Monitor *m);
|
||||||
static void fullscreennotify(struct wl_listener *listener, void *data);
|
static void fullscreennotify(struct wl_listener *listener, void *data);
|
||||||
|
static struct wlr_input_method_keyboard_grab_v2 *getimgrabfromkeyboard(Keyboard *kb);
|
||||||
|
static void imgrabkeyboard(struct wl_listener *listener, void *data);
|
||||||
static void impopupfocusedsurfaceunmap(struct wl_listener *listener, void *data);
|
static void impopupfocusedsurfaceunmap(struct wl_listener *listener, void *data);
|
||||||
static void impopupupdate(InputPopup *popup);
|
static void impopupupdate(InputPopup *popup);
|
||||||
static void impopupsetfocus(InputPopup *popup, struct wlr_surface *surface);
|
static void impopupsetfocus(InputPopup *popup, struct wlr_surface *surface);
|
||||||
@ -1024,6 +1029,7 @@ createinputmethod(struct wl_listener *listener, void *data)
|
|||||||
LISTEN(&relay->input_method->events.commit, &relay->commit, commitinputmethod);
|
LISTEN(&relay->input_method->events.commit, &relay->commit, commitinputmethod);
|
||||||
LISTEN(&relay->input_method->events.new_popup_surface, &relay->new_popup, createimpopup);
|
LISTEN(&relay->input_method->events.new_popup_surface, &relay->new_popup, createimpopup);
|
||||||
LISTEN(&relay->input_method->events.destroy, &relay->destroy, destroyinputmethod);
|
LISTEN(&relay->input_method->events.destroy, &relay->destroy, destroyinputmethod);
|
||||||
|
LISTEN(&relay->input_method->events.grab_keyboard, &relay->grab_keyboard, imgrabkeyboard);
|
||||||
|
|
||||||
text_input = relaygetfocusabletextinput(relay);
|
text_input = relaygetfocusabletextinput(relay);
|
||||||
if (text_input) {
|
if (text_input) {
|
||||||
@ -1312,6 +1318,21 @@ destroyinputmethod(struct wl_listener *listener, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
destroyimkeyboardgrab(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
IMRelay *relay = wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||||
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||||
|
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
||||||
|
|
||||||
|
if (keyboard_grab->keyboard) {
|
||||||
|
/* send modifier state to original client */
|
||||||
|
Keyboard *kb = keyboard_grab->keyboard->data;
|
||||||
|
wlr_seat_set_keyboard(seat, kb->device);
|
||||||
|
wlr_seat_keyboard_notify_modifiers(seat, &kb->device->keyboard->modifiers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
destroyimpopup(struct wl_listener *listener, void *data)
|
destroyimpopup(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@ -1553,6 +1574,44 @@ fullscreennotify(struct wl_listener *listener, void *data)
|
|||||||
setfullscreen(c, client_wants_fullscreen(c));
|
setfullscreen(c, client_wants_fullscreen(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
*/
|
||||||
|
struct wlr_input_method_keyboard_grab_v2 *
|
||||||
|
getimgrabfromkeyboard(Keyboard *kb)
|
||||||
|
{
|
||||||
|
struct wlr_input_method_v2 *input_method = input_method_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
|
||||||
|
imgrabkeyboard(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
IMRelay *relay = wl_container_of(listener, relay, 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);
|
||||||
|
|
||||||
|
LISTEN(&keyboard_grab->events.destroy, &relay->keyboard_grab_destroy,
|
||||||
|
destroyimkeyboardgrab);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
impopupfocusedsurfaceunmap(struct wl_listener *listener, void *data)
|
impopupfocusedsurfaceunmap(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@ -1811,8 +1870,18 @@ 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 = getimgrabfromkeyboard(kb);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
wlr_seat_keyboard_notify_key(seat, event->time_msec,
|
wlr_seat_keyboard_notify_key(seat, event->time_msec,
|
||||||
event->keycode, event->state);
|
event->keycode, event->state);
|
||||||
}
|
}
|
||||||
@ -1824,6 +1893,8 @@ 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 = getimgrabfromkeyboard(kb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
@ -1831,9 +1902,14 @@ keypressmod(struct wl_listener *listener, void *data)
|
|||||||
* wlr_seat handles this transparently.
|
* wlr_seat handles this transparently.
|
||||||
*/
|
*/
|
||||||
wlr_seat_set_keyboard(seat, kb->device);
|
wlr_seat_set_keyboard(seat, kb->device);
|
||||||
/* Send modifiers to the client. */
|
if (kb_grab) {
|
||||||
wlr_seat_keyboard_notify_modifiers(seat,
|
wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab,
|
||||||
&kb->device->keyboard->modifiers);
|
&kb->device->keyboard->modifiers);
|
||||||
|
} else {
|
||||||
|
/* Send modifiers to the client. */
|
||||||
|
wlr_seat_keyboard_notify_modifiers(seat,
|
||||||
|
&kb->device->keyboard->modifiers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user