summaryrefslogtreecommitdiff
path: root/src/lib/elput
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2017-05-26 16:34:10 -0400
committerMike Blumenkrantz <zmike@osg.samsung.com>2017-05-26 16:27:42 -0400
commite8fe0bcc47ff44a5afaf8442407248887f716b89 (patch)
tree4fd7e06b862670ab7f87b2aa313f763e77b99cfc /src/lib/elput
parent6ddcd48fdeb57fc5b237825df709a2e3746e845e (diff)
elput/drm: redo xkb context/keymap setting
context and keymap need to be set at the same time in order to effectively update keyboard state, and active group should be accessible through api as well preserve old function ABI to ensure old binaries don't crash
Diffstat (limited to 'src/lib/elput')
-rw-r--r--src/lib/elput/Elput.h16
-rw-r--r--src/lib/elput/elput_evdev.c120
-rw-r--r--src/lib/elput/elput_input.c26
-rw-r--r--src/lib/elput/elput_logind.c2
-rw-r--r--src/lib/elput/elput_private.h8
5 files changed, 123 insertions, 49 deletions
diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h
index 378912eb90..f9e950c821 100644
--- a/src/lib/elput/Elput.h
+++ b/src/lib/elput/Elput.h
@@ -395,26 +395,28 @@ EAPI Eina_Bool elput_input_key_remap_enable(Elput_Manager *manager, Eina_Bool en
395EAPI Eina_Bool elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys, int num); 395EAPI Eina_Bool elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys, int num);
396 396
397/** 397/**
398 * Set a cached context to be used for keyboards 398 * Set info to be used for keyboards
399 * 399 *
400 * @param manager 400 * @param manager
401 * @param context 401 * @param context
402 * @param keymap
403 * @param group
402 * 404 *
403 * @ingroup Elput_Input_Group 405 * @ingroup Elput_Input_Group
404 * @since 1.18 406 * @since 1.20
405 */ 407 */
406EAPI void elput_input_keyboard_cached_context_set(Elput_Manager *manager, void *context); 408EAPI void elput_input_keyboard_info_set(Elput_Manager *manager, void *context, void *keymap, int group);
407 409
408/** 410/**
409 * Set a cached keymap to be used for keyboards 411 * Set group layout to be used for keyboards
410 * 412 *
411 * @param manager 413 * @param manager
412 * @param keymap 414 * @param group
413 * 415 *
414 * @ingroup Elput_Input_Group 416 * @ingroup Elput_Input_Group
415 * @since 1.18 417 * @since 1.20
416 */ 418 */
417EAPI void elput_input_keyboard_cached_keymap_set(Elput_Manager *manager, void *keymap); 419EAPI void elput_input_keyboard_group_set(Elput_Manager *manager, int group);
418 420
419/** 421/**
420 * Return the output name associated with a given device 422 * Return the output name associated with a given device
diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c
index 3c6243bc1a..46f8068f79 100644
--- a/src/lib/elput/elput_evdev.c
+++ b/src/lib/elput/elput_evdev.c
@@ -89,7 +89,7 @@ _keyboard_fd_get(off_t size)
89} 89}
90 90
91static Elput_Keyboard_Info * 91static Elput_Keyboard_Info *
92_keyboard_info_create(struct xkb_keymap *keymap, Eina_Bool external) 92_keyboard_info_create(struct xkb_keymap *keymap)
93{ 93{
94 Elput_Keyboard_Info *info; 94 Elput_Keyboard_Info *info;
95 char *str; 95 char *str;
@@ -113,9 +113,6 @@ _keyboard_info_create(struct xkb_keymap *keymap, Eina_Bool external)
113 info->mods.altgr = 113 info->mods.altgr =
114 1 << xkb_keymap_mod_get_index(info->keymap.map, "ISO_Level3_Shift"); 114 1 << xkb_keymap_mod_get_index(info->keymap.map, "ISO_Level3_Shift");
115 115
116 /* if we are using an external keymap then we do not need go further */
117 if (external) return info;
118
119 str = xkb_keymap_get_as_string(info->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1); 116 str = xkb_keymap_get_as_string(info->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
120 if (!str) goto err; 117 if (!str) goto err;
121 118
@@ -145,17 +142,14 @@ err:
145} 142}
146 143
147static void 144static void
148_keyboard_info_destroy(Elput_Keyboard_Info *info, Eina_Bool external) 145_keyboard_info_destroy(Elput_Keyboard_Info *info)
149{ 146{
150 if (--info->refs > 0) return; 147 if (--info->refs > 0) return;
151 148
152 xkb_keymap_unref(info->keymap.map); 149 xkb_keymap_unref(info->keymap.map);
153 150
154 if (!external) 151 if (info->keymap.area) munmap(info->keymap.area, info->keymap.size);
155 { 152 if (info->keymap.fd >= 0) close(info->keymap.fd);
156 if (info->keymap.area) munmap(info->keymap.area, info->keymap.size);
157 if (info->keymap.fd >= 0) close(info->keymap.fd);
158 }
159 153
160 free(info); 154 free(info);
161} 155}
@@ -175,7 +169,7 @@ _keyboard_global_build(Elput_Keyboard *kbd)
175 keymap = xkb_keymap_new_from_names(kbd->context, &kbd->names, 0); 169 keymap = xkb_keymap_new_from_names(kbd->context, &kbd->names, 0);
176 if (!keymap) return EINA_FALSE; 170 if (!keymap) return EINA_FALSE;
177 171
178 kbd->info = _keyboard_info_create(keymap, EINA_FALSE); 172 kbd->info = _keyboard_info_create(keymap);
179 xkb_keymap_unref(keymap); 173 xkb_keymap_unref(keymap);
180 174
181 if (!kbd->info) return EINA_FALSE; 175 if (!kbd->info) return EINA_FALSE;
@@ -231,7 +225,9 @@ _keyboard_init(Elput_Seat *seat, struct xkb_keymap *keymap)
231 225
232 if (keymap) 226 if (keymap)
233 { 227 {
234 kbd->info = _keyboard_info_create(keymap, EINA_TRUE); 228 if (seat->manager->cached.keymap == keymap)
229 kbd->context = xkb_context_ref(seat->manager->cached.context);
230 kbd->info = _keyboard_info_create(keymap);
235 if (!kbd->info) goto err; 231 if (!kbd->info) goto err;
236 } 232 }
237 else 233 else
@@ -254,7 +250,7 @@ _keyboard_init(Elput_Seat *seat, struct xkb_keymap *keymap)
254 return EINA_TRUE; 250 return EINA_TRUE;
255 251
256err: 252err:
257 if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map); 253 if (kbd->info) _keyboard_info_destroy(kbd->info);
258 free(kbd); 254 free(kbd);
259 return EINA_FALSE; 255 return EINA_FALSE;
260} 256}
@@ -346,39 +342,91 @@ _keyboard_modifiers_send(Elput_Keyboard *kbd)
346 ecore_event_add(ELPUT_EVENT_MODIFIERS_SEND, ev, NULL, NULL); 342 ecore_event_add(ELPUT_EVENT_MODIFIERS_SEND, ev, NULL, NULL);
347} 343}
348 344
349static void 345static Eina_Bool
346_keyboard_state_update(Elput_Keyboard *kbd, struct xkb_keymap *map, xkb_mod_mask_t *latched, xkb_mod_mask_t *locked)
347{
348 struct xkb_state *state, *maskless_state;
349
350 state = xkb_state_new(map);
351 if (!state) return EINA_FALSE;
352 maskless_state = xkb_state_new(map);
353 if (!maskless_state)
354 {
355 xkb_state_unref(state);
356 return EINA_FALSE;
357 }
358
359 *latched = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LATCHED);
360 *locked = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LOCKED);
361 xkb_state_update_mask(state, 0, *latched, *locked, kbd->seat->manager->cached.group, 0, 0);
362
363 xkb_state_unref(kbd->state);
364 kbd->state = state;
365 xkb_state_unref(kbd->maskless_state);
366 kbd->maskless_state = maskless_state;
367 return EINA_TRUE;
368}
369
370void
350_keyboard_keymap_update(Elput_Seat *seat) 371_keyboard_keymap_update(Elput_Seat *seat)
351{ 372{
352 Elput_Keyboard *kbd; 373 Elput_Keyboard *kbd;
353 Elput_Keyboard_Info *info; 374 Elput_Keyboard_Info *info = NULL;
354 struct xkb_state *state;
355 xkb_mod_mask_t latched, locked; 375 xkb_mod_mask_t latched, locked;
376 Eina_Bool state = EINA_TRUE;
356 377
357 kbd = _evdev_keyboard_get(seat); 378 kbd = _evdev_keyboard_get(seat);
358 if (!kbd) return; 379 if (!kbd) return;
380 kbd->pending_keymap = 1;
381 if (kbd->key_count) return;
359 382
360 info = _keyboard_info_create(kbd->pending_map, kbd->external_map); 383 if (kbd->seat->manager->cached.keymap)
361 xkb_keymap_unref(kbd->pending_map); 384 {
362 kbd->pending_map = NULL; 385 if (kbd->context) xkb_context_unref(kbd->context);
363 386 kbd->context = xkb_context_ref(kbd->seat->manager->cached.context);
364 if (!info) return; 387 info = _keyboard_info_create(kbd->seat->manager->cached.keymap);
365 388 if (!info) return;
366 state = xkb_state_new(info->keymap.map); 389 state = _keyboard_state_update(kbd, info->keymap.map, &latched, &locked);
390 }
391 else if (!_keyboard_global_build(kbd)) return;
392 else
393 state = _keyboard_state_update(kbd, kbd->info->keymap.map, &latched, &locked);
394 kbd->pending_keymap = 0;
367 if (!state) 395 if (!state)
368 { 396 {
369 _keyboard_info_destroy(info, kbd->external_map); 397 if (info) _keyboard_info_destroy(info);
370 return; 398 return;
371 } 399 }
372 400
373 latched = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LATCHED); 401 if (info)
374 locked = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LOCKED); 402 {
375 xkb_state_update_mask(state, 0, latched, locked, 0, 0, 0); 403 _keyboard_info_destroy(kbd->info);
404 kbd->info = info;
405 }
376 406
377 _keyboard_info_destroy(kbd->info, kbd->external_map); 407 _keyboard_compose_init(kbd);
378 kbd->info = info;
379 408
380 xkb_state_unref(kbd->state); 409 _keyboard_modifiers_update(kbd, seat);
381 kbd->state = state; 410 _keyboard_keymap_send(kbd->info);
411
412 if ((!latched) && (!locked)) return;
413
414 _keyboard_modifiers_send(kbd);
415}
416
417void
418_keyboard_group_update(Elput_Seat *seat)
419{
420 Elput_Keyboard *kbd;
421 xkb_mod_mask_t latched, locked;
422 Eina_Bool state;
423
424 kbd = _evdev_keyboard_get(seat);
425 if (!kbd) return;
426
427 state = _keyboard_state_update(kbd, kbd->info->keymap.map, &latched, &locked);
428 if (!state) return;
429 _keyboard_compose_init(kbd);
382 430
383 _keyboard_modifiers_update(kbd, seat); 431 _keyboard_modifiers_update(kbd, seat);
384 _keyboard_keymap_send(kbd->info); 432 _keyboard_keymap_send(kbd->info);
@@ -568,7 +616,7 @@ _keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *e
568 if (!kbd) return; 616 if (!kbd) return;
569 617
570 state = libinput_event_keyboard_get_key_state(event); 618 state = libinput_event_keyboard_get_key_state(event);
571 count = libinput_event_keyboard_get_seat_key_count(event); 619 kbd->key_count = count = libinput_event_keyboard_get_seat_key_count(event);
572 620
573 /* Ignore key events that are not seat wide state changes. */ 621 /* Ignore key events that are not seat wide state changes. */
574 if (((state == LIBINPUT_KEY_STATE_PRESSED) && (count != 1)) || 622 if (((state == LIBINPUT_KEY_STATE_PRESSED) && (count != 1)) ||
@@ -610,7 +658,7 @@ _keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *e
610 _keyboard_keysym_translate(sym, dev->seat->modifiers, compose, sizeof(compose)); 658 _keyboard_keysym_translate(sym, dev->seat->modifiers, compose, sizeof(compose));
611 _keyboard_key_send(dev, state, keyname, key, compose, code, timestamp); 659 _keyboard_key_send(dev, state, keyname, key, compose, code, timestamp);
612 660
613 if ((kbd->pending_map) && (count == 0)) 661 if ((kbd->pending_keymap) && (count == 0))
614 _keyboard_keymap_update(dev->seat); 662 _keyboard_keymap_update(dev->seat);
615 663
616 if (state == LIBINPUT_KEY_STATE_PRESSED) 664 if (state == LIBINPUT_KEY_STATE_PRESSED)
@@ -1588,12 +1636,14 @@ _evdev_keyboard_destroy(Elput_Keyboard *kbd)
1588 free((char *)kbd->names.variant); 1636 free((char *)kbd->names.variant);
1589 free((char *)kbd->names.options); 1637 free((char *)kbd->names.options);
1590 1638
1639 if (kbd->compose_table) xkb_compose_table_unref(kbd->compose_table);
1640 if (kbd->compose_state) xkb_compose_state_unref(kbd->compose_state);
1641
1591 if (kbd->state) xkb_state_unref(kbd->state); 1642 if (kbd->state) xkb_state_unref(kbd->state);
1592 if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map);
1593 if (kbd->maskless_state) xkb_state_unref(kbd->maskless_state); 1643 if (kbd->maskless_state) xkb_state_unref(kbd->maskless_state);
1644 if (kbd->info) _keyboard_info_destroy(kbd->info);
1594 1645
1595 xkb_context_unref(kbd->context); 1646 xkb_context_unref(kbd->context);
1596 xkb_keymap_unref(kbd->pending_map);
1597 1647
1598 free(kbd); 1648 free(kbd);
1599} 1649}
diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c
index f46f26d246..a5afe74fd9 100644
--- a/src/lib/elput/elput_input.c
+++ b/src/lib/elput/elput_input.c
@@ -654,21 +654,37 @@ elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys,
654} 654}
655 655
656EAPI void 656EAPI void
657elput_input_keyboard_cached_context_set(Elput_Manager *manager, void *context) 657elput_input_keyboard_info_set(Elput_Manager *manager, void *context, void *keymap, int group)
658{ 658{
659 Eina_List *l;
660 Elput_Seat *seat;
661
659 EINA_SAFETY_ON_NULL_RETURN(manager); 662 EINA_SAFETY_ON_NULL_RETURN(manager);
663 EINA_SAFETY_ON_FALSE_RETURN((!!context) == (!!keymap));
660 664
661 if ((context) && (manager->cached.context == context)) return; 665 if ((manager->cached.context == context) && (manager->cached.keymap == keymap)) return;
666 if (context) xkb_context_ref(context);
667 if (keymap) xkb_keymap_ref(keymap);
668 if (manager->cached.context) xkb_context_unref(manager->cached.context);
669 if (manager->cached.keymap) xkb_keymap_unref(manager->cached.keymap);
662 manager->cached.context = context; 670 manager->cached.context = context;
671 manager->cached.keymap = keymap;
672 manager->cached.group = group;
673 EINA_LIST_FOREACH(manager->input.seats, l, seat)
674 _keyboard_keymap_update(seat);
663} 675}
664 676
665EAPI void 677EAPI void
666elput_input_keyboard_cached_keymap_set(Elput_Manager *manager, void *keymap) 678elput_input_keyboard_group_set(Elput_Manager *manager, int group)
667{ 679{
680 Eina_List *l;
681 Elput_Seat *seat;
668 EINA_SAFETY_ON_NULL_RETURN(manager); 682 EINA_SAFETY_ON_NULL_RETURN(manager);
669 683
670 if ((keymap) && (manager->cached.keymap == keymap)) return; 684 if (manager->cached.group == group) return;
671 manager->cached.keymap = keymap; 685 manager->cached.group = group;
686 EINA_LIST_FOREACH(manager->input.seats, l, seat)
687 _keyboard_group_update(seat);
672} 688}
673 689
674EAPI Eina_Stringshare * 690EAPI Eina_Stringshare *
diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c
index 25034480d2..cfce90e3aa 100644
--- a/src/lib/elput/elput_logind.c
+++ b/src/lib/elput/elput_logind.c
@@ -527,6 +527,8 @@ _logind_disconnect(Elput_Manager *em)
527 _logind_dbus_close(em->dbus.conn); 527 _logind_dbus_close(em->dbus.conn);
528 eina_stringshare_del(em->seat); 528 eina_stringshare_del(em->seat);
529 free(em->sid); 529 free(em->sid);
530 if (em->cached.context) xkb_context_unref(em->cached.context);
531 if (em->cached.keymap) xkb_keymap_unref(em->cached.keymap);
530 free(em); 532 free(em);
531} 533}
532 534
diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h
index c6e3c81d83..4c7881e0ef 100644
--- a/src/lib/elput/elput_private.h
+++ b/src/lib/elput/elput_private.h
@@ -135,9 +135,9 @@ struct _Elput_Keyboard
135 } grab; 135 } grab;
136 136
137 Elput_Keyboard_Info *info; 137 Elput_Keyboard_Info *info;
138 unsigned int key_count;
138 139
139 struct xkb_state *state; 140 struct xkb_state *state;
140 struct xkb_keymap *pending_map;
141 struct xkb_state *maskless_state; 141 struct xkb_state *maskless_state;
142 struct xkb_context *context; 142 struct xkb_context *context;
143 struct xkb_rule_names names; 143 struct xkb_rule_names names;
@@ -146,7 +146,7 @@ struct _Elput_Keyboard
146 146
147 Elput_Seat *seat; 147 Elput_Seat *seat;
148 148
149 Eina_Bool external_map : 1; 149 Eina_Bool pending_keymap : 1;
150}; 150};
151 151
152struct _Elput_Pointer 152struct _Elput_Pointer
@@ -261,6 +261,7 @@ struct _Elput_Manager
261 { 261 {
262 struct xkb_keymap *keymap; 262 struct xkb_keymap *keymap;
263 struct xkb_context *context; 263 struct xkb_context *context;
264 int group;
264 } cached; 265 } cached;
265 266
266 Elput_Input input; 267 Elput_Input input;
@@ -292,4 +293,7 @@ Elput_Touch *_evdev_touch_get(Elput_Seat *seat);
292 293
293extern Elput_Interface _logind_interface; 294extern Elput_Interface _logind_interface;
294 295
296void _keyboard_keymap_update(Elput_Seat *seat);
297void _keyboard_group_update(Elput_Seat *seat);
298
295#endif 299#endif