diff --git a/src/lib/ecore_drm/Ecore_Drm.h b/src/lib/ecore_drm/Ecore_Drm.h --- a/src/lib/ecore_drm/Ecore_Drm.h +++ b/src/lib/ecore_drm/Ecore_Drm.h @@ -6,6 +6,7 @@ # include # include # include +# include # ifdef EAPI # undef EAPI @@ -382,6 +383,32 @@ EAPI Eina_Bool ecore_drm_device_pointer_left_handed_set(Ecore_Drm_Device *dev, Eina_Bool left_handed); /** + * Setup a cached context to use same context for each devices + * + * This function will setup a cached context to use same context for each devices + * This function will be called before initialize Ecore_Drm. + * + * @param ctx struct xkb_context used in libxkbcommon + * + * @ingroup Ecore_Drm_Device_Group + * @since 1.17 + */ +EAPI void ecore_drm_device_keyboard_cached_context_set(struct xkb_context *ctx); + +/** + * Setup a cached keymap to use same keymap for each devices + * + * This function will setup a cached keymap to use same keymap for each devices + * This function will be called before initialize Ecore_Drm. + * + * @param map struct xkb_keymap used in libxkbcommon + * + * @ingroup Ecore_Drm_Device_Group + * @since 1.17 + */ +EAPI void ecore_drm_device_keyboard_cached_keymap_set(struct xkb_keymap *map); + +/** * Find an Ecore_Drm_Output at the given coordinates * * This function will loop all the existing outputs in Ecore_Drm_Device and diff --git a/src/lib/ecore_drm/ecore_drm_device.c b/src/lib/ecore_drm/ecore_drm_device.c --- a/src/lib/ecore_drm/ecore_drm_device.c +++ b/src/lib/ecore_drm/ecore_drm_device.c @@ -107,6 +107,58 @@ _ecore_drm_outputs_update(dev); } +struct xkb_context * +_ecore_drm_device_cached_context_get(enum xkb_context_flags flags) +{ + if (!cached_context) + return xkb_context_new(flags); + else + return xkb_context_ref(cached_context); +} + +struct xkb_keymap * +_ecore_drm_device_cached_keymap_get(struct xkb_context *ctx, + const struct xkb_rule_names *names, + enum xkb_keymap_compile_flags flags) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + + if (!cached_keymap) + return xkb_map_new_from_names(ctx, names, flags); + else + return xkb_map_ref(cached_keymap); +} + +void +_ecore_drm_device_cached_context_update(struct xkb_context *ctx) +{ + Eina_List *l; + Ecore_Drm_Device *dev; + + EINA_LIST_FOREACH(drm_devices, l, dev) + { + xkb_context_unref(dev->xkb_ctx); + dev->xkb_ctx = xkb_context_ref(ctx); + } +} + +void +_ecore_drm_device_cached_keymap_update(struct xkb_keymap *map) +{ + Eina_List *l, *l2, *l3; + Ecore_Drm_Device *dev; + Ecore_Drm_Seat *seat; + Ecore_Drm_Evdev *edev; + + EINA_LIST_FOREACH(drm_devices, l, dev) + EINA_LIST_FOREACH(dev->seats, l2, seat) + EINA_LIST_FOREACH(seat->devices, l3, edev) + { + xkb_keymap_unref(edev->xkb.keymap); + edev->xkb.keymap = xkb_keymap_ref(map); + } +} + /** * @defgroup Ecore_Drm_Device_Group Device manipulation functions * @@ -308,7 +360,7 @@ } /* try to create xkb context */ - if (!(dev->xkb_ctx = xkb_context_new(0))) + if (!(dev->xkb_ctx = _ecore_drm_device_cached_context_get(0))) { ERR("Failed to create xkb context: %m"); return EINA_FALSE; @@ -590,3 +642,29 @@ } return EINA_TRUE; } + +EAPI void +ecore_drm_device_keyboard_cached_context_set(struct xkb_context *ctx) +{ + EINA_SAFETY_ON_NULL_RETURN(ctx); + + if (cached_context == ctx) return; + + if (cached_context) + _ecore_drm_device_cached_context_update(ctx); + + cached_context = ctx; +} + +EAPI void +ecore_drm_device_keyboard_cached_keymap_set(struct xkb_keymap *map) +{ + EINA_SAFETY_ON_NULL_RETURN(map); + + if (cached_keymap == map) return; + + if (cached_keymap) + _ecore_drm_device_cached_keymap_update(map); + + cached_keymap = map; +} diff --git a/src/lib/ecore_drm/ecore_drm_evdev.c b/src/lib/ecore_drm/ecore_drm_evdev.c --- a/src/lib/ecore_drm/ecore_drm_evdev.c +++ b/src/lib/ecore_drm/ecore_drm_evdev.c @@ -116,7 +116,7 @@ if (!input->dev->xkb_ctx) return; /* create keymap from xkb context */ - edev->xkb.keymap = xkb_map_new_from_names(input->dev->xkb_ctx, NULL, 0); + edev->xkb.keymap = _ecore_drm_device_cached_keymap_get(input->dev->xkb_ctx, NULL, 0); if (!edev->xkb.keymap) { ERR("Failed to create keymap: %m"); diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h --- a/src/lib/ecore_drm/ecore_drm_private.h +++ b/src/lib/ecore_drm/ecore_drm_private.h @@ -24,7 +24,6 @@ # include # include # include -# include # ifdef HAVE_SYSTEMD # include @@ -69,6 +68,8 @@ # endif extern int _ecore_drm_log_dom; +struct xkb_keymap *cached_keymap; +struct xkb_context *cached_context; # define EVDEV_MAX_SLOTS 32 @@ -294,4 +295,9 @@ void _ecore_drm_inputs_init(void); void _ecore_drm_inputs_shutdown(void); + +struct xkb_context *_ecore_drm_device_cached_context_get(enum xkb_context_flags flags); +struct xkb_keymap *_ecore_drm_device_cached_keymap_get(struct xkb_context *ctx, + const struct xkb_rule_names *names, + enum xkb_keymap_compile_flags flags); #endif