64 lines
3.2 KiB
C
64 lines
3.2 KiB
C
/* Private-display integration helper; stdin uses Linux evdev key codes.
|
|
* Compile via dev/build-input-probe.sh inside the temporary tools shell. */
|
|
#define _GNU_SOURCE
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
#include <wayland-client.h>
|
|
#include <xkbcommon/xkbcommon.h>
|
|
#include "virtual-keyboard-client-protocol.h"
|
|
static struct wl_seat *seat;
|
|
static struct zwp_virtual_keyboard_manager_v1 *manager;
|
|
static void global(void *data, struct wl_registry *registry, uint32_t id,
|
|
const char *interface, uint32_t version) {
|
|
(void)data; (void)version;
|
|
if (!strcmp(interface,"wl_seat"))
|
|
seat = wl_registry_bind(registry,id,&wl_seat_interface,1);
|
|
else if (!strcmp(interface,"zwp_virtual_keyboard_manager_v1"))
|
|
manager = wl_registry_bind(registry,id,&zwp_virtual_keyboard_manager_v1_interface,1);
|
|
}
|
|
static void removed(void *data,struct wl_registry *registry,uint32_t id) {
|
|
(void)data; (void)registry; (void)id;
|
|
}
|
|
int main(void) {
|
|
/* The caller supplies the separately created scratch Wayland runtime. */
|
|
assert(getenv("WAYLAND_DISPLAY") && getenv("XDG_RUNTIME_DIR"));
|
|
struct wl_display *display = wl_display_connect(NULL); assert(display);
|
|
struct wl_registry *registry = wl_display_get_registry(display);
|
|
struct wl_registry_listener listener={global,removed};
|
|
wl_registry_add_listener(registry,&listener,NULL); wl_display_roundtrip(display);
|
|
assert(seat && manager);
|
|
struct zwp_virtual_keyboard_v1 *keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(manager,seat);
|
|
struct xkb_context *context=xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
struct xkb_rule_names names={.rules="evdev",.model="pc105",.layout="us"};
|
|
struct xkb_keymap *map=xkb_keymap_new_from_names(context,&names,XKB_KEYMAP_COMPILE_NO_FLAGS); assert(map);
|
|
struct xkb_state *state=xkb_state_new(map); assert(state);
|
|
char *text=xkb_keymap_get_as_string(map,XKB_KEYMAP_FORMAT_TEXT_V1);
|
|
size_t size=strlen(text)+1;
|
|
int fd=memfd_create("hydra-private-keymap",0); assert(fd>=0);
|
|
assert(write(fd,text,size)==(ssize_t)size);
|
|
zwp_virtual_keyboard_v1_keymap(keyboard,WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,fd,size);
|
|
wl_display_roundtrip(display); close(fd); free(text);
|
|
char command[16]; unsigned key; unsigned tick=0;
|
|
while (scanf("%15s %u",command,&key)==2) {
|
|
if (!strcmp(command,"wait")) { usleep(key*1000); continue; }
|
|
unsigned down=!strcmp(command,"down");
|
|
assert(down || !strcmp(command,"up"));
|
|
xkb_state_update_key(state,key+8,down?XKB_KEY_DOWN:XKB_KEY_UP);
|
|
zwp_virtual_keyboard_v1_key(keyboard,++tick,key,down);
|
|
zwp_virtual_keyboard_v1_modifiers(keyboard,
|
|
xkb_state_serialize_mods(state,XKB_STATE_MODS_DEPRESSED),
|
|
xkb_state_serialize_mods(state,XKB_STATE_MODS_LATCHED),
|
|
xkb_state_serialize_mods(state,XKB_STATE_MODS_LOCKED),
|
|
xkb_state_serialize_layout(state,XKB_STATE_LAYOUT_EFFECTIVE));
|
|
assert(wl_display_roundtrip(display)>=0);
|
|
}
|
|
zwp_virtual_keyboard_v1_destroy(keyboard); wl_display_roundtrip(display);
|
|
xkb_state_unref(state); xkb_keymap_unref(map); xkb_context_unref(context);
|
|
wl_display_disconnect(display);
|
|
return 0;
|
|
}
|