guint gdk_keymap_lookup_key (GdkKeymap *keymap, const GdkKeymapKey *key) { guint sym; g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0); g_return_val_if_fail (key != NULL, 0); g_return_val_if_fail (key->group < 4, 0); /* Accept only the default keymap */ if (keymap != NULL && keymap != gdk_keymap_get_default ()) return 0; update_keymap (); if (key->keycode >= 256 || key->group < 0 || key->group >= 2 || key->level < 0 || key->level >= 2) return 0; sym = keysym_tab[key->keycode*4 + key->group*2 + key->level]; if (sym == GDK_VoidSymbol) return 0; else return sym; }
static void init_keyboard(Keyboard *keyboard) { int ret = xkb_x11_setup_xkb_extension(keyboard->conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &keyboard->first_xkb_event, NULL); if (!ret) { fprintf(stderr, "Failed to setup XKB extension.\n"); exit(EXIT_FAILURE); } keyboard->ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!keyboard->ctx) { fprintf(stderr, "Failed to create XKB context.\n"); exit(EXIT_FAILURE); } keyboard->device_id = xkb_x11_get_core_keyboard_device_id(keyboard->conn); if (keyboard->device_id == -1) { fprintf(stderr, "Failed to create keyboard device.\n"); exit(EXIT_FAILURE); } static const xcb_xkb_map_part_t required_map_parts = ( XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); static const xcb_xkb_event_type_t required_events = ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY); xcb_xkb_select_events( keyboard->conn, keyboard->device_id, required_events, 0, required_events, required_map_parts, required_map_parts, NULL); keyboard->compose_table = xkb_compose_table_new_from_locale(keyboard->ctx, get_locale(), XKB_COMPOSE_COMPILE_NO_FLAGS); if (!keyboard->compose_table) { fprintf(stderr, "Failed create compose table.\n"); exit(EXIT_FAILURE); } keyboard->compose_state = xkb_compose_state_new(keyboard->compose_table, XKB_COMPOSE_STATE_NO_FLAGS); if (!keyboard->compose_state) { fprintf(stderr, "Failed create compose state.\n"); exit(EXIT_FAILURE); } update_keymap(keyboard); }
static void process_keyboard_event(Keyboard *keyboard, xcb_generic_event_t *event) { union xkb_event { struct { uint8_t response_type; uint8_t xkbType; uint16_t sequence; xcb_timestamp_t time; uint8_t deviceID; } any; xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify; xcb_xkb_map_notify_event_t map_notify; xcb_xkb_state_notify_event_t state_notify; } *e = (union xkb_event *)event; if (e->any.deviceID != keyboard->device_id) { return; } switch (e->any.xkbType) { case XCB_XKB_NEW_KEYBOARD_NOTIFY: if (e->new_keyboard_notify.changed & XCB_XKB_NKN_DETAIL_KEYCODES) { update_keymap(keyboard); } break; case XCB_XKB_MAP_NOTIFY: update_keymap(keyboard); break; case XCB_XKB_STATE_NOTIFY: xkb_state_update_mask(keyboard->state, e->state_notify.baseMods, e->state_notify.latchedMods, e->state_notify.lockedMods, e->state_notify.baseGroup, e->state_notify.latchedGroup, e->state_notify.lockedGroup); break; default: break; } }
PangoDirection gdk_keymap_get_direction (GdkKeymap *keymap) { update_keymap (); switch (PRIMARYLANGID (LOWORD ((DWORD) (gintptr) _gdk_input_locale))) { case LANG_HEBREW: case LANG_ARABIC: #ifdef LANG_URDU case LANG_URDU: #endif case LANG_FARSI: /* Others? */ return PANGO_DIRECTION_RTL; default: return PANGO_DIRECTION_LTR; } }
gboolean gdk_keymap_translate_keyboard_state (GdkKeymap *keymap, guint hardware_keycode, GdkModifierType state, gint group, guint *keyval, gint *effective_group, gint *level, GdkModifierType *consumed_modifiers) { guint tmp_keyval; guint *keyvals; gint shift_level; gboolean ignore_shift = FALSE; gboolean ignore_group = FALSE; g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); g_return_val_if_fail (group < 4, FALSE); #if 0 GDK_NOTE (EVENTS, g_print ("gdk_keymap_translate_keyboard_state: keycode=%#x state=%#x group=%d\n", hardware_keycode, state, group)); #endif if (keyval) *keyval = 0; if (effective_group) *effective_group = 0; if (level) *level = 0; if (consumed_modifiers) *consumed_modifiers = 0; /* Accept only the default keymap */ if (keymap != NULL && keymap != gdk_keymap_get_default ()) return FALSE; if (hardware_keycode >= 256) return FALSE; if (group < 0 || group >= 2) return FALSE; update_keymap (); keyvals = keysym_tab + hardware_keycode*4; if ((state & GDK_LOCK_MASK) && (state & GDK_SHIFT_MASK) && ((gdk_shift_modifiers & GDK_LOCK_MASK) || (keyvals[group*2 + 1] == gdk_keyval_to_upper (keyvals[group*2 + 0])))) /* Shift always disables ShiftLock. Shift disables CapsLock for * keys with lowercase/uppercase letter pairs. */ shift_level = 0; else if (state & gdk_shift_modifiers) shift_level = 1; else shift_level = 0; /* Drop group and shift if there are no keysymbols on * the key for those. */ if (shift_level == 1 && keyvals[group*2 + 1] == GDK_VoidSymbol && keyvals[group*2] != GDK_VoidSymbol) { shift_level = 0; ignore_shift = TRUE; } if (group == 1 && keyvals[2 + shift_level] == GDK_VoidSymbol && keyvals[0 + shift_level] != GDK_VoidSymbol) { group = 0; ignore_group = TRUE; } if (keyvals[group *2 + shift_level] == GDK_VoidSymbol && keyvals[0 + 0] != GDK_VoidSymbol) { shift_level = 0; group = 0; ignore_group = TRUE; ignore_shift = TRUE; } /* See whether the group and shift level actually mattered * to know what to put in consumed_modifiers */ if (keyvals[group*2 + 1] == GDK_VoidSymbol || keyvals[group*2 + 0] == keyvals[group*2 + 1]) ignore_shift = TRUE; if (keyvals[2 + shift_level] == GDK_VoidSymbol || keyvals[0 + shift_level] == keyvals[2 + shift_level]) ignore_group = TRUE; tmp_keyval = keyvals[group*2 + shift_level]; /* If a true CapsLock is toggled, and Shift is not down, * and the shifted keysym is the uppercase of the unshifted, * use it. */ if (!(gdk_shift_modifiers & GDK_LOCK_MASK) && !(state & GDK_SHIFT_MASK) && (state & GDK_LOCK_MASK)) { guint upper = gdk_keyval_to_upper (tmp_keyval); if (upper == keyvals[group*2 + 1]) tmp_keyval = upper; } if (keyval) *keyval = tmp_keyval; if (effective_group) *effective_group = group; if (level) *level = shift_level; if (consumed_modifiers) { *consumed_modifiers = (ignore_group ? 0 : GDK_MOD2_MASK) | (ignore_shift ? 0 : (GDK_SHIFT_MASK|GDK_LOCK_MASK)); } #if 0 GDK_NOTE (EVENTS, g_print ("... group=%d level=%d cmods=%#x keyval=%s\n", group, shift_level, tmp_modifiers, gdk_keyval_name (tmp_keyval))); #endif return tmp_keyval != GDK_VoidSymbol; }
gboolean gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap, guint hardware_keycode, GdkKeymapKey **keys, guint **keyvals, gint *n_entries) { GArray *key_array; GArray *keyval_array; g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); g_return_val_if_fail (n_entries != NULL, FALSE); if (hardware_keycode <= 0 || hardware_keycode >= 256) { if (keys) *keys = NULL; if (keyvals) *keyvals = NULL; *n_entries = 0; return FALSE; } if (keys) key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey)); else key_array = NULL; if (keyvals) keyval_array = g_array_new (FALSE, FALSE, sizeof (guint)); else keyval_array = NULL; /* Accept only the default keymap */ if (keymap == NULL || keymap == gdk_keymap_get_default ()) { gint i; update_keymap (); for (i = 0; i < 4; i++) { if (key_array) { GdkKeymapKey key; key.keycode = hardware_keycode; key.group = i / 2; key.level = i % 2; g_array_append_val (key_array, key); } if (keyval_array) g_array_append_val (keyval_array, keysym_tab[hardware_keycode*4+i]); } } if ((key_array && key_array->len > 0) || (keyval_array && keyval_array->len > 0)) { if (keys) *keys = (GdkKeymapKey*) key_array->data; if (keyvals) *keyvals = (guint*) keyval_array->data; if (key_array) *n_entries = key_array->len; else *n_entries = keyval_array->len; } else { if (keys) *keys = NULL; if (keyvals) *keyvals = NULL; *n_entries = 0; } if (key_array) g_array_free (key_array, key_array->len > 0 ? FALSE : TRUE); if (keyval_array) g_array_free (keyval_array, keyval_array->len > 0 ? FALSE : TRUE); return *n_entries > 0; }
gboolean gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap, guint keyval, GdkKeymapKey **keys, gint *n_keys) { GArray *retval; g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); g_return_val_if_fail (keys != NULL, FALSE); g_return_val_if_fail (n_keys != NULL, FALSE); g_return_val_if_fail (keyval != 0, FALSE); retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey)); /* Accept only the default keymap */ if (keymap == NULL || keymap == gdk_keymap_get_default ()) { gint vk; update_keymap (); for (vk = 0; vk < 256; vk++) { gint i; for (i = 0; i < 4; i++) { if (keysym_tab[vk*4+i] == keyval) { GdkKeymapKey key; key.keycode = vk; /* 2 levels (normal, shift), two groups (normal, AltGr) */ key.group = i / 2; key.level = i % 2; g_array_append_val (retval, key); } } } } #ifdef G_ENABLE_DEBUG if (_gdk_debug_flags & GDK_DEBUG_EVENTS) { gint i; g_print ("gdk_keymap_get_entries_for_keyval: %#.04x (%s):", keyval, gdk_keyval_name (keyval)); for (i = 0; i < retval->len; i++) { GdkKeymapKey *entry = (GdkKeymapKey *) retval->data + i; g_print (" %#.02x %d %d", entry->keycode, entry->group, entry->level); } g_print ("\n"); } #endif if (retval->len > 0) { *keys = (GdkKeymapKey*) retval->data; *n_keys = retval->len; } else { *keys = NULL; *n_keys = 0; } g_array_free (retval, retval->len > 0 ? FALSE : TRUE); return *n_keys > 0; }