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