diff options
-rw-r--r-- | include/input.h | 6 | ||||
-rw-r--r-- | include/xkbsrv.h | 4 | ||||
-rw-r--r-- | xkb/ddxLoad.c | 72 | ||||
-rw-r--r-- | xkb/xkbInit.c | 42 |
4 files changed, 116 insertions, 8 deletions
diff --git a/include/input.h b/include/input.h index 93c45107d..36463f2d1 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 c1c1561cb..a80e11970 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -876,4 +876,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 76bf09ca7..1dc0e4eee 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -68,6 +68,9 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE. #define PATHSEPARATOR "/" #endif +static unsigned +LoadXKM(unsigned want, unsigned need, const char *keymap, XkbDescPtr *xkbRtrn); + static void OutputDirectory(char *outdir, size_t size) { @@ -255,6 +258,46 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, return rc; } +typedef struct { + const char *keymap; + size_t len; +} XkbKeymapString; + +static void +xkb_write_keymap_string_cb(FILE *out, void *userdata) +{ + XkbKeymapString *s = userdata; + fwrite(s->keymap, s->len, 1, out); +} + +static unsigned int +XkbDDXLoadKeymapFromString(DeviceIntPtr keybd, + const char *keymap, int keymap_length, + unsigned int want, + unsigned int need, + XkbDescPtr *xkbRtrn) +{ + unsigned int have; + char *map_name; + XkbKeymapString map = { + .keymap = keymap, + .len = keymap_length + }; + + *xkbRtrn = NULL; + + map_name = RunXkbComp(xkb_write_keymap_string_cb, &map); + if (!map_name) { + LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n"); + return 0; + } + + have = LoadXKM(want, need, map_name, xkbRtrn); + free(map_name); + + return have; +} + static FILE * XkbDDXOpenConfigFile(const char *mapName, char *fileNameRtrn, int fileNameRtrnLen) { @@ -486,3 +529,32 @@ XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo) return KeymapOrDefaults(dev, xkb); } + +XkbDescPtr +XkbCompileKeymapFromString(DeviceIntPtr dev, + const char *keymap, int keymap_length) +{ + XkbDescPtr xkb; + unsigned int need, provided; + + if (!dev || !keymap) { + LogMessage(X_ERROR, "XKB: No device or keymap specified\n"); + return NULL; + } + + /* These are the components we really really need */ + need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask | + XkmKeyNamesMask | XkmVirtualModsMask; + + provided = + XkbDDXLoadKeymapFromString(dev, keymap, keymap_length, + XkmAllIndicesMask, need, &xkb); + if ((need & provided) != need) { + if (xkb) { + XkbFreeKeyboard(xkb, 0, TRUE); + xkb = NULL; + } + } + + return KeymapOrDefaults(dev, xkb); +} diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c index 33420b6b6..06ec46e81 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; @@ -521,8 +522,9 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo, BUG_RETURN_VAL(dev == NULL, FALSE); BUG_RETURN_VAL(dev->key != NULL, FALSE); BUG_RETURN_VAL(dev->kbdfeed != NULL, FALSE); + BUG_RETURN_VAL(rmlvo && keymap, FALSE); - if (!rmlvo) { + if (!rmlvo && !keymap) { rmlvo = &rmlvo_dflts; XkbGetRulesDflts(rmlvo); } @@ -550,7 +552,7 @@ 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; } @@ -558,7 +560,11 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo, if (xkb_cached_map) LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n"); else { - xkb_cached_map = XkbCompileKeymap(dev, rmlvo); + if (rmlvo) + xkb_cached_map = XkbCompileKeymap(dev, rmlvo); + else + xkb_cached_map = XkbCompileKeymapFromString(dev, keymap, keymap_length); + if (!xkb_cached_map) { ErrorF("XKB: Failed to compile keymap\n"); goto unwind_info; @@ -627,8 +633,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 +655,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); +} + /***====================================================================***/ /* |