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); }
static void keyboardHandleKeymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size) { struct xkb_keymap* keymap; struct xkb_state* state; char* mapStr; if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); return; } mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (mapStr == MAP_FAILED) { close(fd); return; } keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context, mapStr, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(mapStr, size); close(fd); if (!keymap) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to compile keymap"); return; } state = xkb_state_new(keymap); if (!state) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB state"); xkb_keymap_unref(keymap); return; } xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_state_unref(_glfw.wl.xkb.state); _glfw.wl.xkb.keymap = keymap; _glfw.wl.xkb.state = state; _glfw.wl.xkb.controlMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control"); _glfw.wl.xkb.altMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1"); _glfw.wl.xkb.shiftMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift"); _glfw.wl.xkb.superMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4"); }
static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) { UwacSeat *input = data; struct xkb_keymap *keymap; struct xkb_state *state; char *map_str; if (!data) { 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_keymap_new_from_string(input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(map_str, size); close(fd); if (!keymap) { assert(uwacErrorHandler(input->display, UWAC_ERROR_INTERNAL, "failed to compile keymap\n")); return; } state = xkb_state_new(keymap); if (!state) { assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY, "failed to create XKB state\n")); xkb_keymap_unref(keymap); return; } xkb_keymap_unref(input->xkb.keymap); xkb_state_unref(input->xkb.state); input->xkb.keymap = keymap; input->xkb.state = state; input->xkb.control_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Control"); input->xkb.alt_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod1"); input->xkb.shift_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Shift"); }
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; }
/* * Loads the XKB keymap from the X11 server and feeds it to xkbcommon. * Necessary so that we can properly let xkbcommon track the keyboard state and * translate keypresses to utf-8. * */ static bool load_keymap(void) { if (xkb_context == NULL) { if ((xkb_context = xkb_context_new(0)) == NULL) { fprintf(stderr, "[i3lock] could not create xkbcommon context\n"); return false; } } xkb_keymap_unref(xkb_keymap); int32_t device_id = xkb_x11_get_core_keyboard_device_id(conn); DEBUG("device = %d\n", device_id); if ((xkb_keymap = xkb_x11_keymap_new_from_device(xkb_context, conn, device_id, 0)) == NULL) { fprintf(stderr, "[i3lock] xkb_x11_keymap_new_from_device failed\n"); return false; } struct xkb_state *new_state = xkb_x11_state_new_from_device(xkb_keymap, conn, device_id); if (new_state == NULL) { fprintf(stderr, "[i3lock] xkb_x11_state_new_from_device failed\n"); return false; } xkb_state_unref(xkb_state); xkb_state = new_state; return true; }
static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) { // Keyboard errors are abort-worthy because you wouldn't be able to unlock your screen otherwise. struct registry *registry = data; if (!data) { close(fd); return; } if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); sway_abort("Unknown keymap format %d, aborting", format); } char *map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (map_str == MAP_FAILED) { close(fd); sway_abort("Unable to initialized shared keyboard memory, aborting"); } struct xkb_keymap *keymap = xkb_keymap_new_from_string(registry->input->xkb.context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(map_str, size); close(fd); if (!keymap) { sway_abort("Failed to compile keymap, aborting"); } struct xkb_state *state = xkb_state_new(keymap); if (!state) { xkb_keymap_unref(keymap); sway_abort("Failed to create xkb state, aborting"); } xkb_keymap_unref(registry->input->xkb.keymap); xkb_state_unref(registry->input->xkb.state); registry->input->xkb.keymap = keymap; registry->input->xkb.state = state; int i; for (i = 0; i < MASK_LAST; ++i) { registry->input->xkb.masks[i] = 1 << xkb_keymap_mod_get_index(registry->input->xkb.keymap, XKB_MASK_NAMES[i]); } }
int xrtb_keyboard_reload(struct xcb_rutabaga *xrtb) { struct xkb_keymap *new_keymap; int32_t device_id; assert(xrtb->xkb_ctx); device_id = xkb_x11_get_core_keyboard_device_id(xrtb->xcb_conn); if (device_id == -1) goto err_get_kbd_device; if (!(new_keymap = xkb_x11_keymap_new_from_device(xrtb->xkb_ctx, xrtb->xcb_conn, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS))) goto err_new_keymap; if (xrtb->xkb_keymap) xkb_keymap_unref(xrtb->xkb_keymap); xrtb->xkb_keymap = new_keymap; if (xrtb->xkb_state) xkb_state_unref(xrtb->xkb_state); if (!(xrtb->xkb_state = xkb_x11_state_new_from_device(new_keymap, xrtb->xcb_conn, device_id))) goto err_new_state; #define CACHE_MOD_INDEX(name, constant) \ xrtb->mod_indices.name = xkb_keymap_mod_get_index(new_keymap, constant) CACHE_MOD_INDEX(shift, XKB_MOD_NAME_SHIFT); CACHE_MOD_INDEX(ctrl, XKB_MOD_NAME_CTRL); CACHE_MOD_INDEX(alt, XKB_MOD_NAME_ALT); CACHE_MOD_INDEX(super, XKB_MOD_NAME_LOGO); #undef CACHE_MOD_INDEX return 0; err_new_state: xkb_keymap_unref(xrtb->xkb_keymap); xrtb->xkb_keymap = NULL; err_new_keymap: err_get_kbd_device: return -1; }
void KeyboardState::Setup(const Keymap &keymap) { Destroy(); xkb_state_ = xkb_state_new(keymap.xkb_keymap_); if (nullptr == xkb_state_) { xkb_keymap_unref(keymap.xkb_keymap_); throw std::runtime_error("FATAL! Cannot create keyboard state!"); } }
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); }
/* * Loads the XKB keymap from the X11 server and feeds it to xkbcommon. * Necessary so that we can properly let xkbcommon track the keyboard state and * translate keypresses to utf-8. * * Ideally, xkbcommon would ship something like this itself, but as of now * (version 0.2.0), it doesn’t. * */ static bool load_keymap(void) { bool ret = false; XkbFileInfo result; memset(&result, '\0', sizeof(result)); result.xkb = XkbGetKeyboard(display, XkbAllMapComponentsMask, XkbUseCoreKbd); if (result.xkb == NULL) { fprintf(stderr, "[i3lock] XKB: XkbGetKeyboard failed\n"); return false; } FILE *temp = tmpfile(); if (temp == NULL) { fprintf(stderr, "[i3lock] could not create tempfile\n"); return false; } bool ok = XkbWriteXKBKeymap(temp, &result, false, false, NULL, NULL); if (!ok) { fprintf(stderr, "[i3lock] XkbWriteXKBKeymap failed\n"); goto out; } rewind(temp); if (xkb_context == NULL) { if ((xkb_context = xkb_context_new(0)) == NULL) { fprintf(stderr, "[i3lock] could not create xkbcommon context\n"); goto out; } } if (xkb_keymap != NULL) xkb_keymap_unref(xkb_keymap); if ((xkb_keymap = xkb_keymap_new_from_file(xkb_context, temp, XKB_KEYMAP_FORMAT_TEXT_V1, 0)) == NULL) { fprintf(stderr, "[i3lock] xkb_keymap_new_from_file failed\n"); goto out; } struct xkb_state *new_state = xkb_state_new(xkb_keymap); if (new_state == NULL) { fprintf(stderr, "[i3lock] xkb_state_new failed\n"); goto out; } if (xkb_state != NULL) xkb_state_unref(xkb_state); xkb_state = new_state; ret = true; out: XkbFreeKeyboard(result.xkb, XkbAllComponentsMask, true); fclose(temp); return ret; }
static int test_file(struct xkb_context *ctx, const char *path_rel) { struct xkb_keymap *keymap = test_compile_file(ctx, path_rel); if (!keymap) return 0; xkb_keymap_unref(keymap); return 1; }
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 }
static void ss_seat_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int fd, uint32_t size) { struct ss_seat *seat = data; struct xkb_keymap *keymap; char *map_str; if (!data) goto error; if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (map_str == MAP_FAILED) { weston_log("mmap failed: %m\n"); goto error; } keymap = xkb_keymap_new_from_string(seat->base.compositor->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(map_str, size); if (!keymap) { weston_log("failed to compile keymap\n"); goto error; } seat->keyboard_state_update = STATE_UPDATE_NONE; } else if (format == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) { weston_log("No keymap provided; falling back to default\n"); keymap = NULL; seat->keyboard_state_update = STATE_UPDATE_AUTOMATIC; } else { weston_log("Invalid keymap\n"); goto error; } close(fd); if (seat->base.keyboard_device_count) weston_seat_update_keymap(&seat->base, keymap); else weston_seat_init_keyboard(&seat->base, keymap); xkb_keymap_unref(keymap); return; error: wl_keyboard_release(seat->parent.keyboard); close(fd); }
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); }
/** * Process X11 events in the main-loop (gui-thread) of the application. */ static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer data ) { if ( ev == NULL ) { int status = xcb_connection_has_error ( xcb->connection ); fprintf ( stderr, "The XCB connection to X server had a fatal error: %d\n", status ); g_main_loop_quit ( main_loop ); return G_SOURCE_REMOVE; } uint8_t type = ev->response_type & ~0x80; if ( type == xkb.first_event ) { switch ( ev->pad0 ) { case XCB_XKB_MAP_NOTIFY: xkb_state_unref ( xkb.state ); xkb_keymap_unref ( xkb.keymap ); xkb.keymap = xkb_x11_keymap_new_from_device ( xkb.context, xcb->connection, xkb.device_id, 0 ); xkb.state = xkb_x11_state_new_from_device ( xkb.keymap, xcb->connection, xkb.device_id ); break; case XCB_XKB_STATE_NOTIFY: { xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) ev; xkb_state_update_mask ( xkb.state, ksne->baseMods, ksne->latchedMods, ksne->lockedMods, ksne->baseGroup, ksne->latchedGroup, ksne->lockedGroup ); break; } } return G_SOURCE_CONTINUE; } RofiViewState *state = rofi_view_get_active (); if ( xcb->sndisplay != NULL ) { sn_xcb_display_process_event ( xcb->sndisplay, ev ); } if ( state != NULL ) { rofi_view_itterrate ( state, ev, &xkb ); if ( rofi_view_get_completed ( state ) ) { // This menu is done. rofi_view_finalize ( state ); // cleanup if ( rofi_view_get_active () == NULL ) { teardown ( pfd ); g_main_loop_quit ( main_loop ); } } } return G_SOURCE_CONTINUE; }
static void keymap_changed (MetaBackend *backend) { MetaBackendX11 *x11 = META_BACKEND_X11 (backend); MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); if (priv->keymap) { xkb_keymap_unref (priv->keymap); priv->keymap = NULL; } g_signal_emit_by_name (backend, "keymap-changed", 0); }
static kbdmap *kbdmap_unref(kbdmap *km) { if (!km) return NULL; assert_return(km->ref > 0, NULL); if (--km->ref > 0) return NULL; xkb_keymap_unref(km->xkb_keymap); free(km); return 0; }
static void input_method_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { struct simple_im *keyboard = data; char *map_str; 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; } keyboard->keymap = xkb_keymap_new_from_string(keyboard->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(map_str, size); close(fd); if (!keyboard->keymap) { fprintf(stderr, "failed to compile keymap\n"); return; } keyboard->state = xkb_state_new(keyboard->keymap); if (!keyboard->state) { fprintf(stderr, "failed to create XKB state\n"); xkb_keymap_unref(keyboard->keymap); return; } keyboard->control_mask = 1 << xkb_keymap_mod_get_index(keyboard->keymap, "Control"); keyboard->alt_mask = 1 << xkb_keymap_mod_get_index(keyboard->keymap, "Mod1"); keyboard->shift_mask = 1 << xkb_keymap_mod_get_index(keyboard->keymap, "Shift"); }
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{ }; }
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); }
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(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 void keyboardHandleKeymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size) { struct xkb_keymap* keymap; struct xkb_state* state; #ifdef HAVE_XKBCOMMON_COMPOSE_H struct xkb_compose_table* composeTable; struct xkb_compose_state* composeState; #endif char* mapStr; const char* locale; if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); return; } mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (mapStr == MAP_FAILED) { close(fd); return; } keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context, mapStr, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(mapStr, size); close(fd); if (!keymap) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to compile keymap"); return; } state = xkb_state_new(keymap); if (!state) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB state"); xkb_keymap_unref(keymap); return; } // Look up the preferred locale, falling back to "C" as default. locale = getenv("LC_ALL"); if (!locale) locale = getenv("LC_CTYPE"); if (!locale) locale = getenv("LANG"); if (!locale) locale = "C"; #ifdef HAVE_XKBCOMMON_COMPOSE_H composeTable = xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (composeTable) { composeState = xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS); xkb_compose_table_unref(composeTable); if (composeState) _glfw.wl.xkb.composeState = composeState; else _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB compose state"); } else { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB compose table"); } #endif xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_state_unref(_glfw.wl.xkb.state); _glfw.wl.xkb.keymap = keymap; _glfw.wl.xkb.state = state; _glfw.wl.xkb.controlMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control"); _glfw.wl.xkb.altMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1"); _glfw.wl.xkb.shiftMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift"); _glfw.wl.xkb.superMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4"); _glfw.wl.xkb.capsLockMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock"); _glfw.wl.xkb.numLockMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2"); }
static void free_keyboard(Keyboard *keyboard) { xkb_state_unref(keyboard->state); xkb_keymap_unref(keyboard->keymap); xkb_context_unref(keyboard->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 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); }
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); }