| File: | cdk/wayland/cdkkeys-wayland.c |
| Warning: | line 173, column 11 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
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)); |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
| 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 < num_layouts; 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 | } |