Bug Summary

File:cdk/x11/cdkkeys-x11.c
Warning:line 1030, column 20
Access to field 'len' results in a dereference of a null pointer (loaded from variable 'key_array')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cdkkeys-x11.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/cdk/x11 -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -D G_LOG_DOMAIN="Cdk" -D G_LOG_USE_STRUCTURED=1 -D CDK_COMPILATION -I ../.. -I ../../cdk -I ../../cdk -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/cdk/x11 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-172131-43638-1 -x c cdkkeys-x11.c
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 "cdkx11keys.h"
28#include "cdkkeysprivate.h"
29#include "cdkkeysyms.h"
30#include "cdkprivate-x11.h"
31#include "cdkdisplay-x11.h"
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37#include <limits.h>
38#include <errno(*__errno_location ()).h>
39
40#ifdef HAVE_XKB1
41#include <X11/XKBlib.h>
42
43/* OSF-4.0 is apparently missing this macro
44 */
45# ifndef XkbKeySymEntry
46# define XkbKeySymEntry(d,k,sl,g)((((&((d)->map)->syms[(((d)->map)->key_sym_map
[(k)].offset)]))[((((((d)->map)->key_sym_map[k].width))
*(g))+(sl))]))
\
47 (XkbKeySym(d,k,((XkbKeyGroupsWidth(d,k)*(g))+(sl)))(((&((d)->map)->syms[(((d)->map)->key_sym_map
[(k)].offset)]))[((((((d)->map)->key_sym_map[k].width))
*(g))+(sl))])
)
48# endif
49#endif /* HAVE_XKB */
50
51typedef struct _DirectionCacheEntry DirectionCacheEntry;
52
53struct _DirectionCacheEntry
54{
55 guint serial;
56 Atom group_atom;
57 PangoDirection direction;
58};
59
60struct _CdkX11Keymap
61{
62 CdkKeymap parent_instance;
63
64 gint min_keycode;
65 gint max_keycode;
66 KeySym* keymap;
67 gint keysyms_per_keycode;
68 XModifierKeymap* mod_keymap;
69 guint lock_keysym;
70 CdkModifierType group_switch_mask;
71 CdkModifierType num_lock_mask;
72 CdkModifierType scroll_lock_mask;
73 CdkModifierType modmap[8];
74 PangoDirection current_direction;
75 guint have_direction : 1;
76 guint have_lock_state : 1;
77 guint caps_lock_state : 1;
78 guint num_lock_state : 1;
79 guint scroll_lock_state : 1;
80 guint modifier_state;
81 guint current_serial;
82
83#ifdef HAVE_XKB1
84 XkbDescPtr xkb_desc;
85 /* We cache the directions */
86 Atom current_group_atom;
87 guint current_cache_serial;
88 /* A cache of size four should be more than enough, people usually
89 * have two groups around, and the xkb limit is four. It still
90 * works correct for more than four groups. It's just the
91 * cache.
92 */
93 DirectionCacheEntry group_direction_cache[4];
94#endif
95};
96
97struct _CdkX11KeymapClass
98{
99 CdkKeymapClass parent_class;
100};
101
102#define KEYMAP_USE_XKB(keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
CDK_X11_DISPLAY ((keymap)->display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))
->use_xkb
103#define KEYMAP_XDISPLAY(keymap)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->xdisplay)
CDK_DISPLAY_XDISPLAY ((keymap)->display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->xdisplay)
104
105G_DEFINE_TYPE (CdkX11Keymap, cdk_x11_keymap, CDK_TYPE_KEYMAP)static void cdk_x11_keymap_init (CdkX11Keymap *self); static void
cdk_x11_keymap_class_init (CdkX11KeymapClass *klass); static
GType cdk_x11_keymap_get_type_once (void); static gpointer cdk_x11_keymap_parent_class
= ((void*)0); static gint CdkX11Keymap_private_offset; static
void cdk_x11_keymap_class_intern_init (gpointer klass) { cdk_x11_keymap_parent_class
= g_type_class_peek_parent (klass); if (CdkX11Keymap_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CdkX11Keymap_private_offset
); cdk_x11_keymap_class_init ((CdkX11KeymapClass*) klass); } __attribute__
((__unused__)) static inline gpointer cdk_x11_keymap_get_instance_private
(CdkX11Keymap *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (CdkX11Keymap_private_offset)))); } GType cdk_x11_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_x11_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_x11_keymap_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
cdk_keymap_get_type ()), g_intern_static_string ("CdkX11Keymap"
), sizeof (CdkX11KeymapClass), (GClassInitFunc)(void (*)(void
)) cdk_x11_keymap_class_intern_init, sizeof (CdkX11Keymap), (
GInstanceInitFunc)(void (*)(void)) cdk_x11_keymap_init, (GTypeFlags
) 0); { {{};} } return g_define_type_id; }
106
107static void
108cdk_x11_keymap_init (CdkX11Keymap *keymap)
109{
110 keymap->min_keycode = 0;
111 keymap->max_keycode = 0;
112
113 keymap->keymap = NULL((void*)0);
114 keymap->keysyms_per_keycode = 0;
115 keymap->mod_keymap = NULL((void*)0);
116
117 keymap->num_lock_mask = 0;
118 keymap->scroll_lock_mask = 0;
119 keymap->group_switch_mask = 0;
120 keymap->lock_keysym = CDK_KEY_Caps_Lock0xffe5;
121 keymap->have_direction = FALSE(0);
122 keymap->have_lock_state = FALSE(0);
123 keymap->current_serial = 0;
124
125#ifdef HAVE_XKB1
126 keymap->xkb_desc = NULL((void*)0);
127 keymap->current_group_atom = 0;
128 keymap->current_cache_serial = 0;
129#endif
130
131}
132
133static void
134cdk_x11_keymap_finalize (GObject *object)
135{
136 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (object)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((cdk_x11_keymap_get_type()))))))
;
137
138 if (keymap_x11->keymap)
139 XFree (keymap_x11->keymap);
140
141 if (keymap_x11->mod_keymap)
142 XFreeModifiermap (keymap_x11->mod_keymap);
143
144#ifdef HAVE_XKB1
145 if (keymap_x11->xkb_desc)
146 XkbFreeKeyboard (keymap_x11->xkb_desc, XkbAllComponentsMask(0x7f), True1);
147#endif
148
149 G_OBJECT_CLASS (cdk_x11_keymap_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cdk_x11_keymap_parent_class)), (((GType) ((20) << (
2))))))))
->finalize (object);
150}
151
152static inline void
153update_keyrange (CdkX11Keymap *keymap_x11)
154{
155 if (keymap_x11->max_keycode == 0)
156 XDisplayKeycodes (KEYMAP_XDISPLAY (CDK_KEYMAP (keymap_x11))(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((((((CdkKeymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap_x11)), ((cdk_keymap_get_type ())))))))->display
)), ((cdk_x11_display_get_type()))))))->xdisplay)
,
157 &keymap_x11->min_keycode, &keymap_x11->max_keycode);
158}
159
160#ifdef HAVE_XKB1
161
162static void
163update_modmap (Display *display,
164 CdkX11Keymap *keymap_x11)
165{
166 static struct {
167 const gchar *name;
168 Atom atom;
169 CdkModifierType mask;
170 } vmods[] = {
171 { "Meta", 0, CDK_META_MASK },
172 { "Super", 0, CDK_SUPER_MASK },
173 { "Hyper", 0, CDK_HYPER_MASK },
174 { NULL((void*)0), 0, 0 }
175 };
176
177 gint i, j, k;
178
179 if (!vmods[0].atom)
180 for (i = 0; vmods[i].name; i++)
181 vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE(0));
182
183 for (i = 0; i < 8; i++)
184 keymap_x11->modmap[i] = 1 << i;
185
186 for (i = 0; i < XkbNumVirtualMods16; i++)
187 {
188 for (j = 0; vmods[j].atom; j++)
189 {
190 if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom)
191 {
192 for (k = 0; k < 8; k++)
193 {
194 if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k))
195 keymap_x11->modmap[k] |= vmods[j].mask;
196 }
197 }
198 }
199 }
200}
201
202static XkbDescPtr
203get_xkb (CdkX11Keymap *keymap_x11)
204{
205 CdkX11Display *display_x11 = CDK_X11_DISPLAY (CDK_KEYMAP (keymap_x11)->display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((((CdkKeymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap_x11)), ((cdk_keymap_get_type ()))))))->display
)), ((cdk_x11_display_get_type()))))))
;
206 Display *xdisplay = display_x11->xdisplay;
207
208 update_keyrange (keymap_x11);
209
210 if (keymap_x11->xkb_desc == NULL((void*)0))
211 {
212 keymap_x11->xkb_desc = XkbGetMap (xdisplay, XkbKeySymsMask(1<<1) | XkbKeyTypesMask(1<<0) | XkbModifierMapMask(1<<2) | XkbVirtualModsMask(1<<6), XkbUseCoreKbd0x0100);
213 if (keymap_x11->xkb_desc == NULL((void*)0))
214 {
215 g_error ("Failed to get keymap");
216 return NULL((void*)0);
217 }
218
219 XkbGetNames (xdisplay, XkbGroupNamesMask(1<<12) | XkbVirtualModNamesMask(1<<11), keymap_x11->xkb_desc);
220
221 update_modmap (xdisplay, keymap_x11);
222 }
223 else if (keymap_x11->current_serial != display_x11->keymap_serial)
224 {
225 XkbGetUpdatedMap (xdisplay, XkbKeySymsMask(1<<1) | XkbKeyTypesMask(1<<0) | XkbModifierMapMask(1<<2) | XkbVirtualModsMask(1<<6),
226 keymap_x11->xkb_desc);
227 XkbGetNames (xdisplay, XkbGroupNamesMask(1<<12) | XkbVirtualModNamesMask(1<<11), keymap_x11->xkb_desc);
228
229 update_modmap (xdisplay, keymap_x11);
230 }
231
232 keymap_x11->current_serial = display_x11->keymap_serial;
233
234 if (keymap_x11->num_lock_mask == 0)
235 keymap_x11->num_lock_mask = XkbKeysymToModifiers (KEYMAP_XDISPLAY (CDK_KEYMAP (keymap_x11))(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((((((CdkKeymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap_x11)), ((cdk_keymap_get_type ())))))))->display
)), ((cdk_x11_display_get_type()))))))->xdisplay)
, CDK_KEY_Num_Lock0xff7f);
236
237 if (keymap_x11->scroll_lock_mask == 0)
238 keymap_x11->scroll_lock_mask = XkbKeysymToModifiers (KEYMAP_XDISPLAY (CDK_KEYMAP (keymap_x11))(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((((((CdkKeymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap_x11)), ((cdk_keymap_get_type ())))))))->display
)), ((cdk_x11_display_get_type()))))))->xdisplay)
, CDK_KEY_Scroll_Lock0xff14);
239
240
241 return keymap_x11->xkb_desc;
242}
243#endif /* HAVE_XKB */
244
245/* Whether we were able to turn on detectable-autorepeat using
246 * XkbSetDetectableAutorepeat. If FALSE, we’ll fall back
247 * to checking the next event with XPending().
248 */
249
250/* Find the index of the group/level pair within the keysyms for a key.
251 * We round up the number of keysyms per keycode to the next even number,
252 * otherwise we lose a whole group of keys
253 */
254#define KEYSYM_INDEX(keymap_impl, group, level)(2 * ((group) % (gint)((keymap_impl->keysyms_per_keycode +
1) / 2)) + (level))
\
255 (2 * ((group) % (gint)((keymap_impl->keysyms_per_keycode + 1) / 2)) + (level))
256#define KEYSYM_IS_KEYPAD(s)(((s) >= 0xff80 && (s) <= 0xffbd) || ((s) >=
0x11000000 && (s) <= 0x1100ffff))
(((s) >= 0xff80 && (s) <= 0xffbd) || \
257 ((s) >= 0x11000000 && (s) <= 0x1100ffff))
258
259static gint
260get_symbol (const KeySym *syms,
261 CdkX11Keymap *keymap_x11,
262 gint group,
263 gint level)
264{
265 gint index;
266
267 index = KEYSYM_INDEX(keymap_x11, group, level)(2 * ((group) % (gint)((keymap_x11->keysyms_per_keycode + 1
) / 2)) + (level))
;
268 if (index >= keymap_x11->keysyms_per_keycode)
269 return NoSymbol0L;
270
271 return syms[index];
272}
273
274static void
275set_symbol (KeySym *syms,
276 CdkX11Keymap *keymap_x11,
277 gint group,
278 gint level,
279 KeySym sym)
280{
281 gint index;
282
283 index = KEYSYM_INDEX(keymap_x11, group, level)(2 * ((group) % (gint)((keymap_x11->keysyms_per_keycode + 1
) / 2)) + (level))
;
284 if (index >= keymap_x11->keysyms_per_keycode)
285 return;
286
287 syms[index] = sym;
288}
289
290static void
291update_keymaps (CdkX11Keymap *keymap_x11)
292{
293 CdkX11Display *display_x11 = CDK_X11_DISPLAY (CDK_KEYMAP (keymap_x11)->display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((((CdkKeymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap_x11)), ((cdk_keymap_get_type ()))))))->display
)), ((cdk_x11_display_get_type()))))))
;
294 Display *xdisplay = display_x11->xdisplay;
295
296#ifdef HAVE_XKB1
297 g_assert (!KEYMAP_USE_XKB (CDK_KEYMAP (keymap_x11)))do { if (!((((CdkX11Display*) (void *) g_type_check_instance_cast
((GTypeInstance*) (((((((CdkKeymap*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((keymap_x11)), ((cdk_keymap_get_type ()))
)))))->display)), ((cdk_x11_display_get_type()))))))->use_xkb
) ; else g_assertion_message_expr ("Cdk", "cdkkeys-x11.c", 297
, ((const char*) (__func__)), "!KEYMAP_USE_XKB (CDK_KEYMAP (keymap_x11))"
); } while (0)
;
298#endif
299
300 if (keymap_x11->keymap == NULL((void*)0) ||
301 keymap_x11->current_serial != display_x11->keymap_serial)
302 {
303 gint i;
304 gint map_size;
305 gint keycode;
306
307 keymap_x11->current_serial = display_x11->keymap_serial;
308
309 update_keyrange (keymap_x11);
310
311 if (keymap_x11->keymap)
312 XFree (keymap_x11->keymap);
313
314 if (keymap_x11->mod_keymap)
315 XFreeModifiermap (keymap_x11->mod_keymap);
316
317 keymap_x11->keymap = XGetKeyboardMapping (xdisplay, keymap_x11->min_keycode,
318 keymap_x11->max_keycode - keymap_x11->min_keycode + 1,
319 &keymap_x11->keysyms_per_keycode);
320
321
322 /* CDK_KEY_ISO_Left_Tab, as usually configured through XKB, really messes
323 * up the whole idea of "consumed modifiers" because shift is consumed.
324 * However, <shift>Tab is not usually CDK_KEY_ISO_Left_Tab without XKB,
325 * we we fudge the map here.
326 */
327 keycode = keymap_x11->min_keycode;
328 while (keycode <= keymap_x11->max_keycode)
329 {
330 KeySym *syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
331 /* Check both groups */
332 for (i = 0 ; i < 2 ; i++)
333 {
334 if (get_symbol (syms, keymap_x11, i, 0) == CDK_KEY_Tab0xff09)
335 set_symbol (syms, keymap_x11, i, 1, CDK_KEY_ISO_Left_Tab0xfe20);
336 }
337
338 /*
339 * If there is one keysym and the key symbol has upper and lower
340 * case variants fudge the keymap
341 */
342 if (get_symbol (syms, keymap_x11, 0, 1) == 0)
343 {
344 guint lower;
345 guint upper;
346
347 cdk_keyval_convert_case (get_symbol (syms, keymap_x11, 0, 0), &lower, &upper);
348 if (lower != upper)
349 {
350 set_symbol (syms, keymap_x11, 0, 0, lower);
351 set_symbol (syms, keymap_x11, 0, 1, upper);
352 }
353 }
354
355 ++keycode;
356 }
357
358 keymap_x11->mod_keymap = XGetModifierMapping (xdisplay);
359
360 keymap_x11->lock_keysym = CDK_KEY_VoidSymbol0xffffff;
361 keymap_x11->group_switch_mask = 0;
362 keymap_x11->num_lock_mask = 0;
363 keymap_x11->scroll_lock_mask = 0;
364
365 for (i = 0; i < 8; i++)
366 keymap_x11->modmap[i] = 1 << i;
367
368 /* There are 8 sets of modifiers, with each set containing
369 * max_keypermod keycodes.
370 */
371 map_size = 8 * keymap_x11->mod_keymap->max_keypermod;
372 for (i = 0; i < map_size; i++)
373 {
374 /* Get the key code at this point in the map. */
375 gint code = keymap_x11->mod_keymap->modifiermap[i];
376 gint j;
377 KeySym *syms;
378 guint mask;
379
380 /* Ignore invalid keycodes. */
381 if (code < keymap_x11->min_keycode ||
382 code > keymap_x11->max_keycode)
383 continue;
384
385 syms = keymap_x11->keymap + (code - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
386
387 mask = 0;
388 for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
389 {
390 if (syms[j] == CDK_KEY_Meta_L0xffe7 ||
391 syms[j] == CDK_KEY_Meta_R0xffe8)
392 mask |= CDK_META_MASK;
393 else if (syms[j] == CDK_KEY_Hyper_L0xffed ||
394 syms[j] == CDK_KEY_Hyper_R0xffee)
395 mask |= CDK_HYPER_MASK;
396 else if (syms[j] == CDK_KEY_Super_L0xffeb ||
397 syms[j] == CDK_KEY_Super_R0xffec)
398 mask |= CDK_SUPER_MASK;
399 }
400
401 keymap_x11->modmap[i / keymap_x11->mod_keymap->max_keypermod] |= mask;
402
403 /* The fourth modifier, CDK_MOD1_MASK is 1 << 3.
404 * Each group of max_keypermod entries refers to the same modifier.
405 */
406 mask = 1 << (i / keymap_x11->mod_keymap->max_keypermod);
407
408 switch (mask)
409 {
410 case CDK_LOCK_MASK:
411 /* Get the Lock keysym. If any keysym bound to the Lock modifier
412 * is Caps_Lock, we will interpret the modifier as Caps_Lock;
413 * otherwise, if any is bound to Shift_Lock, we will interpret
414 * the modifier as Shift_Lock. Otherwise, the lock modifier
415 * has no effect.
416 */
417 for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
418 {
419 if (syms[j] == CDK_KEY_Caps_Lock0xffe5)
420 keymap_x11->lock_keysym = CDK_KEY_Caps_Lock0xffe5;
421 else if (syms[j] == CDK_KEY_Shift_Lock0xffe6 &&
422 keymap_x11->lock_keysym == CDK_KEY_VoidSymbol0xffffff)
423 keymap_x11->lock_keysym = CDK_KEY_Shift_Lock0xffe6;
424 }
425 break;
426
427 case CDK_CONTROL_MASK:
428 case CDK_SHIFT_MASK:
429 case CDK_MOD1_MASK:
430 /* Some keyboard maps are known to map Mode_Switch as an
431 * extra Mod1 key. In circumstances like that, it won't be
432 * used to switch groups.
433 */
434 break;
435
436 default:
437 /* Find the Mode_Switch, Num_Lock and Scroll_Lock modifiers. */
438 for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
439 {
440 if (syms[j] == CDK_KEY_Mode_switch0xff7e)
441 {
442 /* This modifier swaps groups */
443 keymap_x11->group_switch_mask |= mask;
444 }
445 else if (syms[j] == CDK_KEY_Num_Lock0xff7f)
446 {
447 /* This modifier is used for Num_Lock */
448 keymap_x11->num_lock_mask |= mask;
449 }
450 else if (syms[j] == CDK_KEY_Scroll_Lock0xff14)
451 {
452 /* This modifier is used for Scroll_Lock */
453 keymap_x11->scroll_lock_mask |= mask;
454 }
455 }
456 break;
457 }
458 }
459 }
460}
461
462static const KeySym*
463get_keymap (CdkX11Keymap *keymap_x11)
464{
465 update_keymaps (keymap_x11);
466
467 return keymap_x11->keymap;
468}
469
470#ifdef HAVE_XKB1
471static PangoDirection
472get_direction (XkbDescRec *xkb,
473 gint group)
474{
475 gint code;
476
477 gint rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */
478
479 for (code = xkb->min_key_code; code <= xkb->max_key_code; code++)
480 {
481 gint level = 0;
482 KeySym sym = XkbKeySymEntry (xkb, code, level, group)((((&((xkb)->map)->syms[(((xkb)->map)->key_sym_map
[(code)].offset)]))[((((((xkb)->map)->key_sym_map[code]
.width))*(group))+(level))]))
;
483 PangoDirection dir = cdk_unichar_direction (cdk_keyval_to_unicode (sym));
484
485 switch (dir)
486 {
487 case PANGO_DIRECTION_RTL:
488 rtl_minus_ltr++;
489 break;
490 case PANGO_DIRECTION_LTR:
491 rtl_minus_ltr--;
492 break;
493 default:
494 break;
495 }
496 }
497
498 if (rtl_minus_ltr > 0)
499 return PANGO_DIRECTION_RTL;
500 else
501 return PANGO_DIRECTION_LTR;
502}
503
504static PangoDirection
505get_direction_from_cache (CdkX11Keymap *keymap_x11,
506 XkbDescPtr xkb,
507 gint group)
508{
509 Atom group_atom = xkb->names->groups[group];
510
511 gboolean cache_hit = FALSE(0);
512 DirectionCacheEntry *cache = keymap_x11->group_direction_cache;
513
514 PangoDirection direction = PANGO_DIRECTION_NEUTRAL;
515 gint i;
516
517 if (keymap_x11->have_direction)
518 {
519 /* lookup in cache */
520 for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache)(sizeof (keymap_x11->group_direction_cache) / sizeof ((keymap_x11
->group_direction_cache)[0]))
; i++)
521 {
522 if (cache[i].group_atom == group_atom)
523 {
524 cache_hit = TRUE(!(0));
525 cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */
526 direction = cache[i].direction;
527 group_atom = cache[i].group_atom;
528 break;
529 }
530 }
531 }
532 else
533 {
534 /* initialize cache */
535 for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache)(sizeof (keymap_x11->group_direction_cache) / sizeof ((keymap_x11
->group_direction_cache)[0]))
; i++)
536 {
537 cache[i].group_atom = 0;
538 cache[i].serial = keymap_x11->current_cache_serial;
539 }
540 keymap_x11->current_cache_serial++;
541 }
542
543 /* insert in cache */
544 if (!cache_hit)
545 {
546 gint oldest = 0;
547
548 direction = get_direction (xkb, group);
549
550 /* remove the oldest entry */
551 for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache)(sizeof (keymap_x11->group_direction_cache) / sizeof ((keymap_x11
->group_direction_cache)[0]))
; i++)
552 {
553 if (cache[i].serial < cache[oldest].serial)
554 oldest = i;
555 }
556
557 cache[oldest].group_atom = group_atom;
558 cache[oldest].direction = direction;
559 cache[oldest].serial = keymap_x11->current_cache_serial++;
560 }
561
562 return direction;
563}
564
565static int
566get_num_groups (CdkKeymap *keymap,
567 XkbDescPtr xkb)
568{
569 Display *display = KEYMAP_XDISPLAY (keymap)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->xdisplay)
;
570 XkbGetControls(display, XkbSlowKeysMask(1L << 1), xkb);
571 XkbGetUpdatedMap (display, XkbKeySymsMask(1<<1) | XkbKeyTypesMask(1<<0) |
572 XkbModifierMapMask(1<<2) | XkbVirtualModsMask(1<<6), xkb);
573 return xkb->ctrls->num_groups;
574}
575
576static gboolean
577update_direction (CdkX11Keymap *keymap_x11,
578 gint group)
579{
580 XkbDescPtr xkb = get_xkb (keymap_x11);
581 Atom group_atom;
582 gboolean had_direction;
583 PangoDirection old_direction;
584
585 had_direction = keymap_x11->have_direction;
586 old_direction = keymap_x11->current_direction;
587
588 group_atom = xkb->names->groups[group];
589
590 /* a group change? */
591 if (!keymap_x11->have_direction || keymap_x11->current_group_atom != group_atom)
592 {
593 keymap_x11->current_direction = get_direction_from_cache (keymap_x11, xkb, group);
594 keymap_x11->current_group_atom = group_atom;
595 keymap_x11->have_direction = TRUE(!(0));
596 }
597
598 return !had_direction || old_direction != keymap_x11->current_direction;
599}
600
601static gboolean
602update_lock_state (CdkX11Keymap *keymap_x11,
603 gint locked_mods,
604 gint effective_mods)
605{
606 XkbDescPtr xkb G_GNUC_UNUSED__attribute__ ((__unused__));
607 gboolean have_lock_state;
608 gboolean caps_lock_state;
609 gboolean num_lock_state;
610 gboolean scroll_lock_state;
611 guint modifier_state;
612
613 /* ensure keymap_x11->num_lock_mask is initialized */
614 xkb = get_xkb (keymap_x11);
615
616 have_lock_state = keymap_x11->have_lock_state;
617 caps_lock_state = keymap_x11->caps_lock_state;
618 num_lock_state = keymap_x11->num_lock_state;
619 scroll_lock_state = keymap_x11->scroll_lock_state;
620 modifier_state = keymap_x11->modifier_state;
621
622 keymap_x11->have_lock_state = TRUE(!(0));
623 keymap_x11->caps_lock_state = (locked_mods & CDK_LOCK_MASK) != 0;
624 keymap_x11->num_lock_state = (locked_mods & keymap_x11->num_lock_mask) != 0;
625 keymap_x11->scroll_lock_state = (locked_mods & keymap_x11->scroll_lock_mask) != 0;
626 /* FIXME: sanitize this */
627 keymap_x11->modifier_state = (guint)effective_mods;
628
629 return !have_lock_state
630 || (caps_lock_state != keymap_x11->caps_lock_state)
631 || (num_lock_state != keymap_x11->num_lock_state)
632 || (scroll_lock_state != keymap_x11->scroll_lock_state)
633 || (modifier_state != keymap_x11->modifier_state);
634}
635
636/* keep this in sync with the XkbSelectEventDetails()
637 * call in cdk_display_open()
638 */
639void
640_cdk_x11_keymap_state_changed (CdkDisplay *display,
641 XEvent *xevent)
642{
643 CdkX11Display *display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
644 XkbEvent *xkb_event = (XkbEvent *)xevent;
645
646 if (display_x11->keymap)
647 {
648 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (display_x11->keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display_x11->keymap)), ((cdk_x11_keymap_get_type())))
)))
;
649
650 if (update_direction (keymap_x11, XkbStateGroup (&xkb_event->state)((&xkb_event->state)->base_group+(&xkb_event->
state)->latched_group+((&xkb_event->state)->locked_group
))
))
651 g_signal_emit_by_name (keymap_x11, "direction-changed");
652
653 if (update_lock_state (keymap_x11,
654 xkb_event->state.locked_mods,
655 xkb_event->state.mods))
656 g_signal_emit_by_name (keymap_x11, "state-changed");
657 }
658}
659
660#endif /* HAVE_XKB */
661
662static void
663ensure_lock_state (CdkKeymap *keymap)
664{
665#ifdef HAVE_XKB1
666 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
667 {
668 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
669
670 if (!keymap_x11->have_lock_state)
671 {
672 CdkDisplay *display = keymap->display;
673 XkbStateRec state_rec;
674
675 XkbGetState (CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
, XkbUseCoreKbd0x0100, &state_rec);
676 update_lock_state (keymap_x11, state_rec.locked_mods, state_rec.mods);
677 }
678 }
679#endif /* HAVE_XKB */
680}
681
682void
683_cdk_x11_keymap_keys_changed (CdkDisplay *display)
684{
685 CdkX11Display *display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
686
687 ++display_x11->keymap_serial;
688
689 if (display_x11->keymap)
690 g_signal_emit_by_name (display_x11->keymap, "keys_changed", 0);
691}
692
693static PangoDirection
694cdk_x11_keymap_get_direction (CdkKeymap *keymap)
695{
696#ifdef HAVE_XKB1
697 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
698 {
699 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
700
701 if (!keymap_x11->have_direction)
702 {
703 CdkDisplay *display = keymap->display;
704 XkbStateRec state_rec;
705
706 XkbGetState (CDK_DISPLAY_XDISPLAY (display)(((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))->xdisplay
)
, XkbUseCoreKbd0x0100,
707 &state_rec);
708 update_direction (keymap_x11, XkbStateGroup (&state_rec)((&state_rec)->base_group+(&state_rec)->latched_group
+((&state_rec)->locked_group))
);
709 }
710
711 return keymap_x11->current_direction;
712 }
713 else
714#endif /* HAVE_XKB */
715 return PANGO_DIRECTION_NEUTRAL;
716}
717
718static gboolean
719cdk_x11_keymap_have_bidi_layouts (CdkKeymap *keymap)
720{
721#ifdef HAVE_XKB1
722 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
723 {
724 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
725 XkbDescPtr xkb = get_xkb (keymap_x11);
726 int num_groups = get_num_groups (keymap, xkb);
727
728 int i;
729 gboolean have_ltr_keyboard = FALSE(0);
730 gboolean have_rtl_keyboard = FALSE(0);
731
732 for (i = 0; i < num_groups; i++)
733 {
734 if (get_direction_from_cache (keymap_x11, xkb, i) == PANGO_DIRECTION_RTL)
735 have_rtl_keyboard = TRUE(!(0));
736 else
737 have_ltr_keyboard = TRUE(!(0));
738 }
739
740 return have_ltr_keyboard && have_rtl_keyboard;
741 }
742 else
743#endif /* HAVE_XKB */
744 return FALSE(0);
745}
746
747static gboolean
748cdk_x11_keymap_get_caps_lock_state (CdkKeymap *keymap)
749{
750 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
751
752 ensure_lock_state (keymap);
753
754 return keymap_x11->caps_lock_state;
755}
756
757static gboolean
758cdk_x11_keymap_get_num_lock_state (CdkKeymap *keymap)
759{
760 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
761
762 ensure_lock_state (keymap);
763
764 return keymap_x11->num_lock_state;
765}
766
767static gboolean
768cdk_x11_keymap_get_scroll_lock_state (CdkKeymap *keymap)
769{
770 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
771
772 ensure_lock_state (keymap);
773
774 return keymap_x11->scroll_lock_state;
775}
776
777static guint
778cdk_x11_keymap_get_modifier_state (CdkKeymap *keymap)
779{
780 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
781
782 ensure_lock_state (keymap);
783
784 return keymap_x11->modifier_state;
785}
786
787static gboolean
788cdk_x11_keymap_get_entries_for_keyval (CdkKeymap *keymap,
789 guint keyval,
790 CdkKeymapKey **keys,
791 gint *n_keys)
792{
793 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
794 GArray *retval;
795
796 retval = g_array_new (FALSE(0), FALSE(0), sizeof (CdkKeymapKey));
797
798#ifdef HAVE_XKB1
799 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
800 {
801 /* See sec 15.3.4 in XKB docs */
802
803 XkbDescRec *xkb = get_xkb (keymap_x11);
804 gint keycode;
805
806 keycode = keymap_x11->min_keycode;
807
808 while (keycode <= keymap_x11->max_keycode)
809 {
810 gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode)((((xkb)->map)->key_sym_map[keycode].width)); /* "key width" */
811 gint group = 0;
812 gint level = 0;
813 gint total_syms = XkbKeyNumSyms (xkb, keycode)(((((xkb)->map)->key_sym_map[(keycode)].width)*(((((xkb
)->map)->key_sym_map[(keycode)].group_info)&0x0f)))
)
;
814 gint i = 0;
815 KeySym *entry;
816
817 /* entry is an array with all syms for group 0, all
818 * syms for group 1, etc. and for each group the
819 * shift level syms are in order
820 */
821 entry = XkbKeySymsPtr (xkb, keycode)((&((xkb)->map)->syms[(((xkb)->map)->key_sym_map
[(keycode)].offset)]))
;
822
823 while (i < total_syms)
824 {
825 /* check out our cool loop invariant */
826 g_assert (i == (group * max_shift_levels + level))do { if (i == (group * max_shift_levels + level)) ; else g_assertion_message_expr
("Cdk", "cdkkeys-x11.c", 826, ((const char*) (__func__)), "i == (group * max_shift_levels + level)"
); } while (0)
;
827
828 if (entry[i] == keyval)
829 {
830 /* Found a match */
831 CdkKeymapKey key;
832
833 key.keycode = keycode;
834 key.group = group;
835 key.level = level;
836
837 g_array_append_val (retval, key)g_array_append_vals (retval, &(key), 1);
838
839 g_assert (XkbKeySymEntry (xkb, keycode, level, group) ==do { if (((((&((xkb)->map)->syms[(((xkb)->map)->
key_sym_map[(keycode)].offset)]))[((((((xkb)->map)->key_sym_map
[keycode].width))*(group))+(level))])) == keyval) ; else g_assertion_message_expr
("Cdk", "cdkkeys-x11.c", 840, ((const char*) (__func__)), "XkbKeySymEntry (xkb, keycode, level, group) == keyval"
); } while (0)
840 keyval)do { if (((((&((xkb)->map)->syms[(((xkb)->map)->
key_sym_map[(keycode)].offset)]))[((((((xkb)->map)->key_sym_map
[keycode].width))*(group))+(level))])) == keyval) ; else g_assertion_message_expr
("Cdk", "cdkkeys-x11.c", 840, ((const char*) (__func__)), "XkbKeySymEntry (xkb, keycode, level, group) == keyval"
); } while (0)
;
841 }
842
843 ++level;
844
845 if (level == max_shift_levels)
846 {
847 level = 0;
848 ++group;
849 }
850
851 ++i;
852 }
853
854 ++keycode;
855 }
856 }
857 else
858#endif
859 {
860 const KeySym *map = get_keymap (keymap_x11);
861 gint keycode;
862
863 keycode = keymap_x11->min_keycode;
864 while (keycode <= keymap_x11->max_keycode)
865 {
866 const KeySym *syms = map + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
867 gint i = 0;
868
869 while (i < keymap_x11->keysyms_per_keycode)
870 {
871 if (syms[i] == keyval)
872 {
873 /* found a match */
874 CdkKeymapKey key;
875
876 key.keycode = keycode;
877
878 /* The "classic" non-XKB keymap has 2 levels per group */
879 key.group = i / 2;
880 key.level = i % 2;
881
882 g_array_append_val (retval, key)g_array_append_vals (retval, &(key), 1);
883 }
884
885 ++i;
886 }
887
888 ++keycode;
889 }
890 }
891
892 if (retval->len > 0)
893 {
894 *keys = (CdkKeymapKey*) retval->data;
895 *n_keys = retval->len;
896 }
897 else
898 {
899 *keys = NULL((void*)0);
900 *n_keys = 0;
901 }
902
903 g_array_free (retval, retval->len > 0 ? FALSE(0) : TRUE(!(0)));
904
905 return *n_keys > 0;
906}
907
908static gboolean
909cdk_x11_keymap_get_entries_for_keycode (CdkKeymap *keymap,
910 guint hardware_keycode,
911 CdkKeymapKey **keys,
912 guint **keyvals,
913 gint *n_entries)
914{
915 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
916 GArray *key_array;
917 GArray *keyval_array;
918
919 update_keyrange (keymap_x11);
920
921 if (hardware_keycode < keymap_x11->min_keycode ||
1
Assuming 'hardware_keycode' is >= field 'min_keycode'
3
Taking false branch
922 hardware_keycode > keymap_x11->max_keycode)
2
Assuming 'hardware_keycode' is <= field 'max_keycode'
923 {
924 if (keys)
925 *keys = NULL((void*)0);
926 if (keyvals)
927 *keyvals = NULL((void*)0);
928
929 *n_entries = 0;
930 return FALSE(0);
931 }
932
933 if (keys)
4
Assuming 'keys' is non-null
5
Taking true branch
934 key_array = g_array_new (FALSE(0), FALSE(0), sizeof (CdkKeymapKey));
6
Value assigned to 'key_array'
935 else
936 key_array = NULL((void*)0);
937
938 if (keyvals)
7
Assuming 'keyvals' is null
8
Taking false branch
939 keyval_array = g_array_new (FALSE(0), FALSE(0), sizeof (guint));
940 else
941 keyval_array = NULL((void*)0);
942
943#ifdef HAVE_XKB1
944 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
9
Assuming field 'use_xkb' is 0
10
Taking false branch
945 {
946 /* See sec 15.3.4 in XKB docs */
947
948 XkbDescRec *xkb = get_xkb (keymap_x11);
949 gint max_shift_levels;
950 gint group = 0;
951 gint level = 0;
952 gint total_syms;
953 gint i = 0;
954 KeySym *entry;
955
956 max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode)((((xkb)->map)->key_sym_map[hardware_keycode].width)); /* "key width" */
957 total_syms = XkbKeyNumSyms (xkb, hardware_keycode)(((((xkb)->map)->key_sym_map[(hardware_keycode)].width)
*(((((xkb)->map)->key_sym_map[(hardware_keycode)].group_info
)&0x0f))))
;
958
959 /* entry is an array with all syms for group 0, all
960 * syms for group 1, etc. and for each group the
961 * shift level syms are in order
962 */
963 entry = XkbKeySymsPtr (xkb, hardware_keycode)((&((xkb)->map)->syms[(((xkb)->map)->key_sym_map
[(hardware_keycode)].offset)]))
;
964
965 while (i < total_syms)
966 {
967 /* check out our cool loop invariant */
968 g_assert (i == (group * max_shift_levels + level))do { if (i == (group * max_shift_levels + level)) ; else g_assertion_message_expr
("Cdk", "cdkkeys-x11.c", 968, ((const char*) (__func__)), "i == (group * max_shift_levels + level)"
); } while (0)
;
969
970 if (key_array)
971 {
972 CdkKeymapKey key;
973
974 key.keycode = hardware_keycode;
975 key.group = group;
976 key.level = level;
977
978 g_array_append_val (key_array, key)g_array_append_vals (key_array, &(key), 1);
979 }
980
981 if (keyval_array)
982 g_array_append_val (keyval_array, entry[i])g_array_append_vals (keyval_array, &(entry[i]), 1);
983
984 ++level;
985
986 if (level == max_shift_levels)
987 {
988 level = 0;
989 ++group;
990 }
991
992 ++i;
993 }
994 }
995 else
996#endif
997 {
998 const KeySym *map = get_keymap (keymap_x11);
999 const KeySym *syms;
1000 gint i = 0;
1001
1002 syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1003
1004 while (i < keymap_x11->keysyms_per_keycode)
11
Assuming 'i' is < field 'keysyms_per_keycode'
12
Loop condition is true. Entering loop body
16
Assuming 'i' is >= field 'keysyms_per_keycode'
17
Loop condition is false. Execution continues on line 1026
1005 {
1006 if (key_array)
13
Assuming 'key_array' is null
14
Taking false branch
1007 {
1008 CdkKeymapKey key;
1009
1010 key.keycode = hardware_keycode;
1011
1012 /* The "classic" non-XKB keymap has 2 levels per group */
1013 key.group = i / 2;
1014 key.level = i % 2;
1015
1016 g_array_append_val (key_array, key)g_array_append_vals (key_array, &(key), 1);
1017 }
1018
1019 if (keyval_array
14.1
'keyval_array' is null
)
15
Taking false branch
1020 g_array_append_val (keyval_array, syms[i])g_array_append_vals (keyval_array, &(syms[i]), 1);
1021
1022 ++i;
1023 }
1024 }
1025
1026 *n_entries = 0;
1027
1028 if (keys
17.1
'keys' is non-null
)
18
Taking true branch
1029 {
1030 *n_entries = key_array->len;
19
Access to field 'len' results in a dereference of a null pointer (loaded from variable 'key_array')
1031 *keys = (CdkKeymapKey*) g_array_free (key_array, FALSE(0));
1032 }
1033
1034 if (keyvals)
1035 {
1036 *n_entries = keyval_array->len;
1037 *keyvals = (guint*) g_array_free (keyval_array, FALSE(0));
1038 }
1039
1040 return *n_entries > 0;
1041}
1042
1043static guint
1044cdk_x11_keymap_lookup_key (CdkKeymap *keymap,
1045 const CdkKeymapKey *key)
1046{
1047 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
1048
1049 g_return_val_if_fail (key->group < 4, 0)do { if ((key->group < 4)) { } else { g_return_if_fail_warning
("Cdk", ((const char*) (__func__)), "key->group < 4");
return (0); } } while (0)
;
1050
1051#ifdef HAVE_XKB1
1052 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
1053 {
1054 XkbDescRec *xkb = get_xkb (keymap_x11);
1055
1056 return XkbKeySymEntry (xkb, key->keycode, key->level, key->group)((((&((xkb)->map)->syms[(((xkb)->map)->key_sym_map
[(key->keycode)].offset)]))[((((((xkb)->map)->key_sym_map
[key->keycode].width))*(key->group))+(key->level))])
)
;
1057 }
1058 else
1059#endif
1060 {
1061 const KeySym *map = get_keymap (keymap_x11);
1062 const KeySym *syms = map + (key->keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1063 return get_symbol (syms, keymap_x11, key->group, key->level);
1064 }
1065}
1066
1067#ifdef HAVE_XKB1
1068/* This is copied straight from XFree86 Xlib, to:
1069 * - add the group and level return.
1070 * - change the interpretation of mods_rtrn as described
1071 * in the docs for cdk_keymap_translate_keyboard_state()
1072 * It’s unchanged for ease of diff against the Xlib sources; don't
1073 * reformat it.
1074 */
1075static Boolint
1076MyEnhancedXkbTranslateKeyCode(register XkbDescPtr xkb,
1077 KeyCode key,
1078 register unsigned int mods,
1079 unsigned int * mods_rtrn,
1080 KeySym * keysym_rtrn,
1081 int * group_rtrn,
1082 int * level_rtrn)
1083{
1084 XkbKeyTypeRec *type;
1085 int col,nKeyGroups;
1086 unsigned preserve,effectiveGroup;
1087 KeySym *syms;
1088 int found_col = 0;
1089
1090 if (mods_rtrn!=NULL((void*)0))
1091 *mods_rtrn = 0;
1092
1093 nKeyGroups= XkbKeyNumGroups(xkb,key)((((((xkb)->map)->key_sym_map[(key)].group_info)&0x0f
)))
;
1094 if ((!XkbKeycodeInRange(xkb,key)(((key)>=(xkb)->min_key_code)&& ((key)<=(xkb
)->max_key_code))
)||(nKeyGroups==0)) {
1095 if (keysym_rtrn!=NULL((void*)0))
1096 *keysym_rtrn = NoSymbol0L;
1097 return False0;
1098 }
1099
1100 syms = XkbKeySymsPtr(xkb,key)((&((xkb)->map)->syms[(((xkb)->map)->key_sym_map
[(key)].offset)]))
;
1101
1102 /* find the offset of the effective group */
1103 col = 0;
1104 effectiveGroup= XkbGroupForCoreState(mods)(((mods)>>13)&0x3);
1105 if ( effectiveGroup>=nKeyGroups ) {
1106 unsigned groupInfo= XkbKeyGroupInfo(xkb,key)((((xkb)->map)->key_sym_map[(key)].group_info));
1107 switch (XkbOutOfRangeGroupAction(groupInfo)((groupInfo)&0xc0)) {
1108 default:
1109 effectiveGroup %= nKeyGroups;
1110 break;
1111 case XkbClampIntoRange(0x40):
1112 effectiveGroup = nKeyGroups-1;
1113 break;
1114 case XkbRedirectIntoRange(0x80):
1115 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo)(((groupInfo)&0x30)>>4);
1116 if (effectiveGroup>=nKeyGroups)
1117 effectiveGroup= 0;
1118 break;
1119 }
1120 }
1121 found_col = col= effectiveGroup*XkbKeyGroupsWidth(xkb,key)((((xkb)->map)->key_sym_map[key].width));
1122 type = XkbKeyKeyType(xkb,key,effectiveGroup)((&((xkb)->map)->types[(((xkb)->map)->key_sym_map
[key].kt_index[effectiveGroup&0x3])]))
;
1123
1124 preserve= 0;
1125 if (type->map) { /* find the column (shift level) within the group */
1126 register int i;
1127 register XkbKTMapEntryPtr entry;
1128 /* ---- Begin section modified for CDK ---- */
1129 int found = 0;
1130
1131 for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
1132 if (!entry->active || syms[col+entry->level] == syms[col])
1133 continue;
1134 if (mods_rtrn) {
1135 int bits = 0;
1136 unsigned long tmp = entry->mods.mask;
1137 while (tmp) {
1138 if ((tmp & 1) == 1)
1139 bits++;
1140 tmp >>= 1;
1141 }
1142 /* We always add one-modifiers levels to mods_rtrn since
1143 * they can't wipe out bits in the state unless the
1144 * level would be triggered. But not if they don't change
1145 * the symbol (otherwise we can't discriminate Shift-F10
1146 * and F10 anymore). And don't add modifiers that are
1147 * explicitly marked as preserved, either.
1148 */
1149 if (bits == 1 ||
1150 (mods&type->mods.mask) == entry->mods.mask)
1151 {
1152 if (type->preserve)
1153 *mods_rtrn |= (entry->mods.mask & ~type->preserve[i].mask);
1154 else
1155 *mods_rtrn |= entry->mods.mask;
1156 }
1157 }
1158
1159 if (!found && ((mods&type->mods.mask) == entry->mods.mask)) {
1160 found_col= col + entry->level;
1161 if (type->preserve)
1162 preserve= type->preserve[i].mask;
1163
1164 if (level_rtrn)
1165 *level_rtrn = entry->level;
1166
1167 found = 1;
1168 }
1169 }
1170 /* ---- End section modified for CDK ---- */
1171 }
1172
1173 if (keysym_rtrn!=NULL((void*)0))
1174 *keysym_rtrn= syms[found_col];
1175 if (mods_rtrn) {
1176 /* ---- Begin section modified for CDK ---- */
1177 *mods_rtrn &= ~preserve;
1178 /* ---- End section modified for CDK ---- */
1179
1180 /* ---- Begin stuff CDK comments out of the original Xlib version ---- */
1181 /* This is commented out because xkb_info is a private struct */
1182
1183#if 0
1184 /* The Motif VTS doesn't get the help callback called if help
1185 * is bound to Shift+<whatever>, and it appears as though it
1186 * is XkbTranslateKeyCode that is causing the problem. The
1187 * core X version of XTranslateKey always OR's in ShiftMask
1188 * and LockMask for mods_rtrn, so this "fix" keeps this behavior
1189 * and solves the VTS problem.
1190 */
1191 if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
1192 (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock(1<<2))) { *mods_rtrn|= (ShiftMask(1<<0)|LockMask(1<<1));
1193 }
1194#endif
1195
1196 /* ---- End stuff CDK comments out of the original Xlib version ---- */
1197 }
1198
1199 /* ---- Begin stuff CDK adds to the original Xlib version ---- */
1200
1201 if (group_rtrn)
1202 *group_rtrn = effectiveGroup;
1203
1204 /* ---- End stuff CDK adds to the original Xlib version ---- */
1205
1206 return (syms[found_col] != NoSymbol0L);
1207}
1208#endif /* HAVE_XKB */
1209
1210/* Translates from keycode/state to keysymbol using the traditional interpretation
1211 * of the keyboard map. See section 12.7 of the Xlib reference manual
1212 */
1213static guint
1214translate_keysym (CdkX11Keymap *keymap_x11,
1215 guint hardware_keycode,
1216 gint group,
1217 CdkModifierType state,
1218 gint *effective_group,
1219 gint *effective_level)
1220{
1221 const KeySym *map = get_keymap (keymap_x11);
1222 const KeySym *syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1223
1224#define SYM(k,g,l) get_symbol (syms, k,g,l)
1225
1226 CdkModifierType shift_modifiers;
1227 gint shift_level;
1228 guint tmp_keyval;
1229
1230 shift_modifiers = CDK_SHIFT_MASK;
1231 if (keymap_x11->lock_keysym == CDK_KEY_Shift_Lock0xffe6)
1232 shift_modifiers |= CDK_LOCK_MASK;
1233
1234 /* Fall back to the first group if the passed in group is empty
1235 */
1236 if (!(SYM (keymap_x11, group, 0) || SYM (keymap_x11, group, 1)) &&
1237 (SYM (keymap_x11, 0, 0) || SYM (keymap_x11, 0, 1)))
1238 group = 0;
1239
1240 if ((state & keymap_x11->num_lock_mask) &&
1241 KEYSYM_IS_KEYPAD (SYM (keymap_x11, group, 1))(((SYM (keymap_x11, group, 1)) >= 0xff80 && (SYM (
keymap_x11, group, 1)) <= 0xffbd) || ((SYM (keymap_x11, group
, 1)) >= 0x11000000 && (SYM (keymap_x11, group, 1)
) <= 0x1100ffff))
)
1242 {
1243 /* Shift, Shift_Lock cancel Num_Lock
1244 */
1245 shift_level = (state & shift_modifiers) ? 0 : 1;
1246 if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1247 shift_level = 0;
1248
1249 tmp_keyval = SYM (keymap_x11, group, shift_level);
1250 }
1251 else
1252 {
1253 /* Fall back to the first level if no symbol for the level
1254 * we were passed.
1255 */
1256 shift_level = (state & shift_modifiers) ? 1 : 0;
1257 if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1258 shift_level = 0;
1259
1260 tmp_keyval = SYM (keymap_x11, group, shift_level);
1261
1262 if (keymap_x11->lock_keysym == CDK_KEY_Caps_Lock0xffe5 && (state & CDK_LOCK_MASK) != 0)
1263 {
1264 guint upper = cdk_keyval_to_upper (tmp_keyval);
1265 if (upper != tmp_keyval)
1266 tmp_keyval = upper;
1267 }
1268 }
1269
1270 if (effective_group)
1271 *effective_group = group;
1272
1273 if (effective_level)
1274 *effective_level = shift_level;
1275
1276 return tmp_keyval;
1277
1278#undef SYM
1279}
1280
1281static gboolean
1282cdk_x11_keymap_translate_keyboard_state (CdkKeymap *keymap,
1283 guint hardware_keycode,
1284 CdkModifierType state,
1285 gint group,
1286 guint *keyval,
1287 gint *effective_group,
1288 gint *level,
1289 CdkModifierType *consumed_modifiers)
1290{
1291 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
1292 KeySym tmp_keyval = NoSymbol0L;
1293 guint tmp_modifiers;
1294
1295 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)
;
1296
1297 if (keyval)
1298 *keyval = NoSymbol0L;
1299 if (effective_group)
1300 *effective_group = 0;
1301 if (level)
1302 *level = 0;
1303 if (consumed_modifiers)
1304 *consumed_modifiers = 0;
1305
1306 update_keyrange (keymap_x11);
1307
1308 if (hardware_keycode < keymap_x11->min_keycode ||
1309 hardware_keycode > keymap_x11->max_keycode)
1310 return FALSE(0);
1311
1312#ifdef HAVE_XKB1
1313 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
1314 {
1315 XkbDescRec *xkb = get_xkb (keymap_x11);
1316
1317 /* replace bits 13 and 14 with the provided group */
1318 state &= ~(1 << 13 | 1 << 14);
1319 state |= group << 13;
1320
1321 MyEnhancedXkbTranslateKeyCode (xkb,
1322 hardware_keycode,
1323 state,
1324 &tmp_modifiers,
1325 &tmp_keyval,
1326 effective_group,
1327 level);
1328
1329 if (state & ~tmp_modifiers & LockMask(1<<1))
1330 tmp_keyval = cdk_keyval_to_upper (tmp_keyval);
1331
1332 /* We need to augment the consumed modifiers with LockMask, since
1333 * we handle that ourselves, and also with the group bits
1334 */
1335 tmp_modifiers |= LockMask(1<<1) | 1 << 13 | 1 << 14;
1336 }
1337 else
1338#endif
1339 {
1340 CdkModifierType bit;
1341
1342 tmp_modifiers = 0;
1343
1344 /* We see what modifiers matter by trying the translation with
1345 * and without each possible modifier
1346 */
1347 for (bit = CDK_SHIFT_MASK; bit < CDK_BUTTON1_MASK; bit <<= 1)
1348 {
1349 /* Handling of the group here is a bit funky; a traditional
1350 * X keyboard map can have more than two groups, but no way
1351 * of accessing the extra groups is defined. We allow a
1352 * caller to pass in any group to this function, but we
1353 * only can represent switching between group 0 and 1 in
1354 * consumed modifiers.
1355 */
1356 if (translate_keysym (keymap_x11, hardware_keycode,
1357 (bit == keymap_x11->group_switch_mask) ? 0 : group,
1358 state & ~bit,
1359 NULL((void*)0), NULL((void*)0)) !=
1360 translate_keysym (keymap_x11, hardware_keycode,
1361 (bit == keymap_x11->group_switch_mask) ? 1 : group,
1362 state | bit,
1363 NULL((void*)0), NULL((void*)0)))
1364 tmp_modifiers |= bit;
1365 }
1366
1367 tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
1368 group, state,
1369 level, effective_group);
1370 }
1371
1372 if (consumed_modifiers)
1373 *consumed_modifiers = tmp_modifiers;
1374
1375 if (keyval)
1376 *keyval = tmp_keyval;
1377
1378 return tmp_keyval != NoSymbol0L;
1379}
1380
1381/**
1382 * cdk_x11_keymap_get_group_for_state:
1383 * @keymap: (type CdkX11Keymap): a #CdkX11Keymap
1384 * @state: raw state returned from X
1385 *
1386 * Extracts the group from the state field sent in an X Key event.
1387 * This is only needed for code processing raw X events, since #CdkEventKey
1388 * directly includes an is_modifier field.
1389 *
1390 * Returns: the index of the active keyboard group for the event
1391 *
1392 * Since: 3.6
1393 */
1394gint
1395cdk_x11_keymap_get_group_for_state (CdkKeymap *keymap,
1396 guint state)
1397{
1398 CdkDisplay *display;
1399 CdkX11Display *display_x11;
1400
1401 g_return_val_if_fail (CDK_IS_X11_KEYMAP (keymap), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((keymap)); GType __t = ((cdk_x11_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__
)), "CDK_IS_X11_KEYMAP (keymap)"); return (0); } } while (0)
;
1402
1403 display = keymap->display;
1404 display_x11 = CDK_X11_DISPLAY (display)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((display)), ((cdk_x11_display_get_type()))))))
;
1405
1406#ifdef HAVE_XKB1
1407 if (display_x11->use_xkb)
1408 {
1409 return XkbGroupForCoreState (state)(((state)>>13)&0x3);
1410 }
1411 else
1412#endif
1413 {
1414 CdkX11Keymap *keymap_impl = CDK_X11_KEYMAP (cdk_keymap_get_for_display (display))((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cdk_keymap_get_for_display (display))), ((cdk_x11_keymap_get_type
()))))))
;
1415 update_keymaps (keymap_impl);
1416 return (state & keymap_impl->group_switch_mask) ? 1 : 0;
1417 }
1418}
1419
1420void
1421_cdk_x11_keymap_add_virt_mods (CdkKeymap *keymap,
1422 CdkModifierType *modifiers)
1423{
1424 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
1425 int i;
1426
1427 /* See comment in add_virtual_modifiers() */
1428 for (i = 4; i < 8; i++)
1429 {
1430 if ((1 << i) & *modifiers)
1431 {
1432 if (keymap_x11->modmap[i] & CDK_SUPER_MASK)
1433 *modifiers |= CDK_SUPER_MASK;
1434 else if (keymap_x11->modmap[i] & CDK_HYPER_MASK)
1435 *modifiers |= CDK_HYPER_MASK;
1436 else if (keymap_x11->modmap[i] & CDK_META_MASK)
1437 *modifiers |= CDK_META_MASK;
1438 }
1439 }
1440}
1441
1442static void
1443cdk_x11_keymap_add_virtual_modifiers (CdkKeymap *keymap,
1444 CdkModifierType *state)
1445{
1446 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
1447 int i;
1448
1449 /* This loop used to start at 3, which included MOD1 in the
1450 * virtual mapping. However, all of CTK+ treats MOD1 as a
1451 * synonym for Alt, and does not expect it to be mapped around,
1452 * therefore it's more sane to simply treat MOD1 like SHIFT and
1453 * CONTROL, which are not mappable either.
1454 */
1455 for (i = 4; i < 8; i++)
1456 {
1457 if ((1 << i) & *state)
1458 {
1459 if (keymap_x11->modmap[i] & CDK_SUPER_MASK)
1460 *state |= CDK_SUPER_MASK;
1461 if (keymap_x11->modmap[i] & CDK_HYPER_MASK)
1462 *state |= CDK_HYPER_MASK;
1463 if (keymap_x11->modmap[i] & CDK_META_MASK)
1464 *state |= CDK_META_MASK;
1465 }
1466 }
1467}
1468
1469/**
1470 * cdk_x11_keymap_key_is_modifier:
1471 * @keymap: (type CdkX11Keymap): a #CdkX11Keymap
1472 * @keycode: the hardware keycode from a key event
1473 *
1474 * Determines whether a particular key code represents a key that
1475 * is a modifier. That is, it’s a key that normally just affects
1476 * the keyboard state and the behavior of other keys rather than
1477 * producing a direct effect itself. This is only needed for code
1478 * processing raw X events, since #CdkEventKey directly includes
1479 * an is_modifier field.
1480 *
1481 * Returns: %TRUE if the hardware keycode is a modifier key
1482 *
1483 * Since: 3.6
1484 */
1485gboolean
1486cdk_x11_keymap_key_is_modifier (CdkKeymap *keymap,
1487 guint keycode)
1488{
1489 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
1490 gint i;
1491
1492 g_return_val_if_fail (CDK_IS_X11_KEYMAP (keymap), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((keymap)); GType __t = ((cdk_x11_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__
)), "CDK_IS_X11_KEYMAP (keymap)"); return ((0)); } } while (0
)
;
1493
1494 update_keyrange (keymap_x11);
1495 if (keycode < keymap_x11->min_keycode ||
1496 keycode > keymap_x11->max_keycode)
1497 return FALSE(0);
1498
1499#ifdef HAVE_XKB1
1500 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
1501 {
1502 XkbDescRec *xkb = get_xkb (keymap_x11);
1503
1504 if (xkb->map->modmap && xkb->map->modmap[keycode] != 0)
1505 return TRUE(!(0));
1506 }
1507 else
1508#endif
1509 {
1510 for (i = 0; i < 8 * keymap_x11->mod_keymap->max_keypermod; i++)
1511 {
1512 if (keycode == keymap_x11->mod_keymap->modifiermap[i])
1513 return TRUE(!(0));
1514 }
1515 }
1516
1517 return FALSE(0);
1518}
1519
1520static gboolean
1521cdk_x11_keymap_map_virtual_modifiers (CdkKeymap *keymap,
1522 CdkModifierType *state)
1523{
1524 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
1525 const guint vmods[] = { CDK_SUPER_MASK, CDK_HYPER_MASK, CDK_META_MASK };
1526 int i, j;
1527 gboolean retval;
1528
1529#ifdef HAVE_XKB1
1530 if (KEYMAP_USE_XKB (keymap)((((CdkX11Display*) (void *) g_type_check_instance_cast ((GTypeInstance
*) (((keymap)->display)), ((cdk_x11_display_get_type()))))
))->use_xkb
)
1531 get_xkb (keymap_x11);
1532#endif
1533
1534 retval = TRUE(!(0));
1535
1536 for (j = 0; j < 3; j++)
1537 {
1538 if (*state & vmods[j])
1539 {
1540 /* See comment in add_virtual_modifiers() */
1541 for (i = 4; i < 8; i++)
1542 {
1543 if (keymap_x11->modmap[i] & vmods[j])
1544 {
1545 if (*state & (1 << i))
1546 retval = FALSE(0);
1547 else
1548 *state |= 1 << i;
1549 }
1550 }
1551 }
1552 }
1553
1554 return retval;
1555}
1556
1557static CdkModifierType
1558cdk_x11_keymap_get_modifier_mask (CdkKeymap *keymap,
1559 CdkModifierIntent intent)
1560{
1561 CdkX11Keymap *keymap_x11 = CDK_X11_KEYMAP (keymap)((((CdkX11Keymap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((keymap)), ((cdk_x11_keymap_get_type()))))))
;
1562
1563 switch (intent)
1564 {
1565 case CDK_MODIFIER_INTENT_SHIFT_GROUP:
1566 return keymap_x11->group_switch_mask;
1567
1568 default:
1569 return CDK_KEYMAP_CLASS (cdk_x11_keymap_parent_class)((((CdkKeymapClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((cdk_x11_keymap_parent_class)), ((cdk_keymap_get_type ())
)))))
->get_modifier_mask (keymap,
1570 intent);
1571 }
1572}
1573
1574static void
1575cdk_x11_keymap_class_init (CdkX11KeymapClass *klass)
1576{
1577 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
1578 CdkKeymapClass *keymap_class = CDK_KEYMAP_CLASS (klass)((((CdkKeymapClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((cdk_keymap_get_type ()))))))
;
1579
1580 object_class->finalize = cdk_x11_keymap_finalize;
1581
1582 keymap_class->get_direction = cdk_x11_keymap_get_direction;
1583 keymap_class->have_bidi_layouts = cdk_x11_keymap_have_bidi_layouts;
1584 keymap_class->get_caps_lock_state = cdk_x11_keymap_get_caps_lock_state;
1585 keymap_class->get_num_lock_state = cdk_x11_keymap_get_num_lock_state;
1586 keymap_class->get_scroll_lock_state = cdk_x11_keymap_get_scroll_lock_state;
1587 keymap_class->get_modifier_state = cdk_x11_keymap_get_modifier_state;
1588 keymap_class->get_entries_for_keyval = cdk_x11_keymap_get_entries_for_keyval;
1589 keymap_class->get_entries_for_keycode = cdk_x11_keymap_get_entries_for_keycode;
1590 keymap_class->lookup_key = cdk_x11_keymap_lookup_key;
1591 keymap_class->translate_keyboard_state = cdk_x11_keymap_translate_keyboard_state;
1592 keymap_class->add_virtual_modifiers = cdk_x11_keymap_add_virtual_modifiers;
1593 keymap_class->map_virtual_modifiers = cdk_x11_keymap_map_virtual_modifiers;
1594 keymap_class->get_modifier_mask = cdk_x11_keymap_get_modifier_mask;
1595}