Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

quickshell/nuguland/test-fixtures/ui/niri-integration-keyboard.c

Raw
// Weston-side keyboard events reach nested Niri's native grabs. Niri's wlr
// virtual keyboard forwards to clients and cannot confirm/cancel those grabs.
#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libweston/libweston.h>

struct controller {
    struct weston_compositor *compositor;
    struct wl_event_source *source;
    struct wl_listener destroy;
    int fd;
};
static int input(int fd, uint32_t mask, void *data) {
    (void)mask;
    struct controller *ctl = data;
    uint32_t command[3]; // expected nested client PID, evdev key, pressed
    assert(read(fd, command, sizeof(command)) == sizeof(command));
    assert(command[0] > 1 && command[2] <= 1);
    assert(command[1] == 1 || command[1] == 28 || command[1] == 29 || command[1] == 46);
    struct weston_seat *seat;
    struct weston_keyboard *keyboard = NULL;
    wl_list_for_each(seat, &ctl->compositor->seat_list, link) {
        struct weston_keyboard *candidate = weston_seat_get_keyboard(seat);
        if (!candidate || !candidate->focus || !candidate->focus->resource) continue;
        pid_t pid;
        wl_client_get_credentials(wl_resource_get_client(candidate->focus->resource), &pid, NULL, NULL);
        if (pid == (pid_t)command[0]) {
            assert(!keyboard);
            keyboard = candidate;
        }
    }
    assert(keyboard); // Never redirect input to an unrelated surface.
    struct timespec now;
    weston_compositor_get_time(&now);
    weston_keyboard_send_key(keyboard, &now, command[1], command[2]);
    xkb_state_update_key(keyboard->xkb_state.state, command[1] + 8, command[2] ? XKB_KEY_DOWN : XKB_KEY_UP);
    weston_keyboard_send_modifiers(keyboard, wl_display_next_serial(ctl->compositor->wl_display),
        xkb_state_serialize_mods(keyboard->xkb_state.state, XKB_STATE_MODS_DEPRESSED),
        xkb_state_serialize_mods(keyboard->xkb_state.state, XKB_STATE_MODS_LATCHED),
        xkb_state_serialize_mods(keyboard->xkb_state.state, XKB_STATE_MODS_LOCKED),
        xkb_state_serialize_layout(keyboard->xkb_state.state, XKB_STATE_LAYOUT_EFFECTIVE));
    return 0;
}
static void destroy(struct wl_listener *listener, void *data) {
    (void)data;
    struct controller *ctl = wl_container_of(listener, ctl, destroy);
    wl_event_source_remove(ctl->source);
    wl_list_remove(&ctl->destroy.link);
    close(ctl->fd);
    free(ctl);
}
WL_EXPORT int wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) {
    (void)argc; (void)argv;
    assert(getenv("NUGULAND_UI_SANDBOX") && !strcmp(getenv("HOME"), "/home/test"));
    struct controller *ctl = calloc(1, sizeof(*ctl));
    assert(ctl);
    ctl->compositor = compositor;
    ctl->fd = open("/run/user/1000/niri-integration-keyboard.fifo", O_RDWR | O_NONBLOCK);
    assert(ctl->fd >= 0);
    ctl->source = wl_event_loop_add_fd(wl_display_get_event_loop(compositor->wl_display), ctl->fd, WL_EVENT_READABLE, input, ctl);
    assert(ctl->source);
    weston_compositor_add_destroy_listener_once(compositor, &ctl->destroy, destroy);
    return 0;
}