| File: | cdk/wayland/cdkkeys-wayland.c |
| Warning: | line 509, column 20 Access of 'int' element in the memory returned by 'alloca' at index 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* CDK - The GIMP Drawing Kit | |||
| 2 | * Copyright (C) 2000 Red Hat, Inc. | |||
| 3 | * | |||
| 4 | * This library is free software; you can redistribute it and/or | |||
| 5 | * modify it under the terms of the GNU Lesser General Public | |||
| 6 | * License as published by the Free Software Foundation; either | |||
| 7 | * version 2 of the License, or (at your option) any later version. | |||
| 8 | * | |||
| 9 | * This library is distributed in the hope that it will be useful, | |||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 12 | * Lesser General Public License for more details. | |||
| 13 | * | |||
| 14 | * You should have received a copy of the GNU Lesser General Public | |||
| 15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
| 16 | */ | |||
| 17 | ||||
| 18 | /* | |||
| 19 | * Modified by the CTK+ Team and others 1997-2000. See the AUTHORS | |||
| 20 | * file for a list of people on the CTK+ Team. See the ChangeLog | |||
| 21 | * files for a list of changes. These files are distributed with | |||
| 22 | * CTK+ at ftp://ftp.ctk.org/pub/ctk/. | |||
| 23 | */ | |||
| 24 | ||||
| 25 | #include "config.h" | |||
| 26 | ||||
| 27 | #include <stdio.h> | |||
| 28 | #include <stdlib.h> | |||
| 29 | #include <string.h> | |||
| 30 | #include <unistd.h> | |||
| 31 | #include <limits.h> | |||
| 32 | #include <errno(*__errno_location ()).h> | |||
| 33 | #include <sys/mman.h> | |||
| 34 | ||||
| 35 | #include "cdk.h" | |||
| 36 | #include "cdkwayland.h" | |||
| 37 | ||||
| 38 | #include "cdkprivate-wayland.h" | |||
| 39 | #include "cdkinternals.h" | |||
| 40 | #include "cdkkeysprivate.h" | |||
| 41 | ||||
| 42 | #include <xkbcommon/xkbcommon.h> | |||
| 43 | ||||
| 44 | typedef struct _CdkWaylandKeymap CdkWaylandKeymap; | |||
| 45 | typedef struct _CdkWaylandKeymapClass CdkWaylandKeymapClass; | |||
| 46 | ||||
| 47 | struct _CdkWaylandKeymap | |||
| 48 | { | |||
| 49 | CdkKeymap parent_instance; | |||
| 50 | ||||
| 51 | struct xkb_keymap *xkb_keymap; | |||
| 52 | struct xkb_state *xkb_state; | |||
| 53 | ||||
| 54 | PangoDirection *direction; | |||
| 55 | gboolean bidi; | |||
| 56 | }; | |||
| 57 | ||||
| 58 | struct _CdkWaylandKeymapClass | |||
| 59 | { | |||
| 60 | CdkKeymapClass parent_class; | |||
| 61 | }; | |||
| 62 | ||||
| 63 | #define CDK_TYPE_WAYLAND_KEYMAP(_cdk_wayland_keymap_get_type ()) (_cdk_wayland_keymap_get_type ()) | |||
| 64 | #define CDK_WAYLAND_KEYMAP(object)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((object)), ((_cdk_wayland_keymap_get_type () )))))) (G_TYPE_CHECK_INSTANCE_CAST ((object), CDK_TYPE_WAYLAND_KEYMAP, CdkWaylandKeymap)(((CdkWaylandKeymap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((_cdk_wayland_keymap_get_type ())))))) | |||
| 65 | #define CDK_IS_WAYLAND_KEYMAP(object)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (object)); GType __t = ((_cdk_wayland_keymap_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) (G_TYPE_CHECK_INSTANCE_TYPE ((object), CDK_TYPE_WAYLAND_KEYMAP)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (object)); GType __t = ((_cdk_wayland_keymap_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) | |||
| 66 | ||||
| 67 | GType _cdk_wayland_keymap_get_type (void); | |||
| 68 | ||||
| 69 | G_DEFINE_TYPE (CdkWaylandKeymap, _cdk_wayland_keymap, CDK_TYPE_KEYMAP)static void _cdk_wayland_keymap_init (CdkWaylandKeymap *self) ; static void _cdk_wayland_keymap_class_init (CdkWaylandKeymapClass *klass); static GType _cdk_wayland_keymap_get_type_once (void ); static gpointer _cdk_wayland_keymap_parent_class = ((void* )0); static gint CdkWaylandKeymap_private_offset; static void _cdk_wayland_keymap_class_intern_init (gpointer klass) { _cdk_wayland_keymap_parent_class = g_type_class_peek_parent (klass); if (CdkWaylandKeymap_private_offset != 0) g_type_class_adjust_private_offset (klass, &CdkWaylandKeymap_private_offset ); _cdk_wayland_keymap_class_init ((CdkWaylandKeymapClass*) klass ); } __attribute__ ((__unused__)) static inline gpointer _cdk_wayland_keymap_get_instance_private (CdkWaylandKeymap *self) { return (((gpointer) ((guint8*) (self ) + (glong) (CdkWaylandKeymap_private_offset)))); } GType _cdk_wayland_keymap_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0)) ; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = _cdk_wayland_keymap_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType _cdk_wayland_keymap_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple ((cdk_keymap_get_type ()), g_intern_static_string ("CdkWaylandKeymap" ), sizeof (CdkWaylandKeymapClass), (GClassInitFunc)(void (*)( void)) _cdk_wayland_keymap_class_intern_init, sizeof (CdkWaylandKeymap ), (GInstanceInitFunc)(void (*)(void)) _cdk_wayland_keymap_init , (GTypeFlags) 0); { {{};} } return g_define_type_id; } | |||
| 70 | ||||
| 71 | static void | |||
| 72 | cdk_wayland_keymap_finalize (GObject *object) | |||
| 73 | { | |||
| 74 | CdkWaylandKeymap *keymap = CDK_WAYLAND_KEYMAP (object)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((object)), ((_cdk_wayland_keymap_get_type () )))))); | |||
| 75 | ||||
| 76 | xkb_keymap_unref (keymap->xkb_keymap); | |||
| 77 | xkb_state_unref (keymap->xkb_state); | |||
| 78 | g_free (keymap->direction); | |||
| 79 | ||||
| 80 | G_OBJECT_CLASS (_cdk_wayland_keymap_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((_cdk_wayland_keymap_parent_class)), (((GType) ((20) << (2))))))))->finalize (object); | |||
| 81 | } | |||
| 82 | ||||
| 83 | static PangoDirection | |||
| 84 | cdk_wayland_keymap_get_direction (CdkKeymap *keymap) | |||
| 85 | { | |||
| 86 | CdkWaylandKeymap *keymap_wayland = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () )))))); | |||
| 87 | gint i; | |||
| 88 | ||||
| 89 | for (i = 0; i < xkb_keymap_num_layouts (keymap_wayland->xkb_keymap); i++) | |||
| 90 | { | |||
| 91 | if (xkb_state_layout_index_is_active (keymap_wayland->xkb_state, i, XKB_STATE_LAYOUT_EFFECTIVE)) | |||
| 92 | return keymap_wayland->direction[i]; | |||
| 93 | } | |||
| 94 | ||||
| 95 | return PANGO_DIRECTION_NEUTRAL; | |||
| 96 | } | |||
| 97 | ||||
| 98 | static gboolean | |||
| 99 | cdk_wayland_keymap_have_bidi_layouts (CdkKeymap *keymap) | |||
| 100 | { | |||
| 101 | CdkWaylandKeymap *keymap_wayland = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () )))))); | |||
| 102 | ||||
| 103 | return keymap_wayland->bidi; | |||
| 104 | } | |||
| 105 | ||||
| 106 | static gboolean | |||
| 107 | cdk_wayland_keymap_get_caps_lock_state (CdkKeymap *keymap) | |||
| 108 | { | |||
| 109 | return xkb_state_led_name_is_active (CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_state, | |||
| 110 | XKB_LED_NAME_CAPS"Caps Lock"); | |||
| 111 | } | |||
| 112 | ||||
| 113 | static gboolean | |||
| 114 | cdk_wayland_keymap_get_num_lock_state (CdkKeymap *keymap) | |||
| 115 | { | |||
| 116 | return xkb_state_led_name_is_active (CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_state, | |||
| 117 | XKB_LED_NAME_NUM"Num Lock"); | |||
| 118 | } | |||
| 119 | ||||
| 120 | static gboolean | |||
| 121 | cdk_wayland_keymap_get_scroll_lock_state (CdkKeymap *keymap) | |||
| 122 | { | |||
| 123 | return xkb_state_led_name_is_active (CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_state, | |||
| 124 | XKB_LED_NAME_SCROLL"Scroll Lock"); | |||
| 125 | } | |||
| 126 | ||||
| 127 | static gboolean | |||
| 128 | cdk_wayland_keymap_get_entries_for_keyval (CdkKeymap *keymap, | |||
| 129 | guint keyval, | |||
| 130 | CdkKeymapKey **keys, | |||
| 131 | gint *n_keys) | |||
| 132 | { | |||
| 133 | struct xkb_keymap *xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 134 | GArray *retval; | |||
| 135 | guint keycode; | |||
| 136 | xkb_keycode_t min_keycode, max_keycode; | |||
| 137 | ||||
| 138 | retval = g_array_new (FALSE(0), FALSE(0), sizeof (CdkKeymapKey)); | |||
| 139 | ||||
| 140 | min_keycode = xkb_keymap_min_keycode (xkb_keymap); | |||
| 141 | max_keycode = xkb_keymap_max_keycode (xkb_keymap); | |||
| 142 | for (keycode = min_keycode; keycode < max_keycode; keycode++) | |||
| 143 | { | |||
| 144 | gint num_layouts, layout; | |||
| 145 | num_layouts = xkb_keymap_num_layouts_for_key (xkb_keymap, keycode); | |||
| 146 | for (layout = 0; layout < num_layouts; layout++) | |||
| 147 | { | |||
| 148 | gint num_levels, level; | |||
| 149 | num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout); | |||
| 150 | for (level = 0; level < num_levels; level++) | |||
| 151 | { | |||
| 152 | const xkb_keysym_t *syms; | |||
| 153 | gint num_syms, sym; | |||
| 154 | num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms); | |||
| 155 | for (sym = 0; sym < num_syms; sym++) | |||
| 156 | { | |||
| 157 | if (syms[sym] == keyval) | |||
| 158 | { | |||
| 159 | CdkKeymapKey key; | |||
| 160 | ||||
| 161 | key.keycode = keycode; | |||
| 162 | key.group = layout; | |||
| 163 | key.level = level; | |||
| 164 | ||||
| 165 | g_array_append_val (retval, key)g_array_append_vals (retval, &(key), 1); | |||
| 166 | } | |||
| 167 | } | |||
| 168 | } | |||
| 169 | } | |||
| 170 | } | |||
| 171 | ||||
| 172 | *n_keys = retval->len; | |||
| 173 | *keys = (CdkKeymapKey*) g_array_free (retval, FALSE(0)); | |||
| 174 | ||||
| 175 | return TRUE(!(0)); | |||
| 176 | } | |||
| 177 | ||||
| 178 | static gboolean | |||
| 179 | cdk_wayland_keymap_get_entries_for_keycode (CdkKeymap *keymap, | |||
| 180 | guint hardware_keycode, | |||
| 181 | CdkKeymapKey **keys, | |||
| 182 | guint **keyvals, | |||
| 183 | gint *n_entries) | |||
| 184 | { | |||
| 185 | struct xkb_keymap *xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 186 | gint num_layouts, layout; | |||
| 187 | gint num_entries; | |||
| 188 | gint i; | |||
| 189 | ||||
| 190 | num_layouts = xkb_keymap_num_layouts_for_key (xkb_keymap, hardware_keycode); | |||
| 191 | ||||
| 192 | num_entries = 0; | |||
| 193 | for (layout = 0; layout < num_layouts; layout++) | |||
| 194 | num_entries += xkb_keymap_num_levels_for_key (xkb_keymap, hardware_keycode, layout); | |||
| 195 | ||||
| 196 | if (n_entries) | |||
| 197 | *n_entries = num_entries; | |||
| 198 | if (keys) | |||
| 199 | *keys = g_new0 (CdkKeymapKey, num_entries)((CdkKeymapKey *) g_malloc0_n ((num_entries), sizeof (CdkKeymapKey ))); | |||
| 200 | if (keyvals) | |||
| 201 | *keyvals = g_new0 (guint, num_entries)((guint *) g_malloc0_n ((num_entries), sizeof (guint))); | |||
| 202 | ||||
| 203 | i = 0; | |||
| 204 | for (layout = 0; layout < num_layouts; layout++) | |||
| 205 | { | |||
| 206 | gint num_levels, level; | |||
| 207 | num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, hardware_keycode, layout); | |||
| 208 | for (level = 0; level < num_levels; level++) | |||
| 209 | { | |||
| 210 | const xkb_keysym_t *syms; | |||
| 211 | int num_syms; | |||
| 212 | num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, hardware_keycode, layout, 0, &syms); | |||
| 213 | if (keys) | |||
| 214 | { | |||
| 215 | (*keys)[i].keycode = hardware_keycode; | |||
| 216 | (*keys)[i].group = layout; | |||
| 217 | (*keys)[i].level = level; | |||
| 218 | } | |||
| 219 | if (keyvals && num_syms > 0) | |||
| 220 | (*keyvals)[i] = syms[0]; | |||
| 221 | ||||
| 222 | i++; | |||
| 223 | } | |||
| 224 | } | |||
| 225 | ||||
| 226 | return num_entries > 0; | |||
| 227 | } | |||
| 228 | ||||
| 229 | static guint | |||
| 230 | cdk_wayland_keymap_lookup_key (CdkKeymap *keymap, | |||
| 231 | const CdkKeymapKey *key) | |||
| 232 | { | |||
| 233 | struct xkb_keymap *xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 234 | const xkb_keysym_t *syms; | |||
| 235 | int num_syms; | |||
| 236 | ||||
| 237 | num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, | |||
| 238 | key->keycode, | |||
| 239 | key->group, | |||
| 240 | key->level, | |||
| 241 | &syms); | |||
| 242 | if (num_syms > 0) | |||
| 243 | return syms[0]; | |||
| 244 | else | |||
| 245 | return XKB_KEY_NoSymbol0x000000; | |||
| 246 | } | |||
| 247 | ||||
| 248 | static guint32 | |||
| 249 | get_xkb_modifiers (struct xkb_keymap *xkb_keymap, | |||
| 250 | CdkModifierType state) | |||
| 251 | { | |||
| 252 | guint32 mods = 0; | |||
| 253 | ||||
| 254 | if (state & CDK_SHIFT_MASK) | |||
| 255 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_SHIFT"Shift"); | |||
| 256 | if (state & CDK_LOCK_MASK) | |||
| 257 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_CAPS"Lock"); | |||
| 258 | if (state & CDK_CONTROL_MASK) | |||
| 259 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_CTRL"Control"); | |||
| 260 | if (state & CDK_MOD1_MASK) | |||
| 261 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_ALT"Mod1"); | |||
| 262 | if (state & CDK_MOD2_MASK) | |||
| 263 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_NUM"Mod2"); | |||
| 264 | if (state & CDK_MOD3_MASK) | |||
| 265 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod3"); | |||
| 266 | if (state & CDK_MOD4_MASK) | |||
| 267 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_LOGO"Mod4"); | |||
| 268 | if (state & CDK_MOD5_MASK) | |||
| 269 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod5"); | |||
| 270 | if (state & CDK_SUPER_MASK) | |||
| 271 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, "Super"); | |||
| 272 | if (state & CDK_HYPER_MASK) | |||
| 273 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, "Hyper"); | |||
| 274 | if (state & CDK_META_MASK) | |||
| 275 | mods |= 1 << xkb_keymap_mod_get_index (xkb_keymap, "Meta"); | |||
| 276 | ||||
| 277 | return mods; | |||
| 278 | } | |||
| 279 | ||||
| 280 | static CdkModifierType | |||
| 281 | get_cdk_modifiers (struct xkb_keymap *xkb_keymap, | |||
| 282 | guint32 mods) | |||
| 283 | { | |||
| 284 | CdkModifierType state = 0; | |||
| 285 | ||||
| 286 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_SHIFT"Shift"))) | |||
| 287 | state |= CDK_SHIFT_MASK; | |||
| 288 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_CAPS"Lock"))) | |||
| 289 | state |= CDK_LOCK_MASK; | |||
| 290 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_CTRL"Control"))) | |||
| 291 | state |= CDK_CONTROL_MASK; | |||
| 292 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_ALT"Mod1"))) | |||
| 293 | state |= CDK_MOD1_MASK; | |||
| 294 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_NUM"Mod2"))) | |||
| 295 | state |= CDK_MOD2_MASK; | |||
| 296 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod3"))) | |||
| 297 | state |= CDK_MOD3_MASK; | |||
| 298 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, XKB_MOD_NAME_LOGO"Mod4"))) | |||
| 299 | state |= CDK_MOD4_MASK; | |||
| 300 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod5"))) | |||
| 301 | state |= CDK_MOD5_MASK; | |||
| 302 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, "Super"))) | |||
| 303 | state |= CDK_SUPER_MASK; | |||
| 304 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, "Hyper"))) | |||
| 305 | state |= CDK_HYPER_MASK; | |||
| 306 | /* Ctk+ treats MOD1 as a synonym for Alt, and does not expect it to | |||
| 307 | * be mapped around, so we should avoid adding CDK_META_MASK if MOD1 | |||
| 308 | * is already included to avoid confusing ctk+ and applications that | |||
| 309 | * rely on that behavior. | |||
| 310 | */ | |||
| 311 | if (mods & (1 << xkb_keymap_mod_get_index (xkb_keymap, "Meta")) && | |||
| 312 | (state & CDK_MOD1_MASK) == 0) | |||
| 313 | state |= CDK_META_MASK; | |||
| 314 | ||||
| 315 | return state; | |||
| 316 | } | |||
| 317 | ||||
| 318 | static gboolean | |||
| 319 | cdk_wayland_keymap_translate_keyboard_state (CdkKeymap *keymap, | |||
| 320 | guint hardware_keycode, | |||
| 321 | CdkModifierType state, | |||
| 322 | gint group, | |||
| 323 | guint *keyval, | |||
| 324 | gint *effective_group, | |||
| 325 | gint *effective_level, | |||
| 326 | CdkModifierType *consumed_modifiers) | |||
| 327 | { | |||
| 328 | struct xkb_keymap *xkb_keymap; | |||
| 329 | struct xkb_state *xkb_state; | |||
| 330 | guint32 modifiers; | |||
| 331 | guint32 consumed; | |||
| 332 | xkb_layout_index_t layout; | |||
| 333 | xkb_level_index_t level; | |||
| 334 | xkb_keysym_t sym; | |||
| 335 | ||||
| 336 | g_return_val_if_fail (keymap == NULL || CDK_IS_KEYMAP (keymap), FALSE)do { if ((keymap == ((void*)0) || (((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((keymap)); GType __t = ((cdk_keymap_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Cdk", ((const char*) (__func__)), "keymap == NULL || CDK_IS_KEYMAP (keymap)" ); return ((0)); } } while (0); | |||
| 337 | g_return_val_if_fail (group < 4, FALSE)do { if ((group < 4)) { } else { g_return_if_fail_warning ( "Cdk", ((const char*) (__func__)), "group < 4"); return (( 0)); } } while (0); | |||
| 338 | ||||
| 339 | xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 340 | ||||
| 341 | modifiers = get_xkb_modifiers (xkb_keymap, state); | |||
| 342 | ||||
| 343 | xkb_state = xkb_state_new (xkb_keymap); | |||
| 344 | ||||
| 345 | xkb_state_update_mask (xkb_state, modifiers, 0, 0, group, 0, 0); | |||
| 346 | ||||
| 347 | layout = xkb_state_key_get_layout (xkb_state, hardware_keycode); | |||
| 348 | level = xkb_state_key_get_level (xkb_state, hardware_keycode, layout); | |||
| 349 | sym = xkb_state_key_get_one_sym (xkb_state, hardware_keycode); | |||
| 350 | consumed = modifiers & ~xkb_state_mod_mask_remove_consumed (xkb_state, hardware_keycode, modifiers); | |||
| 351 | ||||
| 352 | xkb_state_unref (xkb_state); | |||
| 353 | ||||
| 354 | if (keyval) | |||
| 355 | *keyval = sym; | |||
| 356 | if (effective_group) | |||
| 357 | *effective_group = layout; | |||
| 358 | if (effective_level) | |||
| 359 | *effective_level = level; | |||
| 360 | if (consumed_modifiers) | |||
| 361 | *consumed_modifiers = get_cdk_modifiers (xkb_keymap, consumed); | |||
| 362 | ||||
| 363 | return (sym != XKB_KEY_NoSymbol0x000000); | |||
| 364 | } | |||
| 365 | ||||
| 366 | static guint | |||
| 367 | cdk_wayland_keymap_get_modifier_state (CdkKeymap *keymap) | |||
| 368 | { | |||
| 369 | struct xkb_keymap *xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 370 | struct xkb_state *xkb_state = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_state; | |||
| 371 | xkb_mod_mask_t mods; | |||
| 372 | ||||
| 373 | mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE); | |||
| 374 | ||||
| 375 | return get_cdk_modifiers (xkb_keymap, mods); | |||
| 376 | } | |||
| 377 | ||||
| 378 | static void | |||
| 379 | cdk_wayland_keymap_add_virtual_modifiers (CdkKeymap *keymap, | |||
| 380 | CdkModifierType *state) | |||
| 381 | { | |||
| 382 | struct xkb_keymap *xkb_keymap; | |||
| 383 | struct xkb_state *xkb_state; | |||
| 384 | xkb_mod_index_t idx; | |||
| 385 | uint32_t mods, real; | |||
| 386 | struct { const char *name; CdkModifierType mask; } vmods[] = { | |||
| 387 | { "Super", CDK_SUPER_MASK }, | |||
| 388 | { "Hyper", CDK_HYPER_MASK }, | |||
| 389 | { "Meta", CDK_META_MASK }, | |||
| 390 | { NULL((void*)0), 0 } | |||
| 391 | }; | |||
| 392 | int i; | |||
| 393 | ||||
| 394 | xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 395 | mods = get_xkb_modifiers (xkb_keymap, *state); | |||
| 396 | ||||
| 397 | xkb_state = xkb_state_new (xkb_keymap); | |||
| 398 | ||||
| 399 | for (i = 0; vmods[i].name; i++) | |||
| 400 | { | |||
| 401 | idx = xkb_keymap_mod_get_index (xkb_keymap, vmods[i].name); | |||
| 402 | if (idx == XKB_MOD_INVALID(0xffffffff)) | |||
| 403 | continue; | |||
| 404 | ||||
| 405 | xkb_state_update_mask (xkb_state, 1 << idx, 0, 0, 0, 0, 0); | |||
| 406 | real = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE); | |||
| 407 | real &= 0xf0; /* ignore mapping to Lock, Shift, Control, Mod1 */ | |||
| 408 | if (mods & real) | |||
| 409 | *state |= vmods[i].mask; | |||
| 410 | xkb_state_update_mask (xkb_state, 0, 0, 0, 0, 0, 0); | |||
| 411 | } | |||
| 412 | ||||
| 413 | xkb_state_unref (xkb_state); | |||
| 414 | } | |||
| 415 | ||||
| 416 | static gboolean | |||
| 417 | cdk_wayland_keymap_map_virtual_modifiers (CdkKeymap *keymap, | |||
| 418 | CdkModifierType *state) | |||
| 419 | { | |||
| 420 | struct xkb_keymap *xkb_keymap; | |||
| 421 | struct xkb_state *xkb_state; | |||
| 422 | uint32_t mods, mapped; | |||
| 423 | gboolean ret = TRUE(!(0)); | |||
| 424 | ||||
| 425 | xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 426 | mods = get_xkb_modifiers (xkb_keymap, *state); | |||
| 427 | ||||
| 428 | xkb_state = xkb_state_new (xkb_keymap); | |||
| 429 | xkb_state_update_mask (xkb_state, mods & ~0xff, 0, 0, 0, 0, 0); | |||
| 430 | mapped = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE); | |||
| 431 | if ((mapped & mods & 0xff) != 0) | |||
| 432 | ret = FALSE(0); | |||
| 433 | *state |= get_cdk_modifiers (xkb_keymap, mapped); | |||
| 434 | ||||
| 435 | xkb_state_unref (xkb_state); | |||
| 436 | ||||
| 437 | return ret; | |||
| 438 | } | |||
| 439 | ||||
| 440 | static void | |||
| 441 | _cdk_wayland_keymap_class_init (CdkWaylandKeymapClass *klass) | |||
| 442 | { | |||
| 443 | GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); | |||
| 444 | CdkKeymapClass *keymap_class = CDK_KEYMAP_CLASS (klass)((((CdkKeymapClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), ((cdk_keymap_get_type ())))))); | |||
| 445 | ||||
| 446 | object_class->finalize = cdk_wayland_keymap_finalize; | |||
| 447 | ||||
| 448 | keymap_class->get_direction = cdk_wayland_keymap_get_direction; | |||
| 449 | keymap_class->have_bidi_layouts = cdk_wayland_keymap_have_bidi_layouts; | |||
| 450 | keymap_class->get_caps_lock_state = cdk_wayland_keymap_get_caps_lock_state; | |||
| 451 | keymap_class->get_num_lock_state = cdk_wayland_keymap_get_num_lock_state; | |||
| 452 | keymap_class->get_scroll_lock_state = cdk_wayland_keymap_get_scroll_lock_state; | |||
| 453 | keymap_class->get_entries_for_keyval = cdk_wayland_keymap_get_entries_for_keyval; | |||
| 454 | keymap_class->get_entries_for_keycode = cdk_wayland_keymap_get_entries_for_keycode; | |||
| 455 | keymap_class->lookup_key = cdk_wayland_keymap_lookup_key; | |||
| 456 | keymap_class->translate_keyboard_state = cdk_wayland_keymap_translate_keyboard_state; | |||
| 457 | keymap_class->get_modifier_state = cdk_wayland_keymap_get_modifier_state; | |||
| 458 | keymap_class->add_virtual_modifiers = cdk_wayland_keymap_add_virtual_modifiers; | |||
| 459 | keymap_class->map_virtual_modifiers = cdk_wayland_keymap_map_virtual_modifiers; | |||
| 460 | } | |||
| 461 | ||||
| 462 | static void | |||
| 463 | _cdk_wayland_keymap_init (CdkWaylandKeymap *keymap G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 464 | { | |||
| 465 | } | |||
| 466 | ||||
| 467 | static void | |||
| 468 | update_direction (CdkWaylandKeymap *keymap) | |||
| 469 | { | |||
| 470 | gint num_layouts; | |||
| 471 | gint i; | |||
| 472 | gint *rtl; | |||
| 473 | xkb_keycode_t min_keycode, max_keycode; | |||
| 474 | guint key; | |||
| 475 | gboolean have_rtl, have_ltr; | |||
| 476 | ||||
| 477 | num_layouts = xkb_keymap_num_layouts (keymap->xkb_keymap); | |||
| 478 | ||||
| 479 | keymap->direction = g_renew (PangoDirection, keymap->direction, num_layouts)((PangoDirection *) g_realloc_n (keymap->direction, (num_layouts ), sizeof (PangoDirection))); | |||
| 480 | rtl = g_newa (gint, num_layouts)((gint*) __builtin_alloca (sizeof (gint) * (gsize) (num_layouts ))); | |||
| 481 | for (i = 0; i
| |||
| 482 | rtl[i] = 0; | |||
| 483 | ||||
| 484 | min_keycode = xkb_keymap_min_keycode (keymap->xkb_keymap); | |||
| 485 | max_keycode = xkb_keymap_max_keycode (keymap->xkb_keymap); | |||
| 486 | for (key = min_keycode; key < max_keycode; key++) | |||
| 487 | { | |||
| 488 | gint layouts, layout; | |||
| 489 | ||||
| 490 | layouts = xkb_keymap_num_layouts_for_key (keymap->xkb_keymap, key); | |||
| 491 | for (layout = 0; layout < layouts; layout++) | |||
| 492 | { | |||
| 493 | const xkb_keysym_t *syms; | |||
| 494 | gint num_syms; | |||
| 495 | gint sym; | |||
| 496 | ||||
| 497 | num_syms = xkb_keymap_key_get_syms_by_level (keymap->xkb_keymap, key, layout, 0, &syms); | |||
| 498 | for (sym = 0; sym < num_syms; sym++) | |||
| 499 | { | |||
| 500 | PangoDirection dir; | |||
| 501 | ||||
| 502 | dir = cdk_unichar_direction (xkb_keysym_to_utf32 (syms[sym])); | |||
| 503 | switch (dir) | |||
| 504 | { | |||
| 505 | case PANGO_DIRECTION_RTL: | |||
| 506 | rtl[layout]++; | |||
| 507 | break; | |||
| 508 | case PANGO_DIRECTION_LTR: | |||
| 509 | rtl[layout]--; | |||
| ||||
| 510 | break; | |||
| 511 | default: | |||
| 512 | break; | |||
| 513 | } | |||
| 514 | } | |||
| 515 | } | |||
| 516 | } | |||
| 517 | ||||
| 518 | have_rtl = have_ltr = FALSE(0); | |||
| 519 | for (i = 0; i < num_layouts; i++) | |||
| 520 | { | |||
| 521 | if (rtl[i] > 0) | |||
| 522 | { | |||
| 523 | keymap->direction[i] = PANGO_DIRECTION_RTL; | |||
| 524 | have_rtl = TRUE(!(0)); | |||
| 525 | } | |||
| 526 | else | |||
| 527 | { | |||
| 528 | keymap->direction[i] = PANGO_DIRECTION_LTR; | |||
| 529 | have_ltr = TRUE(!(0)); | |||
| 530 | } | |||
| 531 | } | |||
| 532 | ||||
| 533 | if (have_rtl && have_ltr) | |||
| 534 | keymap->bidi = TRUE(!(0)); | |||
| 535 | } | |||
| 536 | ||||
| 537 | CdkKeymap * | |||
| 538 | _cdk_wayland_keymap_new (void) | |||
| 539 | { | |||
| 540 | CdkWaylandKeymap *keymap; | |||
| 541 | struct xkb_context *context; | |||
| 542 | struct xkb_rule_names names; | |||
| 543 | ||||
| 544 | keymap = g_object_new (_cdk_wayland_keymap_get_type(), NULL((void*)0)); | |||
| 545 | ||||
| 546 | context = xkb_context_new (0); | |||
| 547 | ||||
| 548 | names.rules = "evdev"; | |||
| 549 | names.model = "pc105"; | |||
| 550 | names.layout = "us"; | |||
| 551 | names.variant = ""; | |||
| 552 | names.options = ""; | |||
| 553 | keymap->xkb_keymap = xkb_keymap_new_from_names (context, &names, 0); | |||
| 554 | keymap->xkb_state = xkb_state_new (keymap->xkb_keymap); | |||
| 555 | xkb_context_unref (context); | |||
| 556 | ||||
| 557 | update_direction (keymap); | |||
| 558 | ||||
| 559 | return CDK_KEYMAP (keymap)((((CdkKeymap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((keymap)), ((cdk_keymap_get_type ())))))); | |||
| 560 | } | |||
| 561 | ||||
| 562 | #ifdef G_ENABLE_DEBUG1 | |||
| 563 | static void | |||
| 564 | print_modifiers (struct xkb_keymap *keymap) | |||
| 565 | { | |||
| 566 | int i, j; | |||
| 567 | uint32_t real; | |||
| 568 | struct xkb_state *state; | |||
| 569 | ||||
| 570 | g_print ("modifiers:\n"); | |||
| 571 | for (i = 0; i < xkb_keymap_num_mods (keymap); i++) | |||
| 572 | g_print ("%s ", xkb_keymap_mod_get_name (keymap, i)); | |||
| 573 | g_print ("\n\n"); | |||
| 574 | ||||
| 575 | g_print ("modifier mapping\n"); | |||
| 576 | state = xkb_state_new (keymap); | |||
| 577 | for (i = 0; i < 8; i++) | |||
| 578 | { | |||
| 579 | gboolean need_arrow = TRUE(!(0)); | |||
| 580 | g_print ("%s ", xkb_keymap_mod_get_name (keymap, i)); | |||
| 581 | for (j = 8; j < xkb_keymap_num_mods (keymap); j++) | |||
| 582 | { | |||
| 583 | xkb_state_update_mask (state, 1 << j, 0, 0, 0, 0, 0); | |||
| 584 | real = xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE); | |||
| 585 | if (real & (1 << i)) | |||
| 586 | { | |||
| 587 | if (need_arrow) | |||
| 588 | { | |||
| 589 | g_print ("-> "); | |||
| 590 | need_arrow = FALSE(0); | |||
| 591 | } | |||
| 592 | g_print ("%s ", xkb_keymap_mod_get_name (keymap, j)); | |||
| 593 | } | |||
| 594 | } | |||
| 595 | g_print ("\n"); | |||
| 596 | } | |||
| 597 | ||||
| 598 | xkb_state_unref (state); | |||
| 599 | } | |||
| 600 | #endif | |||
| 601 | ||||
| 602 | void | |||
| 603 | _cdk_wayland_keymap_update_from_fd (CdkKeymap *keymap, | |||
| 604 | uint32_t format, | |||
| 605 | uint32_t fd, | |||
| 606 | uint32_t size) | |||
| 607 | { | |||
| 608 | CdkWaylandKeymap *keymap_wayland = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () )))))); | |||
| 609 | struct xkb_context *context; | |||
| 610 | struct xkb_keymap *xkb_keymap; | |||
| 611 | char *map_str; | |||
| 612 | ||||
| 613 | context = xkb_context_new (0); | |||
| 614 | ||||
| 615 | map_str = mmap (NULL((void*)0), size, PROT_READ0x1, MAP_SHARED0x01, fd, 0); | |||
| 616 | if (map_str == MAP_FAILED((void *) -1)) | |||
| ||||
| 617 | { | |||
| 618 | close(fd); | |||
| 619 | return; | |||
| 620 | } | |||
| 621 | ||||
| 622 | CDK_NOTE(INPUT, g_print ("keymap:\n%s\n", map_str))do { if ((_cdk_debug_flags & CDK_DEBUG_INPUT)) { g_print ( "keymap:\n%s\n", map_str); }; } while (0); | |||
| 623 | ||||
| 624 | xkb_keymap = xkb_keymap_new_from_string (context, map_str, format, 0); | |||
| 625 | munmap (map_str, size); | |||
| 626 | close (fd); | |||
| 627 | ||||
| 628 | if (!xkb_keymap) | |||
| 629 | { | |||
| 630 | g_warning ("Got invalid keymap from compositor, keeping previous/default one"); | |||
| 631 | xkb_context_unref (context); | |||
| 632 | return; | |||
| 633 | } | |||
| 634 | ||||
| 635 | CDK_NOTE(INPUT, print_modifiers (xkb_keymap))do { if ((_cdk_debug_flags & CDK_DEBUG_INPUT)) { print_modifiers (xkb_keymap); }; } while (0); | |||
| 636 | ||||
| 637 | xkb_keymap_unref (keymap_wayland->xkb_keymap); | |||
| 638 | keymap_wayland->xkb_keymap = xkb_keymap; | |||
| 639 | ||||
| 640 | xkb_state_unref (keymap_wayland->xkb_state); | |||
| 641 | keymap_wayland->xkb_state = xkb_state_new (keymap_wayland->xkb_keymap); | |||
| 642 | ||||
| 643 | xkb_context_unref (context); | |||
| 644 | ||||
| 645 | update_direction (keymap_wayland); | |||
| 646 | } | |||
| 647 | ||||
| 648 | struct xkb_keymap * | |||
| 649 | _cdk_wayland_keymap_get_xkb_keymap (CdkKeymap *keymap) | |||
| 650 | { | |||
| 651 | return CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 652 | } | |||
| 653 | ||||
| 654 | struct xkb_state * | |||
| 655 | _cdk_wayland_keymap_get_xkb_state (CdkKeymap *keymap) | |||
| 656 | { | |||
| 657 | return CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_state; | |||
| 658 | } | |||
| 659 | ||||
| 660 | gboolean | |||
| 661 | _cdk_wayland_keymap_key_is_modifier (CdkKeymap *keymap, | |||
| 662 | guint keycode) | |||
| 663 | { | |||
| 664 | struct xkb_keymap *xkb_keymap = CDK_WAYLAND_KEYMAP (keymap)((((CdkWaylandKeymap*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((keymap)), ((_cdk_wayland_keymap_get_type () ))))))->xkb_keymap; | |||
| 665 | struct xkb_state *xkb_state; | |||
| 666 | gboolean is_modifier; | |||
| 667 | ||||
| 668 | is_modifier = FALSE(0); | |||
| 669 | ||||
| 670 | xkb_state = xkb_state_new (xkb_keymap); | |||
| 671 | ||||
| 672 | if (xkb_state_update_key (xkb_state, keycode, XKB_KEY_DOWN) & XKB_STATE_MODS_EFFECTIVE) | |||
| 673 | is_modifier = TRUE(!(0)); | |||
| 674 | ||||
| 675 | xkb_state_unref (xkb_state); | |||
| 676 | ||||
| 677 | return is_modifier; | |||
| 678 | } |