[PATCH 3/5] xkb: Add XkbCompileKeymapFromString()
Kristian Høgsberg
krh at bitplanet.net
Fri Mar 7 14:32:26 PST 2014
This new function compiles a keymap from an in-memory string. We use it
to add a new keyooard device init function,
InitKeyboardDeviceStructFromString(), which inits a keyboard device with
a keymap specified as a string instead of a rmlvo set.
Reviewed-by: Daniel Stone <daniel at fooishbar.org>
---
include/input.h | 6 +++
include/xkbsrv.h | 4 ++
xkb/ddxLoad.c | 129 ++++++++++++++++++++++++++++++++++++++++++-------------
xkb/xkbInit.c | 44 +++++++++++++++----
4 files changed, 144 insertions(+), 39 deletions(-)
diff --git a/include/input.h b/include/input.h
index 93c4510..36463f2 100644
--- a/include/input.h
+++ b/include/input.h
@@ -385,6 +385,12 @@ extern _X_EXPORT Bool InitKeyboardDeviceStruct(DeviceIntPtr /*device */ ,
KbdCtrlProcPtr /*controlProc */
);
+extern _X_EXPORT Bool InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
+ const char *keymap,
+ int keymap_length,
+ BellProcPtr bell_func,
+ KbdCtrlProcPtr ctrl_func);
+
extern int ApplyPointerMapping(DeviceIntPtr /* pDev */ ,
CARD8 * /* map */ ,
int /* len */ ,
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index e799799..253612e 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -869,4 +869,8 @@ extern _X_EXPORT XkbDescPtr XkbCompileKeymap(DeviceIntPtr /* dev */ ,
XkbRMLVOSet * /* rmlvo */
);
+extern _X_EXPORT XkbDescPtr XkbCompileKeymapFromString(DeviceIntPtr dev,
+ const char *keymap,
+ int keymap_length);
+
#endif /* _XKBSRV_H_ */
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index d266b36..d4281a0 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -262,6 +262,35 @@ XkbDDXOpenConfigFile(char *mapName, char *fileNameRtrn, int fileNameRtrnLen)
return file;
}
+static unsigned
+LoadXKM(unsigned want, unsigned need, XkbCompContextPtr ctx, XkbDescPtr *xkbRtrn)
+{
+ FILE *file;
+ char fileName[PATH_MAX];
+ unsigned missing;
+
+ file = XkbDDXOpenConfigFile(ctx->keymap, fileName, PATH_MAX);
+ if (file == NULL) {
+ LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
+ fileName);
+ return 0;
+ }
+ missing = XkmReadFile(file, need, want, xkbRtrn);
+ if (*xkbRtrn == NULL) {
+ LogMessage(X_ERROR, "Error loading keymap %s\n", fileName);
+ fclose(file);
+ (void) unlink(fileName);
+ return 0;
+ }
+ else {
+ DebugF("Loaded XKB keymap %s, defined=0x%x\n", fileName,
+ (*xkbRtrn)->defined);
+ }
+ fclose(file);
+ (void) unlink(fileName);
+ return (need | want) & (~missing);
+}
+
unsigned
XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
XkbComponentNamesPtr names,
@@ -270,9 +299,6 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
XkbDescPtr *xkbRtrn, char *nameRtrn, int nameRtrnLen)
{
XkbDescPtr xkb;
- FILE *file;
- char fileName[PATH_MAX];
- unsigned missing;
XkbCompContextRec ctx;
*xkbRtrn = NULL;
@@ -292,26 +318,30 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
return 0;
}
- file = XkbDDXOpenConfigFile(ctx.keymap, fileName, PATH_MAX);
- if (file == NULL) {
- LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
- fileName);
- return 0;
- }
- missing = XkmReadFile(file, need, want, xkbRtrn);
- if (*xkbRtrn == NULL) {
- LogMessage(X_ERROR, "Error loading keymap %s\n", fileName);
- fclose(file);
- (void) unlink(fileName);
+
+ return LoadXKM(want, need, &ctx, xkbRtrn);
+}
+
+static unsigned
+XkbDDXLoadKeymapFromString(DeviceIntPtr keybd,
+ const char *keymap, int keymap_length,
+ unsigned want,
+ unsigned need,
+ XkbDescPtr *xkbRtrn)
+{
+ XkbCompContextRec ctx;
+
+ *xkbRtrn = NULL;
+
+ if (StartXkbComp(&ctx))
+ fwrite(keymap, keymap_length, 1, ctx.out);
+
+ if (!FinishXkbComp(&ctx)) {
+ LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
return 0;
}
- else {
- DebugF("Loaded XKB keymap %s, defined=0x%x\n", fileName,
- (*xkbRtrn)->defined);
- }
- fclose(file);
- (void) unlink(fileName);
- return (need | want) & (~missing);
+
+ return LoadXKM(want, need, &ctx, xkbRtrn);
}
Bool
@@ -407,6 +437,29 @@ XkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet * rmlvo, int need)
return xkb;
}
+static XkbDescPtr
+KeymapOrDefaults(DeviceIntPtr dev, XkbDescPtr xkb)
+{
+ XkbRMLVOSet dflts;
+
+ if (xkb)
+ return xkb;
+
+ /* we didn't get what we really needed. And that will likely leave
+ * us with a keyboard that doesn't work. Use the defaults instead */
+ LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default "
+ "keymap instead.\n");
+
+ XkbGetRulesDflts(&dflts);
+
+ xkb = XkbCompileKeymapForDevice(dev, &dflts, 0);
+
+ XkbFreeRMLVOSet(&dflts, FALSE);
+
+ return xkb;
+}
+
+
XkbDescPtr
XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo)
{
@@ -424,20 +477,34 @@ XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo)
xkb = XkbCompileKeymapForDevice(dev, rmlvo, need);
- if (!xkb) {
- XkbRMLVOSet dflts;
+ return KeymapOrDefaults(dev, xkb);
+}
- /* we didn't get what we really needed. And that will likely leave
- * us with a keyboard that doesn't work. Use the defaults instead */
- LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default "
- "keymap instead.\n");
+XkbDescPtr
+XkbCompileKeymapFromString(DeviceIntPtr dev,
+ const char *keymap, int keymap_length)
+{
+ XkbDescPtr xkb;
+ unsigned int need, provided;
- XkbGetRulesDflts(&dflts);
+ if (!dev || !keymap) {
+ LogMessage(X_ERROR, "XKB: No device or keymap specified\n");
+ return NULL;
+ }
- xkb = XkbCompileKeymapForDevice(dev, &dflts, 0);
+ /* These are the components we really really need */
+ need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask |
+ XkmKeyNamesMask | XkmVirtualModsMask;
- XkbFreeRMLVOSet(&dflts, FALSE);
+ provided =
+ XkbDDXLoadKeymapFromString(dev, keymap, keymap_length,
+ XkmAllIndicesMask, need, &xkb);
+ if ((need & provided) != need) {
+ if (xkb) {
+ XkbFreeKeyboard(xkb, 0, TRUE);
+ xkb = NULL;
+ }
}
- return xkb;
+ return KeymapOrDefaults(dev, xkb);
}
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index 33420b6..766ca7b 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -505,9 +505,10 @@ XkbInitControls(DeviceIntPtr pXDev, XkbSrvInfoPtr xkbi)
return Success;
}
-_X_EXPORT Bool
-InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
- BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
+static Bool
+InitKeyboardDeviceStructInternal(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
+ const char *keymap, int keymap_length,
+ BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
{
int i;
unsigned int check;
@@ -522,7 +523,7 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
BUG_RETURN_VAL(dev->key != NULL, FALSE);
BUG_RETURN_VAL(dev->kbdfeed != NULL, FALSE);
- if (!rmlvo) {
+ if (!rmlvo && !keymap) {
rmlvo = &rmlvo_dflts;
XkbGetRulesDflts(rmlvo);
}
@@ -550,19 +551,26 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
}
dev->key->xkbInfo = xkbi;
- if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
+ if (xkb_cached_map && (keymap || (rmlvo && !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 {
+ else if (rmlvo) {
xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
if (!xkb_cached_map) {
ErrorF("XKB: Failed to compile keymap\n");
goto unwind_info;
}
+ } else {
+ xkb_cached_map = XkbCompileKeymapFromString(dev,
+ keymap, keymap_length);
+ if (!xkb_cached_map) {
+ ErrorF("XKB: Failed to compile keymap from string\n");
+ goto unwind_info;
+ }
}
xkb = XkbAllocKeyboard();
@@ -627,8 +635,10 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
dev->kbdfeed->CtrlProc(dev, &dev->kbdfeed->ctrl);
- XkbSetRulesDflts(rmlvo);
- XkbSetRulesUsed(rmlvo);
+ if (rmlvo) {
+ XkbSetRulesDflts(rmlvo);
+ XkbSetRulesUsed(rmlvo);
+ }
XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
return TRUE;
@@ -647,6 +657,24 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
return FALSE;
}
+_X_EXPORT Bool
+InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
+ BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
+{
+ return InitKeyboardDeviceStructInternal(dev, rmlvo,
+ NULL, 0, bell_func, ctrl_func);
+}
+
+_X_EXPORT Bool
+InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
+ const char *keymap, int keymap_length,
+ BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
+{
+ return InitKeyboardDeviceStructInternal(dev, NULL,
+ keymap, keymap_length,
+ bell_func, ctrl_func);
+}
+
/***====================================================================***/
/*
--
1.9.0
More information about the xorg-devel
mailing list