int main(void) { struct xkb_context *context = test_get_context(0); struct xkb_keymap *keymap; assert(context); /* Make sure these are allowed. */ xkb_context_unref(NULL); xkb_keymap_unref(NULL); xkb_state_unref(NULL); keymap = test_compile_rules(context, "evdev", "pc104", "us,ru", NULL, "grp:menu_toggle"); assert(keymap); test_update_key(keymap); test_serialisation(keymap); test_repeat(keymap); test_consume(keymap); test_range(keymap); test_get_utf8_utf32(keymap); test_ctrl_string_transformation(keymap); xkb_keymap_unref(keymap); keymap = test_compile_rules(context, "evdev", NULL, "ch", "fr", NULL); assert(keymap); test_caps_keysym_transformation(keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); }
int uxkb_desc_init(struct uterm_input *input, const char *model, const char *layout, const char *variant, const char *options) { int ret; struct xkb_rule_names rmlvo = { .rules = "evdev", .model = model, .layout = layout, .variant = variant, .options = options, }; input->ctx = xkb_context_new(0); if (!input->ctx) { log_error("cannot create XKB context"); return -ENOMEM; } input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0); if (!input->keymap) { log_warn("failed to create keymap (%s, %s, %s, %s), " "reverting to default system keymap", model, layout, variant, options); rmlvo.model = ""; rmlvo.layout = ""; rmlvo.variant = ""; rmlvo.options = ""; input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0); if (!input->keymap) { log_warn("failed to create XKB keymap"); ret = -EFAULT; goto err_ctx; } } log_debug("new keyboard description (%s, %s, %s, %s)", model, layout, variant, options); return 0; err_ctx: xkb_context_unref(input->ctx); return ret; } void uxkb_desc_destroy(struct uterm_input *input) { xkb_keymap_unref(input->keymap); xkb_context_unref(input->ctx); }
static void clutter_wayland_handle_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) { ClutterInputDeviceWayland *device = data; struct xkb_context *ctx; struct xkb_keymap *keymap; char *map_str; if (device->xkb) { xkb_state_unref (device->xkb); device->xkb = NULL; } ctx = xkb_context_new (0); if (!ctx) { close (fd); return; } if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close (fd); return; } map_str = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (map_str == MAP_FAILED) { close(fd); return; } keymap = xkb_map_new_from_string (ctx, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); xkb_context_unref (ctx); munmap (map_str, size); close (fd); if (!keymap) { g_warning ("failed to compile keymap\n"); return; } device->xkb = xkb_state_new(keymap); xkb_map_unref (keymap); if (!device->xkb) { g_warning ("failed to create XKB state object\n"); return; } }
int main(int argc, char *argv[]) { struct xkb_context *ctx; struct xkb_keymap *keymap; struct bench_timer timer; char *elapsed; int i; ctx = test_get_context(0); assert(ctx); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); xkb_context_set_log_verbosity(ctx, 0); bench_timer_reset(&timer); bench_timer_start(&timer); for (i = 0; i < BENCHMARK_ITERATIONS; i++) { keymap = test_compile_rules(ctx, "evdev", "evdev", "us", "", ""); assert(keymap); xkb_keymap_unref(keymap); } bench_timer_stop(&timer); elapsed = bench_timer_get_elapsed_time_str(&timer); fprintf(stderr, "compiled %d keymaps in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); xkb_context_unref(ctx); return 0; }
static kbdctx *kbdctx_unref(kbdctx *kc) { if (!kc) return NULL; assert_return(kc->ref > 0, NULL); if (--kc->ref > 0) return NULL; free(kc->last_x11_options); free(kc->last_x11_variant); free(kc->last_x11_layout); free(kc->last_x11_model); free(kc->locale_x11_options); free(kc->locale_x11_variant); free(kc->locale_x11_layout); free(kc->locale_x11_model); free(kc->locale_lang); kc->slot_locale_get_all = sd_bus_slot_unref(kc->slot_locale_get_all); kc->slot_locale_props_changed = sd_bus_slot_unref(kc->slot_locale_props_changed); kc->kbdtbl = kbdtbl_unref(kc->kbdtbl); kc->kbdmap = kbdmap_unref(kc->kbdmap); xkb_context_unref(kc->xkb_context); hashmap_remove_value(kc->context->data_map, KBDCTX_KEY, kc); free(kc); return NULL; }
int main(void) { struct xkb_context *ctx = test_get_context(0); assert(test_file(ctx, "keymaps/basic.xkb")); assert(test_file(ctx, "keymaps/comprehensive-plus-geom.xkb")); assert(test_file(ctx, "keymaps/no-types.xkb")); assert(test_file(ctx, "keymaps/quartz.xkb")); assert(!test_file(ctx, "keymaps/divide-by-zero.xkb")); assert(!test_file(ctx, "keymaps/bad.xkb")); assert(!test_file(ctx, "keymaps/syntax-error.xkb")); assert(!test_file(ctx, "keymaps/syntax-error2.xkb")); assert(!test_file(ctx, "does not exist")); /* Test response to invalid flags and formats. */ fclose(stdin); assert(!xkb_keymap_new_from_file(ctx, NULL, XKB_KEYMAP_FORMAT_TEXT_V1, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, 0, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_USE_ORIGINAL_FORMAT, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, 1234, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_FORMAT_TEXT_V1, -1)); assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_FORMAT_TEXT_V1, 1234)); xkb_context_unref(ctx); return 0; }
void EglFSWaylandInput::releaseKeymap() { if (m_xkbState) xkb_state_unref(m_xkbState); if (m_xkbKeymap) xkb_map_unref(m_xkbKeymap); if (m_xkbContext) xkb_context_unref(m_xkbContext); }
int main(int argc, char *argv[]) { int opt; struct xkb_rule_names rmlvo = { NULL }; struct xkb_context *ctx; struct xkb_component_names kccgst; while ((opt = getopt(argc, argv, "r:m:l:v:o:h")) != -1) { switch (opt) { case 'r': rmlvo.rules = optarg; break; case 'm': rmlvo.model = optarg; break; case 'l': rmlvo.layout = optarg; break; case 'v': rmlvo.variant = optarg; break; case 'o': rmlvo.options = optarg; break; case 'h': case '?': fprintf(stderr, "Usage: %s [-r <rules>] [-m <model>] " "[-l <layout>] [-v <variant>] [-o <options>]\n", argv[0]); return 1; } } ctx = test_get_context(0); if (!ctx) { fprintf(stderr, "Failed to get xkb context\n"); return 1; } xkb_context_sanitize_rule_names(ctx, &rmlvo); if (!xkb_components_from_rules(ctx, &rmlvo, &kccgst)) return 1; printf("keycodes: %s\n", kccgst.keycodes); printf("types: %s\n", kccgst.types); printf("compat: %s\n", kccgst.compat); printf("symbols: %s\n", kccgst.symbols); free(kccgst.keycodes); free(kccgst.types); free(kccgst.compat); free(kccgst.symbols); xkb_context_unref(ctx); return 0; }
/*virtual*/ Display::~Display() { if (xkbContext_) { xkb_context_unref(xkbContext_); } wl_registry_destroy(wl_registry_); wl_display_disconnect(*this); }
QLibInputKeyboard::~QLibInputKeyboard() { #ifndef QT_NO_XKBCOMMON_EVDEV if (m_state) xkb_state_unref(m_state); if (m_keymap) xkb_keymap_unref(m_keymap); if (m_ctx) xkb_context_unref(m_ctx); #endif }
/** * Create a new context. */ XKB_EXPORT struct xkb_context * xkb_context_new(enum xkb_context_flags flags) { const char *env; struct xkb_context *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return NULL; ctx->refcnt = 1; ctx->log_fn = default_log_fn; ctx->log_level = XKB_LOG_LEVEL_ERROR; ctx->log_verbosity = 0; /* Environment overwrites defaults. */ env = getenv("XKB_LOG_LEVEL"); if (env) xkb_context_set_log_level(ctx, log_level(env)); env = getenv("XKB_LOG_VERBOSITY"); if (env) xkb_context_set_log_verbosity(ctx, log_verbosity(env)); if (!(flags & XKB_CONTEXT_NO_DEFAULT_INCLUDES) && !xkb_context_include_path_append_default(ctx)) { log_err(ctx, "failed to add default include path %s\n", DFLT_XKB_CONFIG_ROOT); xkb_context_unref(ctx); return NULL; } ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES); ctx->atom_table = atom_table_new(); if (!ctx->atom_table) { xkb_context_unref(ctx); return NULL; } return ctx; }
QWaylandKeyboardPrivate::~QWaylandKeyboardPrivate() { #ifndef QT_NO_WAYLAND_XKB if (xkb_context) { if (keymap_area) munmap(keymap_area, keymap_size); close(keymap_fd); xkb_context_unref(xkb_context); xkb_state_unref(xkb_state); } #endif }
void xrtb_keyboard_fini(struct xcb_rutabaga *xrtb) { assert(xrtb->xkb_ctx); xkb_context_unref(xrtb->xkb_ctx); if (xrtb->xkb_keymap) xkb_keymap_unref(xrtb->xkb_keymap); if (xrtb->xkb_state) xkb_state_unref(xrtb->xkb_state); }
/* * Try closing the input device(s) */ void fgPlatformCloseInputDevices( void ) { if( fgDisplay.pDisplay.touch ) wl_touch_destroy( fgDisplay.pDisplay.touch ); if( fgDisplay.pDisplay.pointer ) wl_pointer_destroy( fgDisplay.pDisplay.pointer ); if( fgDisplay.pDisplay.keyboard ) wl_keyboard_destroy( fgDisplay.pDisplay.keyboard ); if( fgDisplay.pDisplay.xkb_state ) xkb_state_unref( fgDisplay.pDisplay.xkb_state ); if( fgDisplay.pDisplay.xkb_context ) xkb_context_unref( fgDisplay.pDisplay.xkb_context ); }
int main(void) { struct xkb_context *context = test_get_context(0); assert(context); assert(xkb_context_num_include_paths(context) == 1); assert(!xkb_context_include_path_append(context, "¡NONSENSE!")); assert(xkb_context_num_include_paths(context) == 1); xkb_context_unref(context); return 0; }
WaylandDisplay::~WaylandDisplay() { if (m_eventSource) g_source_unref(m_eventSource); m_eventSource = nullptr; if (m_interfaces.compositor) wl_compositor_destroy(m_interfaces.compositor); if (m_interfaces.data_device_manager) wl_data_device_manager_destroy(m_interfaces.data_device_manager); if (m_interfaces.drm) wl_drm_destroy(m_interfaces.drm); if (m_interfaces.seat) wl_seat_destroy(m_interfaces.seat); if (m_interfaces.xdg) xdg_shell_destroy(m_interfaces.xdg); if (m_interfaces.ivi_application) ivi_application_destroy(m_interfaces.ivi_application); m_interfaces = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; if (m_registry) wl_registry_destroy(m_registry); m_registry = nullptr; if (m_display) wl_display_disconnect(m_display); m_display = nullptr; if (m_seatData.pointer.object) wl_pointer_destroy(m_seatData.pointer.object); if (m_seatData.keyboard.object) wl_keyboard_destroy(m_seatData.keyboard.object); if (m_seatData.touch.object) wl_touch_destroy(m_seatData.touch.object); if (m_seatData.xkb.context) xkb_context_unref(m_seatData.xkb.context); if (m_seatData.xkb.keymap) xkb_keymap_unref(m_seatData.xkb.keymap); if (m_seatData.xkb.state) xkb_state_unref(m_seatData.xkb.state); if (m_seatData.xkb.composeTable) xkb_compose_table_unref(m_seatData.xkb.composeTable); if (m_seatData.xkb.composeState) xkb_compose_state_unref(m_seatData.xkb.composeState); if (m_seatData.repeatData.eventSource) g_source_remove(m_seatData.repeatData.eventSource); m_seatData = SeatData{ }; }
static struct xkb_keymap * meta_backend_x11_get_keymap (MetaBackend *backend) { MetaBackendX11 *x11 = META_BACKEND_X11 (backend); MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); if (priv->keymap == NULL) { struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS); priv->keymap = xkb_x11_keymap_new_from_device (context, priv->xcb, xkb_x11_get_core_keyboard_device_id (priv->xcb), XKB_KEYMAP_COMPILE_NO_FLAGS); xkb_context_unref (context); } return priv->keymap; }
void free_xkb(void) { if (mod_map_idx) free(mod_map_idx); if (mod_map_bit) free(mod_map_bit); if (xkb_map) xkb_keymap_unref(xkb_map); if (xkb_ctx) xkb_context_unref(xkb_ctx); if (xkb_state) xkb_state_unref(xkb_state); mod_map_idx = NULL; mod_map_bit = NULL; xkb_map = NULL; xkb_ctx = NULL; xkb_state = NULL; }
static void udev_input_free(void *data) { unsigned i; udev_input_t *udev = (udev_input_t*)data; if (!data || !udev) return; if (udev->joypad) udev->joypad->destroy(); if (udev->epfd >= 0) close(udev->epfd); for (i = 0; i < udev->num_devices; i++) { close(udev->devices[i]->fd); free(udev->devices[i]); } free(udev->devices); if (udev->monitor) udev_monitor_unref(udev->monitor); if (udev->udev) udev_unref(udev->udev); #ifdef HAVE_XKBCOMMON if (udev->mod_map_idx) free(udev->mod_map_idx); if (udev->mod_map_bit) free(udev->mod_map_bit); if (udev->xkb_map) xkb_keymap_unref(udev->xkb_map); if (udev->xkb_ctx) xkb_context_unref(udev->xkb_ctx); if (udev->xkb_state) xkb_state_unref(udev->xkb_state); #endif free(udev); }
XKB_EXPORT void xkb_keymap_unref(struct xkb_keymap *keymap) { if (!keymap || --keymap->refcnt > 0) return; if (keymap->keys) { struct xkb_key *key; xkb_keys_foreach(key, keymap) { if (key->groups) { for (unsigned i = 0; i < key->num_groups; i++) { if (key->groups[i].levels) { for (unsigned j = 0; j < XkbKeyNumLevels(key, i); j++) if (key->groups[i].levels[j].num_syms > 1) free(key->groups[i].levels[j].u.syms); free(key->groups[i].levels); } } free(key->groups); } } free(keymap->keys); } if (keymap->types) { for (unsigned i = 0; i < keymap->num_types; i++) { free(keymap->types[i].entries); free(keymap->types[i].level_names); } free(keymap->types); } free(keymap->sym_interprets); free(keymap->key_aliases); free(keymap->group_names); free(keymap->keycodes_section_name); free(keymap->symbols_section_name); free(keymap->types_section_name); free(keymap->compat_section_name); xkb_context_unref(keymap->ctx); free(keymap); }
WaylandInputEvent::~WaylandInputEvent() { if (!m_wlEventSource) wl_event_source_remove(m_wlEventSource); if (m_xkbInfo.keymap) xkb_map_unref(m_xkbInfo.keymap); if (m_xkbInfo.keymap_area) munmap(m_xkbInfo.keymap_area, m_xkbInfo.keymap_size); if (m_xkbInfo.keymap_fd >= 0) close(m_xkbInfo.keymap_fd); xkb_context_unref(m_xkbContext); free((char*)m_xkbNames.rules); free((char*)m_xkbNames.model); free((char*)m_xkbNames.layout); free((char*)m_xkbNames.variant); free((char*)m_xkbNames.options); }
int main(void) { struct xkb_context *ctx; struct xkb_keymap *keymap; struct xkb_state *state; struct bench bench; char *elapsed; ctx = test_get_context(0); assert(ctx); keymap = test_compile_rules(ctx, "evdev", "pc104", "us,ru,il,de", ",,,neo", "grp:menu_toggle"); assert(keymap); state = xkb_state_new(keymap); assert(state); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); xkb_context_set_log_verbosity(ctx, 0); srand(time(NULL)); bench_start(&bench); bench_key_proc(state); bench_stop(&bench); elapsed = bench_elapsed_str(&bench); fprintf(stderr, "ran %d iterations in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); xkb_state_unref(state); xkb_keymap_unref(keymap); xkb_context_unref(ctx); return 0; }
void _glfwPlatformTerminate(void) { _glfwTerminateEGL(); _glfwTerminateJoysticksLinux(); _glfwTerminateThreadLocalStoragePOSIX(); xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_state_unref(_glfw.wl.xkb.state); xkb_context_unref(_glfw.wl.xkb.context); if (_glfw.wl.cursorTheme) wl_cursor_theme_destroy(_glfw.wl.cursorTheme); if (_glfw.wl.cursorSurface) wl_surface_destroy(_glfw.wl.cursorSurface); if (_glfw.wl.compositor) wl_compositor_destroy(_glfw.wl.compositor); if (_glfw.wl.shm) wl_shm_destroy(_glfw.wl.shm); if (_glfw.wl.shell) wl_shell_destroy(_glfw.wl.shell); if (_glfw.wl.pointer) wl_pointer_destroy(_glfw.wl.pointer); if (_glfw.wl.keyboard) wl_keyboard_destroy(_glfw.wl.keyboard); if (_glfw.wl.seat) wl_seat_destroy(_glfw.wl.seat); if (_glfw.wl.relativePointerManager) zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager); if (_glfw.wl.pointerConstraints) zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints); if (_glfw.wl.registry) wl_registry_destroy(_glfw.wl.registry); if (_glfw.wl.display) { wl_display_flush(_glfw.wl.display); wl_display_disconnect(_glfw.wl.display); } }
int main() { xkb_rule_names names; names.rules = strdup("evdev"); names.model = strdup("pc105"); names.layout = strdup("us"); names.variant = strdup(""); names.options = strdup(""); xkb_context *context = xkb_context_new(xkb_context_flags(0)); if (context) { xkb_keymap * keymap = xkb_map_new_from_names(context, &names, xkb_map_compile_flags(0)); if (keymap) { xkb_state *state = xkb_state_new(keymap); if (state) xkb_state_unref(state); xkb_map_unref(keymap); } xkb_context_unref(context); } return 0; }
int main(int argc, char **argv) { struct xkb_context *ctx; struct xkb_keymap *keymap; struct xkb_rule_names names = { .rules = NULL, .model = NULL, .layout = NULL, .variant = NULL, .options = NULL, }; int rc; if (argc <= 1) { usage(); return 1; } if (!parse_options(argc, argv, &names)) return 1; ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(ctx); keymap = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); rc = (keymap == NULL); if (rc == 0 && print) printf("%s\n", xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1)); xkb_keymap_unref(keymap); xkb_context_unref(ctx); return rc; }
int main(int argc, char *argv[]) { struct xkb_context *ctx = test_get_context(0); struct xkb_keymap *keymap; char *original, *dump; assert(ctx); /* Load in a prebuilt keymap, make sure we can compile it from a string, * then compare it to make sure we get the same result when dumping it * to a string. */ original = test_read_file(DATA_PATH); assert(original); keymap = test_compile_string(ctx, original); assert(keymap); dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); assert(dump); if (!streq(original, dump)) { fprintf(stderr, "round-trip test failed: dumped map differs from original\n"); fprintf(stderr, "path to original file: %s\n", test_get_path(DATA_PATH)); fprintf(stderr, "length: dumped %lu, original %lu\n", (unsigned long) strlen(dump), (unsigned long) strlen(original)); fprintf(stderr, "dumped map:\n"); fprintf(stderr, "%s\n", dump); fflush(stderr); assert(0); } free(original); free(dump); xkb_keymap_unref(keymap); /* Make sure we can't (falsely claim to) compile an empty string. */ keymap = test_compile_string(ctx, ""); assert(!keymap); /* Make sure we can recompile our output for a normal keymap from rules. */ keymap = test_compile_rules(ctx, NULL, NULL, "ru,ca,de,us", ",multix,neo,intl", NULL); assert(keymap); dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); assert(dump); xkb_keymap_unref(keymap); keymap = test_compile_string(ctx, dump); assert(keymap); /* Test response to invalid formats and flags. */ assert(!xkb_keymap_new_from_string(ctx, dump, 0, 0)); assert(!xkb_keymap_new_from_string(ctx, dump, -1, 0)); assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1+1, 0)); assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, -1)); assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, 1414)); assert(!xkb_keymap_get_as_string(keymap, 0)); assert(!xkb_keymap_get_as_string(keymap, 4893)); xkb_keymap_unref(keymap); free(dump); xkb_context_unref(ctx); return 0; }
static int uxkb_desc_init(struct kbd_desc **out, const char *layout, const char *variant, const char *options) { int ret; struct kbd_desc *desc; struct xkb_rule_names rmlvo = { .rules = "evdev", .model = "evdev", .layout = layout, .variant = variant, .options = options, }; if (!out) return -EINVAL; desc = malloc(sizeof(*desc)); if (!desc) return -ENOMEM; memset(desc, 0, sizeof(*desc)); desc->ref = 1; desc->ops = &uxkb_desc_ops; desc->uxkb.ctx = xkb_context_new(0); if (!desc->uxkb.ctx) { ret = -ENOMEM; goto err_desc; } desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx, &rmlvo, 0); if (!desc->uxkb.keymap) { log_warn("failed to create keymap (%s, %s, %s), " "reverting to default US keymap", layout, variant, options); rmlvo.layout = "us"; rmlvo.variant = ""; rmlvo.options = ""; desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx, &rmlvo, 0); if (!desc->uxkb.keymap) { log_warn("failed to create keymap"); ret = -EFAULT; goto err_ctx; } } log_debug("new keyboard description (%s, %s, %s)", layout, variant, options); *out = desc; return 0; err_ctx: xkb_context_unref(desc->uxkb.ctx); err_desc: free(desc); return ret; } static void uxkb_desc_ref(struct kbd_desc *desc) { if (!desc || !desc->ref) return; ++desc->ref; } static void uxkb_desc_unref(struct kbd_desc *desc) { if (!desc || !desc->ref || --desc->ref) return; log_debug("destroying keyboard description"); xkb_map_unref(desc->uxkb.keymap); xkb_context_unref(desc->uxkb.ctx); free(desc); } static int uxkb_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out) { struct kbd_dev *kbd; kbd = malloc(sizeof(*kbd)); if (!kbd) return -ENOMEM; memset(kbd, 0, sizeof(*kbd)); kbd->ref = 1; kbd->desc = desc; kbd->ops = &uxkb_dev_ops; kbd->uxkb.state = xkb_state_new(desc->uxkb.keymap); if (!kbd->uxkb.state) { free(kbd); return -ENOMEM; } kbd_desc_ref(desc); *out = kbd; return 0; } static void uxkb_keysym_to_string(uint32_t keysym, char *str, size_t size) { xkb_keysym_get_name(keysym, str, size); }
int uxkb_desc_init(struct uterm_input *input, const char *model, const char *layout, const char *variant, const char *options, const char *keymap) { int ret; struct xkb_rule_names rmlvo = { .rules = "evdev", .model = model, .layout = layout, .variant = variant, .options = options, }; input->ctx = xkb_context_new(0); if (!input->ctx) { log_error("cannot create XKB context"); return -ENOMEM; } /* If a complete keymap file was given, first try that. */ if (keymap && *keymap) { input->keymap = xkb_keymap_new_from_string(input->ctx, keymap, XKB_KEYMAP_FORMAT_TEXT_V1, 0); if (input->keymap) { log_debug("new keyboard description from memory"); return 0; } log_warn("cannot parse keymap, reverting to rmlvo"); } input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0); if (!input->keymap) { log_warn("failed to create keymap (%s, %s, %s, %s), " "reverting to default system keymap", model, layout, variant, options); rmlvo.model = ""; rmlvo.layout = ""; rmlvo.variant = ""; rmlvo.options = ""; input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0); if (!input->keymap) { log_warn("failed to create XKB keymap"); ret = -EFAULT; goto err_ctx; } } log_debug("new keyboard description (%s, %s, %s, %s)", model, layout, variant, options); return 0; err_ctx: xkb_context_unref(input->ctx); return ret; } void uxkb_desc_destroy(struct uterm_input *input) { xkb_keymap_unref(input->keymap); xkb_context_unref(input->ctx); }
void fill_keycodes() { struct xkb_keymap *keymap; struct xkb_context *context; const struct xkb_rule_names rules={ .rules=xkb_names[0], .model=xkb_names[1], .layout=xkb_names[2], .variant=xkb_names[3], .options=xkb_names[4] }; struct xkb_state *state; enum xkb_state_component current_state; int counter; int i,j,k; char mods[256]; char keysym_asc[256]; char file_path[256]; char command[15]; uint32_t max_keys; int w,h,retval; int jumpto; context=xkb_context_new(0); keymap=xkb_keymap_new_from_names(context,&rules,0); state=NULL; // Get all the modifier keys for(i=8;i<256;i++) { state=xkb_state_new(keymap); current_state=xkb_state_update_key(state, i,XKB_KEY_DOWN); if (current_state!=0) { mods[i]=1; } else { mods[i]=0; } xkb_state_unref(state); } mods[7]=1; // fake mod, used for "no mod" // Read the keyboard definition files sprintf(file_path,"%s/%s.keymap",BASE_CONFIG_DIR,lang_onscreen); FILE *keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Can't open keyboard definition file %s. Trying with US file\n",file_path); sprintf(file_path,"%s/us.keymap",BASE_CONFIG_DIR); keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Also failed to open the US keymap file. Aborting.\n"); exit(-1); } } retval=fscanf(keyboard_file,"%s %d",command,&keyboard_blocks); if (retval!=2) { printf("Can't read the number of blocks\n"); } else { max_keys=keyboard_blocks*4*KEYS_PER_ROW; keyboard_lowercase=(struct key_element *)malloc(max_keys*sizeof(struct key_element)); memset(keyboard_lowercase,0,max_keys*sizeof(struct key_element)); for(counter=0;(!feof(keyboard_file))&&(counter<max_keys);counter++) { retval=fscanf(keyboard_file,"%s %d %d",command,&w,&h); if(retval!=3) { break; } keyboard_lowercase[counter].size=KEYS_FONT_SIZE; keyboard_lowercase[counter].g_element[0]=0; keyboard_lowercase[counter].w=w; keyboard_lowercase[counter].h=h; keyboard_lowercase[counter].keycode=0; keyboard_lowercase[counter].modifier=0; if (!strcmp(command,"BLANK")) { keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } else if (!strcmp(command,"KEY")) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].keysym=init_utf8_to_keysym(keyboard_lowercase[counter].g_element); if (keyboard_lowercase[counter].keysym==0) { keyboard_lowercase[counter].type=KEY_BLANK; } } else if ((!strcmp(command,"KEYSYM"))||(!strcmp(command,"KEYSYMTEXT"))) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keysym_asc); keyboard_lowercase[counter].keysym=xkb_keysym_from_name(keysym_asc,0); if (keyboard_lowercase[counter].keysym==0) { printf("Unknown keysym %s\n",keysym_asc); keyboard_lowercase[counter].type=KEY_BLANK; } else { if (!strcmp(command,"KEYSYMTEXT")) { retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].size=KEYS_TEXT_FONT_SIZE; } else { retval=xkb_keysym_to_utf8(keyboard_lowercase[counter].keysym,keyboard_lowercase[counter].g_element,7); if (retval==-1) { retval++; } keyboard_lowercase[counter].g_element[retval]=0;// terminate string } } } else if (!strcmp(command,"TAB")) { keyboard_lowercase[counter].type=KEY_TAB; keyboard_lowercase[counter].keysym=XK_Tab; } else if (!strcmp(command,"SPACE")) { keyboard_lowercase[counter].type=KEY_SPACE; keyboard_lowercase[counter].keysym=XK_space; } else if (!strcmp(command,"RETURN")) { keyboard_lowercase[counter].type=KEY_RETURN; keyboard_lowercase[counter].keysym=XK_Return; } else if (!strcmp(command,"DELETE")) { keyboard_lowercase[counter].type=KEY_DELETE; keyboard_lowercase[counter].keysym=XK_BackSpace; } else if (!strcmp(command,"JUMPTO")) { retval=fscanf(keyboard_file,"%d %s",&jumpto,command); keyboard_lowercase[counter].type=KEY_JUMPTO; keyboard_lowercase[counter].keycode=jumpto; keyboard_lowercase[counter].keysym=0; if (!strcmp(command,"GEN")) { keyboard_lowercase[counter].modifier=0; } else if (!strcmp(command,"SHIFT")) { keyboard_lowercase[counter].modifier=1; } else if (!strcmp(command,"SYMBOLS")) { keyboard_lowercase[counter].modifier=2; } else if (!strcmp(command,"LETTERS")) { keyboard_lowercase[counter].modifier=3; } if (jumpto>=keyboard_blocks) { printf("Ilegal jump to block %d (max. is %d)\n",jumpto,keyboard_blocks); keyboard_lowercase[counter].type=KEY_BLANK; } } else if (!strcmp(command,"UP")) { keyboard_lowercase[counter].type=KEY_UP; keyboard_lowercase[counter].keysym=XK_Up; } else if (!strcmp(command,"DOWN")) { keyboard_lowercase[counter].type=KEY_DOWN; keyboard_lowercase[counter].keysym=XK_Down; } else if (!strcmp(command,"LEFT")) { keyboard_lowercase[counter].type=KEY_LEFT; keyboard_lowercase[counter].keysym=XK_Left; } else if (!strcmp(command,"RIGHT")) { keyboard_lowercase[counter].type=KEY_RIGHT; keyboard_lowercase[counter].keysym=XK_Right; } else { printf("Unknown command %s\n",command); keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } } xkb_keysym_t keysym; xkb_keycode_t keycode_mod; for(i=7;i<256;i++) { // do a loop on every modifier if (!mods[i]) { continue; // In this loop we test each modifier with each keycode } state=xkb_state_new(keymap); if (i!=7) { xkb_state_update_key(state, i,XKB_KEY_DOWN); // press the modifier key keycode_mod=i; } else { keycode_mod=0; } for(j=8;j<256;j++) { if (mods[j]) { continue; // Don't test modifiers; we want "normal" keys } keysym=xkb_state_key_get_one_sym(state, j); if (keysym==XKB_KEY_NoSymbol) { continue; } for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].keysym==keysym)) { keyboard_lowercase[k].keycode=j; keyboard_lowercase[k].modifier=keycode_mod; } } } xkb_state_unref(state); } /*for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained printf("Texto: %s, Keysym: %d, mod: %d\n",keyboard_lowercase[k].g_element,keyboard_lowercase[k].keycode,keyboard_lowercase[k].modifier); }*/ // Now assign new keysyms to keycodes not used, to allow other keysyms not available in US keyboards xcb_key_symbols_t *symbols; symbols=xcb_key_symbols_alloc(conn); xcb_flush(conn); xcb_keycode_t keycode=8; xcb_keycode_t keycode_found; xcb_keysym_t keysyms[4]; xcb_keycode_t keycode_shift; struct lower_upper_t {xcb_keysym_t upper_first; xcb_keysym_t upper_last; xcb_keysym_t lower_first; xcb_keysym_t lower_last; }; struct lower_upper_t lower_upper[] = { {XKB_KEY_Agrave,XKB_KEY_Odiaeresis,XKB_KEY_agrave,XKB_KEY_odiaeresis}, {XKB_KEY_Oslash,XKB_KEY_THORN,XKB_KEY_oslash,XKB_KEY_thorn}, {0,0,0,0} }; struct lower_upper_t *iter_lu; keycode_shift=*xcb_key_symbols_get_keycode(symbols,XKB_KEY_Shift_L); for(k=0;k<max_keys;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].type!=KEY_JUMPTO)) { // this key is not available in US keyboards; let's redefine a keycode for it keycode_found=0; while(keycode<256) { if ((0==xcb_key_symbols_get_keysym(symbols,keycode,0))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,1))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,2))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,3))) { keycode_found=keycode; break; } keycode++; } if (keycode_found==0) { printf("No more codes available\n"); break; // there are no more free keycodes available } keycode=keycode_found; keysyms[0]=keyboard_lowercase[k].keysym; keysyms[1]=0; keysyms[2]=keyboard_lowercase[k].keysym; keysyms[3]=0; for(iter_lu=lower_upper;iter_lu->upper_first;iter_lu++) { if ((keysyms[0]>=iter_lu->upper_first)&&(keysyms[0]<=iter_lu->upper_last)) { // it's an uppercase special character keysyms[0]|=0x20; // first character as lowercase break; } if ((keysyms[0]>=iter_lu->lower_first)&&(keysyms[0]<=iter_lu->lower_last)) { // it's a lowercase special character keysyms[2]&=0xDF; // second character as uppercase break; } } xcb_change_keyboard_mapping(conn,1,keycode,4,keysyms); // insert the new keysym for(j=k;j<max_keys;j++) { // set the keycode and the shift modifier, if needed, to all keys with that keysyms if (keyboard_lowercase[j].keysym==keysyms[0]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=0; continue; } if (keyboard_lowercase[j].keysym==keysyms[2]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=keycode_shift; continue; } } keycode++; } } xcb_key_symbols_free(symbols); } fclose(keyboard_file); keyboard_current_block=0; xkb_keymap_unref(keymap); xkb_context_unref(context); }
int main(int argc, char *argv[]) { int ret; int opt; struct keyboard *kbds; struct xkb_context *ctx; struct xkb_keymap *keymap; const char *rules = NULL; const char *model = NULL; const char *layout = NULL; const char *variant = NULL; const char *options = NULL; const char *keymap_path = NULL; struct sigaction act; setlocale(LC_ALL, ""); while ((opt = getopt(argc, argv, "r:m:l:v:o:k:n:c")) != -1) { switch (opt) { case 'r': rules = optarg; break; case 'm': model = optarg; break; case 'l': layout = optarg; break; case 'v': variant = optarg; break; case 'o': options = optarg; break; case 'k': keymap_path = optarg; break; case 'n': errno = 0; evdev_offset = strtol(optarg, NULL, 10); if (errno) { fprintf(stderr, "error: -n option expects a number\n"); exit(EXIT_FAILURE); } break; case 'c': report_state_changes = true; break; case '?': fprintf(stderr, " Usage: %s [-r <rules>] [-m <model>] " "[-l <layout>] [-v <variant>] [-o <options>]\n", argv[0]); fprintf(stderr, " or: %s -k <path to keymap file>\n", argv[0]); fprintf(stderr, "For both: -n <evdev keycode offset>\n" " -c (to report changes to the state)\n"); exit(EX_USAGE); } } ctx = test_get_context(0); if (!ctx) { ret = -1; fprintf(stderr, "Couldn't create xkb context\n"); goto err_out; } if (keymap_path) { FILE *file = fopen(keymap_path, "r"); if (!file) { ret = EXIT_FAILURE; fprintf(stderr, "Couldn't open '%s': %s\n", keymap_path, strerror(errno)); goto err_ctx; } keymap = xkb_keymap_new_from_file(ctx, file, XKB_KEYMAP_FORMAT_TEXT_V1, 0); fclose(file); } else { keymap = test_compile_rules(ctx, rules, model, layout, variant, options); } if (!keymap) { ret = -1; fprintf(stderr, "Couldn't create xkb keymap\n"); goto err_ctx; } kbds = get_keyboards(keymap); if (!kbds) { ret = -1; goto err_xkb; } act.sa_handler = sigintr_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); /* Instead of fiddling with termios.. */ system("stty -echo"); ret = loop(kbds); if (ret) goto err_stty; err_stty: system("stty echo"); free_keyboards(kbds); err_xkb: xkb_keymap_unref(keymap); err_ctx: xkb_context_unref(ctx); err_out: exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }