Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xkbcommon support #745

Merged
merged 1 commit into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions demo/xcb_cairo/Makefile
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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}
Expand Down
127 changes: 121 additions & 6 deletions demo/xcb_cairo/nuklear_xcb.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ NK_API void nk_xcb_resize_cairo_surface(struct nk_xcb_context *xcb_ctx, void *su
#include <cairo/cairo-xcb.h>
#include <cairo/cairo-ft.h>

#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-x11.h>


#if defined _XOPEN_SOURCE && _XOPEN_SOURCE >= 600 || \
defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L
#include <time.h>
Expand All @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand All @@ -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:
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 */