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
This commit is contained in:
Mike Blumenkrantz 2017-05-26 16:34:10 -04:00
parent 6ddcd48fde
commit e8fe0bcc47
7 changed files with 148 additions and 68 deletions

View File

@ -285,26 +285,28 @@ EAPI void ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int w
EAPI void ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h);
/**
* Set a cached context to be used on keyboards
* Set info to be used on keyboards
*
* @param device
* @param context
* @param keymap
* @param group
*
* @ingroup Ecore_Drm2_Device_Group
* @since 1.18
* @since 1.20
*/
EAPI void ecore_drm2_device_keyboard_cached_context_set(Ecore_Drm2_Device *device, void *context);
EAPI void ecore_drm2_device_keyboard_info_set(Ecore_Drm2_Device *device, void *context, void *keymap, int group);
/**
* Set a cached keymap to be used on keyboards
* Set a group layout to be used on keyboards
*
* @param device
* @param keymap
* @param group
*
* @ingroup Ecore_Drm2_Device_Group
* @since 1.18
* @since 1.20
*/
EAPI void ecore_drm2_device_keyboard_cached_keymap_set(Ecore_Drm2_Device *device, void *keymap);
EAPI void ecore_drm2_device_keyboard_group_set(Ecore_Drm2_Device *device, int group);
/**
* Get the crtcs of a given device

View File

@ -777,19 +777,19 @@ ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h)
}
EAPI void
ecore_drm2_device_keyboard_cached_context_set(Ecore_Drm2_Device *device, void *context)
ecore_drm2_device_keyboard_info_set(Ecore_Drm2_Device *device, void *context, void *keymap, int group)
{
EINA_SAFETY_ON_NULL_RETURN(device);
elput_input_keyboard_cached_context_set(device->em, context);
elput_input_keyboard_info_set(device->em, context, keymap, group);
}
EAPI void
ecore_drm2_device_keyboard_cached_keymap_set(Ecore_Drm2_Device *device, void *keymap)
ecore_drm2_device_keyboard_group_set(Ecore_Drm2_Device *device, int group)
{
EINA_SAFETY_ON_NULL_RETURN(device);
elput_input_keyboard_cached_keymap_set(device->em, keymap);
elput_input_keyboard_group_set(device->em, group);
}
EAPI unsigned int *
@ -848,3 +848,7 @@ ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device *device)
else
return EINA_FALSE;
}
/* prevent crashing with old apps compiled against these functions */
EAPI void ecore_drm2_device_keyboard_cached_context_set(){};
EAPI void ecore_drm2_device_keyboard_cached_keymap_set(){};

View File

@ -395,26 +395,28 @@ EAPI Eina_Bool elput_input_key_remap_enable(Elput_Manager *manager, Eina_Bool en
EAPI Eina_Bool elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys, int num);
/**
* Set a cached context to be used for keyboards
* Set info to be used for keyboards
*
* @param manager
* @param context
* @param keymap
* @param group
*
* @ingroup Elput_Input_Group
* @since 1.18
* @since 1.20
*/
EAPI void elput_input_keyboard_cached_context_set(Elput_Manager *manager, void *context);
EAPI void elput_input_keyboard_info_set(Elput_Manager *manager, void *context, void *keymap, int group);
/**
* Set a cached keymap to be used for keyboards
* Set group layout to be used for keyboards
*
* @param manager
* @param keymap
* @param group
*
* @ingroup Elput_Input_Group
* @since 1.18
* @since 1.20
*/
EAPI void elput_input_keyboard_cached_keymap_set(Elput_Manager *manager, void *keymap);
EAPI void elput_input_keyboard_group_set(Elput_Manager *manager, int group);
/**
* Return the output name associated with a given device

View File

@ -89,7 +89,7 @@ _keyboard_fd_get(off_t size)
}
static Elput_Keyboard_Info *
_keyboard_info_create(struct xkb_keymap *keymap, Eina_Bool external)
_keyboard_info_create(struct xkb_keymap *keymap)
{
Elput_Keyboard_Info *info;
char *str;
@ -113,9 +113,6 @@ _keyboard_info_create(struct xkb_keymap *keymap, Eina_Bool external)
info->mods.altgr =
1 << xkb_keymap_mod_get_index(info->keymap.map, "ISO_Level3_Shift");
/* if we are using an external keymap then we do not need go further */
if (external) return info;
str = xkb_keymap_get_as_string(info->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
if (!str) goto err;
@ -145,17 +142,14 @@ err:
}
static void
_keyboard_info_destroy(Elput_Keyboard_Info *info, Eina_Bool external)
_keyboard_info_destroy(Elput_Keyboard_Info *info)
{
if (--info->refs > 0) return;
xkb_keymap_unref(info->keymap.map);
if (!external)
{
if (info->keymap.area) munmap(info->keymap.area, info->keymap.size);
if (info->keymap.fd >= 0) close(info->keymap.fd);
}
if (info->keymap.area) munmap(info->keymap.area, info->keymap.size);
if (info->keymap.fd >= 0) close(info->keymap.fd);
free(info);
}
@ -175,7 +169,7 @@ _keyboard_global_build(Elput_Keyboard *kbd)
keymap = xkb_keymap_new_from_names(kbd->context, &kbd->names, 0);
if (!keymap) return EINA_FALSE;
kbd->info = _keyboard_info_create(keymap, EINA_FALSE);
kbd->info = _keyboard_info_create(keymap);
xkb_keymap_unref(keymap);
if (!kbd->info) return EINA_FALSE;
@ -231,7 +225,9 @@ _keyboard_init(Elput_Seat *seat, struct xkb_keymap *keymap)
if (keymap)
{
kbd->info = _keyboard_info_create(keymap, EINA_TRUE);
if (seat->manager->cached.keymap == keymap)
kbd->context = xkb_context_ref(seat->manager->cached.context);
kbd->info = _keyboard_info_create(keymap);
if (!kbd->info) goto err;
}
else
@ -254,7 +250,7 @@ _keyboard_init(Elput_Seat *seat, struct xkb_keymap *keymap)
return EINA_TRUE;
err:
if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map);
if (kbd->info) _keyboard_info_destroy(kbd->info);
free(kbd);
return EINA_FALSE;
}
@ -346,39 +342,91 @@ _keyboard_modifiers_send(Elput_Keyboard *kbd)
ecore_event_add(ELPUT_EVENT_MODIFIERS_SEND, ev, NULL, NULL);
}
static void
static Eina_Bool
_keyboard_state_update(Elput_Keyboard *kbd, struct xkb_keymap *map, xkb_mod_mask_t *latched, xkb_mod_mask_t *locked)
{
struct xkb_state *state, *maskless_state;
state = xkb_state_new(map);
if (!state) return EINA_FALSE;
maskless_state = xkb_state_new(map);
if (!maskless_state)
{
xkb_state_unref(state);
return EINA_FALSE;
}
*latched = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LATCHED);
*locked = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LOCKED);
xkb_state_update_mask(state, 0, *latched, *locked, kbd->seat->manager->cached.group, 0, 0);
xkb_state_unref(kbd->state);
kbd->state = state;
xkb_state_unref(kbd->maskless_state);
kbd->maskless_state = maskless_state;
return EINA_TRUE;
}
void
_keyboard_keymap_update(Elput_Seat *seat)
{
Elput_Keyboard *kbd;
Elput_Keyboard_Info *info;
struct xkb_state *state;
Elput_Keyboard_Info *info = NULL;
xkb_mod_mask_t latched, locked;
Eina_Bool state = EINA_TRUE;
kbd = _evdev_keyboard_get(seat);
if (!kbd) return;
kbd->pending_keymap = 1;
if (kbd->key_count) return;
if (kbd->seat->manager->cached.keymap)
{
if (kbd->context) xkb_context_unref(kbd->context);
kbd->context = xkb_context_ref(kbd->seat->manager->cached.context);
info = _keyboard_info_create(kbd->seat->manager->cached.keymap);
if (!info) return;
state = _keyboard_state_update(kbd, info->keymap.map, &latched, &locked);
}
else if (!_keyboard_global_build(kbd)) return;
else
state = _keyboard_state_update(kbd, kbd->info->keymap.map, &latched, &locked);
kbd->pending_keymap = 0;
if (!state)
{
if (info) _keyboard_info_destroy(info);
return;
}
if (info)
{
_keyboard_info_destroy(kbd->info);
kbd->info = info;
}
_keyboard_compose_init(kbd);
_keyboard_modifiers_update(kbd, seat);
_keyboard_keymap_send(kbd->info);
if ((!latched) && (!locked)) return;
_keyboard_modifiers_send(kbd);
}
void
_keyboard_group_update(Elput_Seat *seat)
{
Elput_Keyboard *kbd;
xkb_mod_mask_t latched, locked;
Eina_Bool state;
kbd = _evdev_keyboard_get(seat);
if (!kbd) return;
info = _keyboard_info_create(kbd->pending_map, kbd->external_map);
xkb_keymap_unref(kbd->pending_map);
kbd->pending_map = NULL;
if (!info) return;
state = xkb_state_new(info->keymap.map);
if (!state)
{
_keyboard_info_destroy(info, kbd->external_map);
return;
}
latched = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LATCHED);
locked = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LOCKED);
xkb_state_update_mask(state, 0, latched, locked, 0, 0, 0);
_keyboard_info_destroy(kbd->info, kbd->external_map);
kbd->info = info;
xkb_state_unref(kbd->state);
kbd->state = state;
state = _keyboard_state_update(kbd, kbd->info->keymap.map, &latched, &locked);
if (!state) return;
_keyboard_compose_init(kbd);
_keyboard_modifiers_update(kbd, seat);
_keyboard_keymap_send(kbd->info);
@ -568,7 +616,7 @@ _keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *e
if (!kbd) return;
state = libinput_event_keyboard_get_key_state(event);
count = libinput_event_keyboard_get_seat_key_count(event);
kbd->key_count = count = libinput_event_keyboard_get_seat_key_count(event);
/* Ignore key events that are not seat wide state changes. */
if (((state == LIBINPUT_KEY_STATE_PRESSED) && (count != 1)) ||
@ -610,7 +658,7 @@ _keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *e
_keyboard_keysym_translate(sym, dev->seat->modifiers, compose, sizeof(compose));
_keyboard_key_send(dev, state, keyname, key, compose, code, timestamp);
if ((kbd->pending_map) && (count == 0))
if ((kbd->pending_keymap) && (count == 0))
_keyboard_keymap_update(dev->seat);
if (state == LIBINPUT_KEY_STATE_PRESSED)
@ -1588,12 +1636,14 @@ _evdev_keyboard_destroy(Elput_Keyboard *kbd)
free((char *)kbd->names.variant);
free((char *)kbd->names.options);
if (kbd->compose_table) xkb_compose_table_unref(kbd->compose_table);
if (kbd->compose_state) xkb_compose_state_unref(kbd->compose_state);
if (kbd->state) xkb_state_unref(kbd->state);
if (kbd->info) _keyboard_info_destroy(kbd->info, kbd->external_map);
if (kbd->maskless_state) xkb_state_unref(kbd->maskless_state);
if (kbd->info) _keyboard_info_destroy(kbd->info);
xkb_context_unref(kbd->context);
xkb_keymap_unref(kbd->pending_map);
free(kbd);
}

View File

@ -654,21 +654,37 @@ elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys,
}
EAPI void
elput_input_keyboard_cached_context_set(Elput_Manager *manager, void *context)
elput_input_keyboard_info_set(Elput_Manager *manager, void *context, void *keymap, int group)
{
EINA_SAFETY_ON_NULL_RETURN(manager);
Eina_List *l;
Elput_Seat *seat;
if ((context) && (manager->cached.context == context)) return;
EINA_SAFETY_ON_NULL_RETURN(manager);
EINA_SAFETY_ON_FALSE_RETURN((!!context) == (!!keymap));
if ((manager->cached.context == context) && (manager->cached.keymap == keymap)) return;
if (context) xkb_context_ref(context);
if (keymap) xkb_keymap_ref(keymap);
if (manager->cached.context) xkb_context_unref(manager->cached.context);
if (manager->cached.keymap) xkb_keymap_unref(manager->cached.keymap);
manager->cached.context = context;
manager->cached.keymap = keymap;
manager->cached.group = group;
EINA_LIST_FOREACH(manager->input.seats, l, seat)
_keyboard_keymap_update(seat);
}
EAPI void
elput_input_keyboard_cached_keymap_set(Elput_Manager *manager, void *keymap)
elput_input_keyboard_group_set(Elput_Manager *manager, int group)
{
Eina_List *l;
Elput_Seat *seat;
EINA_SAFETY_ON_NULL_RETURN(manager);
if ((keymap) && (manager->cached.keymap == keymap)) return;
manager->cached.keymap = keymap;
if (manager->cached.group == group) return;
manager->cached.group = group;
EINA_LIST_FOREACH(manager->input.seats, l, seat)
_keyboard_group_update(seat);
}
EAPI Eina_Stringshare *

View File

@ -527,6 +527,8 @@ _logind_disconnect(Elput_Manager *em)
_logind_dbus_close(em->dbus.conn);
eina_stringshare_del(em->seat);
free(em->sid);
if (em->cached.context) xkb_context_unref(em->cached.context);
if (em->cached.keymap) xkb_keymap_unref(em->cached.keymap);
free(em);
}

View File

@ -135,9 +135,9 @@ struct _Elput_Keyboard
} grab;
Elput_Keyboard_Info *info;
unsigned int key_count;
struct xkb_state *state;
struct xkb_keymap *pending_map;
struct xkb_state *maskless_state;
struct xkb_context *context;
struct xkb_rule_names names;
@ -146,7 +146,7 @@ struct _Elput_Keyboard
Elput_Seat *seat;
Eina_Bool external_map : 1;
Eina_Bool pending_keymap : 1;
};
struct _Elput_Pointer
@ -261,6 +261,7 @@ struct _Elput_Manager
{
struct xkb_keymap *keymap;
struct xkb_context *context;
int group;
} cached;
Elput_Input input;
@ -292,4 +293,7 @@ Elput_Touch *_evdev_touch_get(Elput_Seat *seat);
extern Elput_Interface _logind_interface;
void _keyboard_keymap_update(Elput_Seat *seat);
void _keyboard_group_update(Elput_Seat *seat);
#endif