Rather than compiling a new keymap every time InitKeyboardDeviceStruct is called, cache the previous keymap and reuse it if the rules have not changed.
Signed-off-by: Dan Nicholson <[email protected]> --- The RMLVO comparison takes into account empty string vs. NULL. Should it do that? I can't tell from a cursory glance through xkb/maprule.c whether that's important or not. xkb/xkbInit.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 47 insertions(+), 2 deletions(-) diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c index e9b9d65..1698cf0 100644 --- a/xkb/xkbInit.c +++ b/xkb/xkbInit.c @@ -105,6 +105,8 @@ static char * XkbLayoutUsed= NULL; static char * XkbVariantUsed= NULL; static char * XkbOptionsUsed= NULL; +static XkbDescPtr xkb_cached_map = NULL; + static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP; /***====================================================================***/ @@ -255,8 +257,28 @@ XkbDeleteRulesDflts(void) XkbVariantDflt = NULL; _XkbFree(XkbOptionsDflt); XkbOptionsDflt = NULL; + + XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, True); + xkb_cached_map = NULL; +} + +#define DIFFERS(a,b) \ + (((a) && !(b)) || (!(a) && (b)) || ((a) && (b) && strcmp((a), (b)) != 0)) + +static Bool +XkbCompareUsedRMLVO(XkbRMLVOSet *rmlvo) +{ + if (DIFFERS(rmlvo->rules, XkbRulesUsed) || + DIFFERS(rmlvo->model, XkbModelUsed) || + DIFFERS(rmlvo->layout, XkbLayoutUsed) || + DIFFERS(rmlvo->variant, XkbVariantUsed) || + DIFFERS(rmlvo->options, XkbOptionsUsed)) + return FALSE; + return TRUE; } +#undef DIFFERS + /***====================================================================***/ #include "xkbDflts.h" @@ -479,11 +501,34 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, } dev->key->xkbInfo = xkbi; - xkb = XkbCompileKeymap(dev, rmlvo); + if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) { + XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, True); + xkb_cached_map = NULL; + } + + if (xkb_cached_map) + LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n"); + else { + xkb_cached_map = XkbCompileKeymap(dev, rmlvo); + if (!xkb_cached_map) { + ErrorF("XKB: Failed to compile keymap\n"); + goto unwind_info; + } + } + + xkb = XkbAllocKeyboard(); if (!xkb) { - ErrorF("XKB: Failed to compile keymap\n"); + ErrorF("XKB: Failed to allocate keyboard description\n"); goto unwind_info; } + + if (!XkbCopyKeymap(xkb, xkb_cached_map)) { + ErrorF("XKB: Failed to copy keymap\n"); + goto unwind_desc; + } + xkb->defined = xkb_cached_map->defined; + xkb->flags = xkb_cached_map->flags; + xkb->device_spec = xkb_cached_map->device_spec; xkbi->desc = xkb; if (xkb->min_key_code == 0) -- 1.5.6.6 _______________________________________________ xorg-devel mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-devel
