From d97efedac4de83da7e427ab8d37dd99aaf0b356d Mon Sep 17 00:00:00 2001 From: beatwise Date: Sat, 23 Nov 2024 14:29:20 +0100 Subject: [PATCH] xkbcommon support --- demo/xcb_cairo/Makefile | 6 +- demo/xcb_cairo/nuklear_xcb.h | 127 +++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 9 deletions(-) diff --git a/demo/xcb_cairo/Makefile b/demo/xcb_cairo/Makefile index c1dd635de..9108165be 100644 --- a/demo/xcb_cairo/Makefile +++ b/demo/xcb_cairo/Makefile @@ -1,6 +1,6 @@ # Target BIN = demo -CFLAGS += -std=c89 -pedantic +CFLAGS += -std=c89 -pedantic -g LDFLAGS += -lm SRC = ${wildcard *.c} OBJ = $(SRC:.c=.o) @@ -10,8 +10,8 @@ CFLAGS += ${shell pkg-config --cflags freetype2} LDFLAGS += ${shell pkg-config --libs freetype2} # XCB -CFLAGS += ${shell pkg-config --cflags xcb xcb-util xcb-keysyms} -LDFLAGS += ${shell pkg-config --libs xcb xcb-util xcb-keysyms} +CFLAGS += ${shell pkg-config --cflags xcb xcb-util xcb-keysyms xkbcommon xkbcommon-x11} +LDFLAGS += ${shell pkg-config --libs xcb xcb-util xcb-keysyms xkbcommon xkbcommon-x11} # Cairo CFLAGS += ${shell pkg-config --cflags cairo} diff --git a/demo/xcb_cairo/nuklear_xcb.h b/demo/xcb_cairo/nuklear_xcb.h index 6bf0165cc..3125bab20 100644 --- a/demo/xcb_cairo/nuklear_xcb.h +++ b/demo/xcb_cairo/nuklear_xcb.h @@ -87,6 +87,10 @@ NK_API void nk_xcb_resize_cairo_surface(struct nk_xcb_context *xcb_ctx, void *su #include #include +#include +#include + + #if defined _XOPEN_SOURCE && _XOPEN_SOURCE >= 600 || \ defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L #include @@ -110,6 +114,23 @@ NK_API void nk_xcb_resize_cairo_surface(struct nk_xcb_context *xcb_ctx, void *su #define NK_XCB_TO_CAIRO(x) ((double) x / 255.0) #define NK_XCB_DEG_TO_RAD(x) ((double) x * NK_XCB_PI / 180.0) +typedef struct xkb_context xkb_context; +typedef struct xkb_keymap xkb_keymap; +typedef struct xkb_state xkb_state; +typedef struct xkbcommon_context xkbcommon_context; +typedef struct nk_xcb_context nk_xcb_context; + +struct xkbcommon_context +{ + struct xkb_context *ctx; + struct xkb_keymap *keymap; + struct xkb_state *state; +}; + +NK_INTERN void xkbcommon_free(xkbcommon_context *kbdctx); +NK_INTERN xkbcommon_context *xkbcommon_init(xcb_connection_t *conn); +NK_INTERN xkb_keysym_t keycode_to_keysym(nk_xcb_context *ctx, xkb_keycode_t keycode, int pressed); + struct nk_cairo_context { cairo_surface_t *surface; cairo_t *cr; @@ -126,7 +147,8 @@ struct nk_xcb_context { xcb_connection_t *conn; int screennum; xcb_window_t window; - xcb_key_symbols_t *key_symbols; + /* xcb_key_symbols_t *key_symbols; */ + xkbcommon_context *xkbcommon_ctx; #ifdef NK_XCB_MIN_FRAME_TIME unsigned long last_render; #endif /* NK_XCB_MIN_FRAME_TIME */ @@ -187,7 +209,8 @@ NK_API struct nk_xcb_context *nk_xcb_init(const char *title, int pos_x, int pos_ xcb_ctx->conn = conn; xcb_ctx->screennum = screenNum; xcb_ctx->window = window; - xcb_ctx->key_symbols = xcb_key_symbols_alloc(xcb_ctx->conn); + /* xcb_ctx->key_symbols = xcb_key_symbols_alloc(xcb_ctx->conn); */ + xcb_ctx->xkbcommon_ctx = xkbcommon_init(conn); xcb_ctx->del_atom = del_atom; xcb_ctx->width = width; xcb_ctx->height = height; @@ -197,8 +220,9 @@ NK_API struct nk_xcb_context *nk_xcb_init(const char *title, int pos_x, int pos_ NK_API void nk_xcb_free(struct nk_xcb_context *xcb_ctx) { + xkbcommon_free(xcb_ctx->xkbcommon_ctx); free(xcb_ctx->del_atom); - xcb_key_symbols_free(xcb_ctx->key_symbols); + /* xcb_key_symbols_free(xcb_ctx->key_symbols); */ xcb_disconnect(xcb_ctx->conn); free(xcb_ctx); } @@ -225,7 +249,9 @@ NK_API int nk_xcb_handle_event(struct nk_xcb_context *xcb_ctx, struct nk_context { int press = (XCB_EVENT_RESPONSE_TYPE(event)) == XCB_KEY_PRESS; xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event; - xcb_keysym_t sym = xcb_key_symbols_get_keysym(xcb_ctx->key_symbols, kp->detail, kp->state); + /* xcb_keysym_t sym = xcb_key_symbols_get_keysym(xcb_ctx->key_symbols, kp->detail, kp->state);*/ + xcb_keysym_t sym = keycode_to_keysym(xcb_ctx, kp->detail, press); + switch (sym) { case XK_Shift_L: case XK_Shift_R: @@ -302,7 +328,8 @@ NK_API int nk_xcb_handle_event(struct nk_xcb_context *xcb_ctx, struct nk_context !xcb_is_misc_function_key(sym) && !xcb_is_modifier_key(sym) ) { - nk_input_char(nk_ctx, sym); + /* nk_input_char(nk_ctx, sym); */ + nk_input_unicode(nk_ctx, sym); } else { printf("state: %x code: %x sum: %x\n", kp->state, kp->detail, sym); @@ -366,7 +393,7 @@ NK_API int nk_xcb_handle_event(struct nk_xcb_context *xcb_ctx, struct nk_context } break; case XCB_KEYMAP_NOTIFY: - xcb_refresh_keyboard_mapping(xcb_ctx->key_symbols, (xcb_mapping_notify_event_t *)event); + /* xcb_refresh_keyboard_mapping(xcb_ctx->key_symbols, (xcb_mapping_notify_event_t *)event); */ break; case XCB_EXPOSE: case XCB_REPARENT_NOTIFY: @@ -833,4 +860,92 @@ NK_API int nk_cairo_render(struct nk_cairo_context *cairo_ctx, struct nk_context return nk_true; } +NK_INTERN xkbcommon_context *xkbcommon_init(xcb_connection_t *conn) +{ + xkbcommon_context *kbdctx; + int32_t device_id; + + int ret = xkb_x11_setup_xkb_extension(conn, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION, + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + NULL, NULL, NULL, NULL); + + if (ret == 0) + { + return NULL; + } + + kbdctx = (xkbcommon_context *)malloc(sizeof(xkbcommon_context)); + kbdctx->ctx = NULL; + kbdctx->keymap = NULL; + kbdctx->state = NULL; + + kbdctx->ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!kbdctx->ctx) + { + xkbcommon_free(kbdctx); + return NULL; + } + + device_id = xkb_x11_get_core_keyboard_device_id(conn); + if (device_id == -1) + { + xkbcommon_free(kbdctx); + return NULL; + } + + kbdctx->keymap = xkb_x11_keymap_new_from_device(kbdctx->ctx, conn, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!kbdctx->keymap) + { + xkbcommon_free(kbdctx); + return NULL; + } + + kbdctx->state = xkb_x11_state_new_from_device(kbdctx->keymap, conn, device_id); + if (!kbdctx->state) + { + xkbcommon_free(kbdctx); + return NULL; + } + + return kbdctx; +} + +NK_INTERN void xkbcommon_free(xkbcommon_context *kbdctx) +{ + if (kbdctx != NULL) + { + if (kbdctx->state) xkb_state_unref(kbdctx->state); + if (kbdctx->keymap) xkb_keymap_unref(kbdctx->keymap); + if (kbdctx->ctx) xkb_context_unref(kbdctx->ctx); + + kbdctx->ctx = NULL; + kbdctx->keymap = NULL; + kbdctx->state = NULL; + + free(kbdctx); + } +} + +NK_INTERN xkb_keysym_t keycode_to_keysym(nk_xcb_context *ctx, xkb_keycode_t keycode, int pressed) +{ + xkb_keysym_t keysym; + xkbcommon_context *kbdctx = ctx->xkbcommon_ctx; + + if (kbdctx != NULL) + { + keysym = xkb_state_key_get_one_sym(kbdctx->state, keycode); + + /*xkb_state_component changed = */ + xkb_state_update_key(kbdctx->state, keycode, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + } + else + { + keysym = 0; + } + + return keysym; +} + #endif /* NK_XCB_CAIRO_IMPLEMENTATION */