Fix VT switching and multi-keyboard support
- Use wrapper struct to track keyboard pointer per-listener - Get keyboard from listener that fired event, not from seat - Properly clean up listeners on keyboard disconnect
This commit is contained in:
parent
1d3843f62a
commit
15f19afeb4
|
|
@ -12,9 +12,18 @@
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "wl_types.h"
|
#include "wl_types.h"
|
||||||
|
|
||||||
|
/* Wrapper struct for per-keyboard listeners */
|
||||||
|
struct wl_keyboard_listener {
|
||||||
|
struct wlr_keyboard *keyboard;
|
||||||
|
struct wl_listener key;
|
||||||
|
struct wl_listener modifiers;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
void handle_keyboard_key(struct wl_listener *listener, void *data);
|
void handle_keyboard_key(struct wl_listener *listener, void *data);
|
||||||
void handle_keyboard_modifiers(struct wl_listener *listener, void *data);
|
void handle_keyboard_modifiers(struct wl_listener *listener, void *data);
|
||||||
|
static void handle_keyboard_destroy(struct wl_listener *listener, void *data);
|
||||||
void handle_pointer_motion(struct wl_listener *listener, void *data);
|
void handle_pointer_motion(struct wl_listener *listener, void *data);
|
||||||
void handle_pointer_motion_absolute(struct wl_listener *listener, void *data);
|
void handle_pointer_motion_absolute(struct wl_listener *listener, void *data);
|
||||||
void handle_pointer_button(struct wl_listener *listener, void *data);
|
void handle_pointer_button(struct wl_listener *listener, void *data);
|
||||||
|
|
@ -61,13 +70,22 @@ real_pointer_update_global(struct wl_real_pointer_listener *pl)
|
||||||
static void
|
static void
|
||||||
handle_keyboard_destroy(struct wl_listener *listener, void *data)
|
handle_keyboard_destroy(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
(void)listener; (void)data;
|
(void)data;
|
||||||
INPUT_LISTENER_REMOVE(wl_state.real_keyboard_key_listener);
|
struct wl_keyboard_listener *kl =
|
||||||
INPUT_LISTENER_REMOVE(wl_state.real_keyboard_modifiers_listener);
|
wl_container_of(listener, kl, destroy);
|
||||||
INPUT_LISTENER_REMOVE(wl_state.real_keyboard_destroy_listener);
|
wl_list_remove(&kl->key.link);
|
||||||
|
wl_list_remove(&kl->modifiers.link);
|
||||||
|
wl_list_remove(&kl->destroy.link);
|
||||||
|
/* Clear global if this was the tracked keyboard */
|
||||||
|
if (wl_state.keyboard_dev) {
|
||||||
|
struct wlr_keyboard *kb = wlr_keyboard_from_input_device(wl_state.keyboard_dev);
|
||||||
|
if (kb == kl->keyboard) {
|
||||||
wl_state.real_keyboard_dev = NULL;
|
wl_state.real_keyboard_dev = NULL;
|
||||||
wl_state.keyboard_dev = NULL;
|
wl_state.keyboard_dev = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
free(kl);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
real_pointer_handle_motion(struct wl_listener *listener, void *data)
|
real_pointer_handle_motion(struct wl_listener *listener, void *data)
|
||||||
|
|
@ -160,19 +178,16 @@ handle_backend_new_input(struct wl_listener *listener, void *data)
|
||||||
}
|
}
|
||||||
if (wl_state.seat)
|
if (wl_state.seat)
|
||||||
wlr_seat_set_keyboard(wl_state.seat, kb);
|
wlr_seat_set_keyboard(wl_state.seat, kb);
|
||||||
/* Wire key events — use wlr_keyboard_group or attach to each device.
|
/* Wire key events with wrapper structs that track the keyboard */
|
||||||
* wlroots seat aggregates all keyboards automatically when we call
|
struct wl_keyboard_listener *kl = calloc(1, sizeof(*kl));
|
||||||
* wlr_seat_set_keyboard, but we still need per-device listeners for
|
if (kl) {
|
||||||
* the key events to reach our handler. Use dynamic allocation. */
|
kl->keyboard = kb;
|
||||||
struct wl_listener *key_l = calloc(1, sizeof(*key_l));
|
kl->key.notify = handle_keyboard_key;
|
||||||
struct wl_listener *mod_l = calloc(1, sizeof(*mod_l));
|
wl_signal_add(&kb->events.key, &kl->key);
|
||||||
if (key_l) {
|
kl->modifiers.notify = handle_keyboard_modifiers;
|
||||||
key_l->notify = handle_keyboard_key;
|
wl_signal_add(&kb->events.modifiers, &kl->modifiers);
|
||||||
wl_signal_add(&kb->events.key, key_l);
|
kl->destroy.notify = handle_keyboard_destroy;
|
||||||
}
|
wl_signal_add(&dev->events.destroy, &kl->destroy);
|
||||||
if (mod_l) {
|
|
||||||
mod_l->notify = handle_keyboard_modifiers;
|
|
||||||
wl_signal_add(&kb->events.modifiers, mod_l);
|
|
||||||
}
|
}
|
||||||
wwarning("wl_backend: keyboard wired dev=%p xkb_state=%s", (void*)dev,
|
wwarning("wl_backend: keyboard wired dev=%p xkb_state=%s", (void*)dev,
|
||||||
kb->xkb_state ? "yes" : "no");
|
kb->xkb_state ? "yes" : "no");
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,14 @@ int wWaylandKeyPress(unsigned int keycode, unsigned int modifiers);
|
||||||
#include "wl_types.h"
|
#include "wl_types.h"
|
||||||
#include <WINGs/WINGsP.h>
|
#include <WINGs/WINGsP.h>
|
||||||
|
|
||||||
|
/* Wrapper struct for per-keyboard listeners (defined in wl_input_fwd.c) */
|
||||||
|
struct wl_keyboard_listener {
|
||||||
|
struct wlr_keyboard *keyboard;
|
||||||
|
struct wl_listener key;
|
||||||
|
struct wl_listener modifiers;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
WMScreen *wl_get_wmscreen(void);
|
WMScreen *wl_get_wmscreen(void);
|
||||||
void W_WL_EnqueueEvent(struct W_Screen *scr, const WMEvent *ev, struct W_View *target);
|
void W_WL_EnqueueEvent(struct W_Screen *scr, const WMEvent *ev, struct W_View *target);
|
||||||
|
|
@ -24,19 +32,19 @@ void
|
||||||
handle_keyboard_key(struct wl_listener *listener, void *data)
|
handle_keyboard_key(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct wlr_keyboard_key_event *event = data;
|
struct wlr_keyboard_key_event *event = data;
|
||||||
(void)listener;
|
struct wl_keyboard_listener *kl =
|
||||||
|
wl_container_of(listener, kl, key);
|
||||||
wwarning("handle_keyboard_key: keycode=%u state=%d", event->keycode, event->state);
|
struct wlr_keyboard *kb = kl->keyboard;
|
||||||
|
|
||||||
if (!wl_state.seat)
|
if (!wl_state.seat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct wlr_keyboard *kb = wl_state.seat->keyboard_state.keyboard;
|
if (!kb || !kb->xkb_state) {
|
||||||
if (!kb) {
|
wwarning("handle_keyboard_key: no xkb_state for keycode=%u", event->keycode);
|
||||||
wwarning("handle_keyboard_key: no seat keyboard for event keycode=%u dev=%p", event->keycode, (void*)wl_state.keyboard_dev);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_seat_set_keyboard(wl_state.seat, kb);
|
||||||
wlr_seat_keyboard_notify_modifiers(wl_state.seat, &kb->modifiers);
|
wlr_seat_keyboard_notify_modifiers(wl_state.seat, &kb->modifiers);
|
||||||
|
|
||||||
uint32_t keycode = event->keycode + 8;
|
uint32_t keycode = event->keycode + 8;
|
||||||
|
|
@ -102,10 +110,12 @@ handle_keyboard_key(struct wl_listener *listener, void *data)
|
||||||
void
|
void
|
||||||
handle_keyboard_modifiers(struct wl_listener *listener, void *data)
|
handle_keyboard_modifiers(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
(void)listener; (void)data;
|
(void)data;
|
||||||
if (!wl_state.seat) return;
|
struct wl_keyboard_listener *kl =
|
||||||
struct wlr_keyboard *kb = wl_state.seat->keyboard_state.keyboard;
|
wl_container_of(listener, kl, modifiers);
|
||||||
if (!kb) return;
|
struct wlr_keyboard *kb = kl->keyboard;
|
||||||
|
if (!wl_state.seat || !kb) return;
|
||||||
|
wlr_seat_set_keyboard(wl_state.seat, kb);
|
||||||
wlr_seat_keyboard_notify_modifiers(wl_state.seat, &kb->modifiers);
|
wlr_seat_keyboard_notify_modifiers(wl_state.seat, &kb->modifiers);
|
||||||
/* Cache the real keyboard's depressed modifiers so pointer button
|
/* Cache the real keyboard's depressed modifiers so pointer button
|
||||||
* handlers can read them regardless of which keyboard the seat
|
* handlers can read them regardless of which keyboard the seat
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue