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