[PATCH v2] xkb: Use cached XKB keymap when rules haven't changed

Dan Nicholson dbn.lists at gmail.com
Tue Feb 17 22:46:05 PST 2009


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 <dbn.lists at gmail.com>
---
 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


More information about the xorg-devel mailing list