Add keyboards
parent
fe17fc2e68
commit
fcfa22d8a7
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
struct xkb_context;
|
||||||
|
struct xkb_keymap;
|
||||||
|
struct xkb_state;
|
||||||
|
|
||||||
|
struct keyboard {
|
||||||
|
struct wl_keyboard* wl_keyboard;
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
struct xkb_context* context;
|
||||||
|
struct xkb_keymap* keymap;
|
||||||
|
struct xkb_state* state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct keyboard_collection {
|
||||||
|
struct wl_list keyboards;
|
||||||
|
void (*on_event)(struct keyboard_collection*, struct keyboard*,
|
||||||
|
uint32_t key, bool is_pressed);
|
||||||
|
void* userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct keyboard_collection* keyboard_collection_new(void);
|
||||||
|
void keyboard_collection_destroy(struct keyboard_collection*);
|
||||||
|
|
||||||
|
int keyboard_collection_add_wl_keyboard(struct keyboard_collection* self,
|
||||||
|
struct wl_keyboard* wl_keyboard);
|
||||||
|
void keyboard_collection_remove_wl_keyboard(struct keyboard_collection* self,
|
||||||
|
struct wl_keyboard* wl_keyboard);
|
|
@ -28,6 +28,7 @@ libm = cc.find_library('m', required: false)
|
||||||
librt = cc.find_library('rt', required: false)
|
librt = cc.find_library('rt', required: false)
|
||||||
|
|
||||||
pixman = dependency('pixman-1')
|
pixman = dependency('pixman-1')
|
||||||
|
xkbcommon = dependency('xkbcommon')
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
libvncclient = dependency('libvncclient')
|
libvncclient = dependency('libvncclient')
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ sources = [
|
||||||
'src/shm.c',
|
'src/shm.c',
|
||||||
'src/seat.c',
|
'src/seat.c',
|
||||||
'src/pointer.c',
|
'src/pointer.c',
|
||||||
|
'src/keyboard.c',
|
||||||
'src/strlcpy.c',
|
'src/strlcpy.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -54,6 +56,7 @@ dependencies = [
|
||||||
libm,
|
libm,
|
||||||
librt,
|
librt,
|
||||||
pixman,
|
pixman,
|
||||||
|
xkbcommon,
|
||||||
aml,
|
aml,
|
||||||
wayland_client,
|
wayland_client,
|
||||||
libvncclient,
|
libvncclient,
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
struct keyboard* keyboard_new(struct wl_keyboard* wl_keyboard)
|
||||||
|
{
|
||||||
|
struct keyboard* self = calloc(1, sizeof(*self));
|
||||||
|
if (!self)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
self->wl_keyboard = wl_keyboard;
|
||||||
|
self->context = xkb_context_new(0);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_destroy(struct keyboard* self)
|
||||||
|
{
|
||||||
|
if (self->state)
|
||||||
|
xkb_state_unref(self->state);
|
||||||
|
|
||||||
|
if (self->keymap)
|
||||||
|
xkb_keymap_unref(self->keymap);
|
||||||
|
|
||||||
|
xkb_context_unref(self->context);
|
||||||
|
wl_keyboard_destroy(self->wl_keyboard);
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct keyboard_collection* keyboard_collection_new(void)
|
||||||
|
{
|
||||||
|
struct keyboard_collection* self = calloc(1, sizeof(*self));
|
||||||
|
if (!self)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wl_list_init(&self->keyboards);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_collection_destroy(struct keyboard_collection* self)
|
||||||
|
{
|
||||||
|
struct keyboard* keyboard;
|
||||||
|
struct keyboard* tmp;
|
||||||
|
|
||||||
|
wl_list_for_each_safe(keyboard, tmp, &self->keyboards, link) {
|
||||||
|
wl_list_remove(&keyboard->link);
|
||||||
|
keyboard_destroy(keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct keyboard* keyboard_collection_find_wl_keyboard(
|
||||||
|
struct keyboard_collection* self, struct wl_keyboard* wl_keyboard)
|
||||||
|
{
|
||||||
|
struct keyboard* keyboard;
|
||||||
|
wl_list_for_each(keyboard, &self->keyboards, link)
|
||||||
|
if (keyboard->wl_keyboard == wl_keyboard)
|
||||||
|
return keyboard;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_keymap(void* data, struct wl_keyboard* wl_keyboard,
|
||||||
|
enum wl_keyboard_keymap_format format, int32_t fd,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
struct keyboard_collection* self = data;
|
||||||
|
struct keyboard* keyboard =
|
||||||
|
keyboard_collection_find_wl_keyboard(self, wl_keyboard);
|
||||||
|
assert(keyboard);
|
||||||
|
|
||||||
|
// TODO: Ignore keyboard if no proper format is available?
|
||||||
|
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
|
||||||
|
|
||||||
|
char* buffer = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
if (keyboard->state)
|
||||||
|
xkb_state_unref(keyboard->state);
|
||||||
|
|
||||||
|
if (keyboard->keymap)
|
||||||
|
xkb_keymap_unref(keyboard->keymap);
|
||||||
|
|
||||||
|
keyboard->keymap = xkb_keymap_new_from_string(keyboard->context,
|
||||||
|
buffer, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
|
||||||
|
assert(keyboard->keymap);
|
||||||
|
|
||||||
|
munmap(buffer, size);
|
||||||
|
|
||||||
|
keyboard->state = xkb_state_new(keyboard->keymap);
|
||||||
|
assert(keyboard->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_enter(void* data, struct wl_keyboard* wl_keyboard,
|
||||||
|
uint32_t serial, struct wl_surface* surface,
|
||||||
|
struct wl_array* keys)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_leave(void* data, struct wl_keyboard* wl_keyboard,
|
||||||
|
uint32_t serial, struct wl_surface* surface)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum xkb_key_direction xbk_key_direction_from_wl_keyboard_key_state(
|
||||||
|
enum wl_keyboard_key_state state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case WL_KEYBOARD_KEY_STATE_PRESSED:
|
||||||
|
return XKB_KEY_DOWN;
|
||||||
|
case WL_KEYBOARD_KEY_STATE_RELEASED:
|
||||||
|
return XKB_KEY_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
abort();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_key(void* data, struct wl_keyboard* wl_keyboard,
|
||||||
|
uint32_t serial, uint32_t t, uint32_t key,
|
||||||
|
enum wl_keyboard_key_state state)
|
||||||
|
{
|
||||||
|
struct keyboard_collection* self = data;
|
||||||
|
struct keyboard* keyboard =
|
||||||
|
keyboard_collection_find_wl_keyboard(self, wl_keyboard);
|
||||||
|
assert(keyboard);
|
||||||
|
|
||||||
|
enum xkb_key_direction dir =
|
||||||
|
xbk_key_direction_from_wl_keyboard_key_state(state);
|
||||||
|
xkb_state_update_key(keyboard->state, key + 8, dir);
|
||||||
|
|
||||||
|
self->on_event(self, keyboard, key + 8,
|
||||||
|
state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_modifiers(void* data, struct wl_keyboard* wl_keyboard,
|
||||||
|
uint32_t serial, uint32_t depressed, uint32_t latched,
|
||||||
|
uint32_t locked, uint32_t group)
|
||||||
|
{
|
||||||
|
struct keyboard_collection* self = data;
|
||||||
|
struct keyboard* keyboard =
|
||||||
|
keyboard_collection_find_wl_keyboard(self, wl_keyboard);
|
||||||
|
assert(keyboard);
|
||||||
|
|
||||||
|
xkb_state_update_mask(keyboard->state, depressed, latched, locked, 0, 0,
|
||||||
|
group);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_repeat_info(void* data, struct wl_keyboard* wl_keyboard,
|
||||||
|
int32_t rate, int32_t delay)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wl_keyboard_listener keyboard_listener = {
|
||||||
|
.keymap = keyboard_keymap,
|
||||||
|
.enter = keyboard_enter,
|
||||||
|
.leave = keyboard_leave,
|
||||||
|
.key = keyboard_key,
|
||||||
|
.modifiers = keyboard_modifiers,
|
||||||
|
.repeat_info = keyboard_repeat_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
int keyboard_collection_add_wl_keyboard(struct keyboard_collection* self,
|
||||||
|
struct wl_keyboard* wl_keyboard)
|
||||||
|
{
|
||||||
|
struct keyboard* keyboard = keyboard_new(wl_keyboard);
|
||||||
|
if (!keyboard)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wl_list_insert(&self->keyboards, &keyboard->link);
|
||||||
|
wl_keyboard_add_listener(keyboard->wl_keyboard, &keyboard_listener, self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_collection_remove_wl_keyboard(struct keyboard_collection* self,
|
||||||
|
struct wl_keyboard* wl_keyboard)
|
||||||
|
{
|
||||||
|
struct keyboard* keyboard =
|
||||||
|
keyboard_collection_find_wl_keyboard(self, wl_keyboard);
|
||||||
|
wl_list_remove(&keyboard->link);
|
||||||
|
free(keyboard);
|
||||||
|
}
|
36
src/main.c
36
src/main.c
|
@ -11,11 +11,13 @@
|
||||||
#include <aml.h>
|
#include <aml.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <rfb/rfbclient.h>
|
#include <rfb/rfbclient.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
#include "xdg-shell.h"
|
#include "xdg-shell.h"
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
#include "seat.h"
|
#include "seat.h"
|
||||||
#include "pointer.h"
|
#include "pointer.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
int width, height, stride;
|
int width, height, stride;
|
||||||
|
@ -41,6 +43,7 @@ static struct wl_shm* wl_shm;
|
||||||
static struct xdg_wm_base* xdg_wm_base;
|
static struct xdg_wm_base* xdg_wm_base;
|
||||||
static struct wl_list seats;
|
static struct wl_list seats;
|
||||||
struct pointer_collection* pointers;
|
struct pointer_collection* pointers;
|
||||||
|
struct keyboard_collection* keyboards;
|
||||||
|
|
||||||
static enum wl_shm_format wl_shm_format;
|
static enum wl_shm_format wl_shm_format;
|
||||||
static bool have_format = false;
|
static bool have_format = false;
|
||||||
|
@ -59,6 +62,15 @@ static void on_seat_capability_change(struct seat* seat)
|
||||||
} else {
|
} else {
|
||||||
// TODO Remove
|
// TODO Remove
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||||
|
// TODO: Make sure this only happens once
|
||||||
|
struct wl_keyboard* wl_keyboard =
|
||||||
|
wl_seat_get_keyboard(seat->wl_seat);
|
||||||
|
keyboard_collection_add_wl_keyboard(keyboards, wl_keyboard);
|
||||||
|
} else {
|
||||||
|
// TODO Remove
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registry_add(void* data, struct wl_registry* registry, uint32_t id,
|
static void registry_add(void* data, struct wl_registry* registry, uint32_t id,
|
||||||
|
@ -337,6 +349,21 @@ void on_pointer_event(struct pointer_collection* collection,
|
||||||
SendPointerEvent(client, x, y, pointer->pressed);
|
SendPointerEvent(client, x, y, pointer->pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on_keyboard_event(struct keyboard_collection* collection,
|
||||||
|
struct keyboard* keyboard, uint32_t key, bool is_pressed)
|
||||||
|
{
|
||||||
|
rfbClient* client = collection->userdata;
|
||||||
|
|
||||||
|
// TODO handle multiple symbols
|
||||||
|
xkb_keysym_t symbol = xkb_state_key_get_one_sym(keyboard->state, key);
|
||||||
|
|
||||||
|
char name[256];
|
||||||
|
xkb_keysym_get_name(symbol, name, sizeof(name));
|
||||||
|
printf("Got %s %d\n", name, is_pressed ? 0 : 1);
|
||||||
|
|
||||||
|
SendKeyEvent(client, symbol, is_pressed);
|
||||||
|
}
|
||||||
|
|
||||||
rfbBool rfb_client_alloc_fb(rfbClient* cl)
|
rfbBool rfb_client_alloc_fb(rfbClient* cl)
|
||||||
{
|
{
|
||||||
int stride = cl->width * 4; // TODO?
|
int stride = cl->width * 4; // TODO?
|
||||||
|
@ -484,6 +511,12 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
pointers->on_frame = on_pointer_event;
|
pointers->on_frame = on_pointer_event;
|
||||||
|
|
||||||
|
keyboards = keyboard_collection_new();
|
||||||
|
if (!keyboards)
|
||||||
|
goto keyboards_failure;
|
||||||
|
|
||||||
|
keyboards->on_event = on_keyboard_event;
|
||||||
|
|
||||||
wl_registry = wl_display_get_registry(wl_display);
|
wl_registry = wl_display_get_registry(wl_display);
|
||||||
if (!wl_registry)
|
if (!wl_registry)
|
||||||
goto registry_failure;
|
goto registry_failure;
|
||||||
|
@ -507,6 +540,7 @@ int main(int argc, char* argv[])
|
||||||
goto vnc_failure;
|
goto vnc_failure;
|
||||||
|
|
||||||
pointers->userdata = vnc;
|
pointers->userdata = vnc;
|
||||||
|
keyboards->userdata = vnc;
|
||||||
|
|
||||||
wl_display_dispatch(wl_display);
|
wl_display_dispatch(wl_display);
|
||||||
|
|
||||||
|
@ -528,6 +562,8 @@ vnc_failure:
|
||||||
|
|
||||||
wl_registry_destroy(wl_registry);
|
wl_registry_destroy(wl_registry);
|
||||||
registry_failure:
|
registry_failure:
|
||||||
|
keyboard_collection_destroy(keyboards);
|
||||||
|
keyboards_failure:
|
||||||
pointer_collection_destroy(pointers);
|
pointer_collection_destroy(pointers);
|
||||||
pointer_failure:
|
pointer_failure:
|
||||||
event_handler_failure:
|
event_handler_failure:
|
||||||
|
|
Loading…
Reference in New Issue