From 361f405d3c866bc4d22ef84975fe771691156336 Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Fri, 7 Mar 2014 14:32:28 -0800 Subject: [PATCH 1/7] xkb: Factor out a function to copy a keymap's controls onto another MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Kristian Høgsberg Signed-off-by: Peter Hutterer --- include/xkbsrv.h | 3 +++ xkb/xkb.c | 14 +------------- xkb/xkbUtils.c | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/xkbsrv.h b/include/xkbsrv.h index f857b2280..06f12003b 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -841,6 +841,9 @@ extern void XkbFakeDeviceButton(DeviceIntPtr /* dev */ , int /* press */ , int /* button */ ); +extern _X_EXPORT void XkbCopyControls(XkbDescPtr /* dst */ , + XkbDescPtr /* src */ ); + #include "xkbfile.h" #include "xkbrules.h" diff --git a/xkb/xkb.c b/xkb/xkb.c index 31bb8d3c5..920ec7282 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5950,25 +5950,13 @@ ProcXkbGetKbdByName(ClientPtr client) if (rep.loaded) { XkbDescPtr old_xkb; xkbNewKeyboardNotify nkn; - int i, nG, nTG; old_xkb = xkb; xkb = new; dev->key->xkbInfo->desc = xkb; new = old_xkb; /* so it'll get freed automatically */ - *xkb->ctrls = *old_xkb->ctrls; - for (nG = nTG = 0, i = xkb->min_key_code; i <= xkb->max_key_code; i++) { - nG = XkbKeyNumGroups(xkb, i); - if (nG >= XkbNumKbdGroups) { - nTG = XkbNumKbdGroups; - break; - } - if (nG > nTG) { - nTG = nG; - } - } - xkb->ctrls->num_groups = nTG; + XkbCopyControls(xkb, old_xkb); nkn.deviceID = nkn.oldDeviceID = dev->id; nkn.minKeyCode = new->min_key_code; diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 6c6af60f0..b59d92550 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -2090,3 +2090,26 @@ XkbMergeLockedPtrBtns(DeviceIntPtr master) xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons; } } + +void +XkbCopyControls(XkbDescPtr dst, XkbDescPtr src) +{ + int i, nG, nTG; + + if (!dst || !src) + return; + + *dst->ctrls = *src->ctrls; + + for (nG = nTG = 0, i = dst->min_key_code; i <= dst->max_key_code; i++) { + nG = XkbKeyNumGroups(dst, i); + if (nG >= XkbNumKbdGroups) { + nTG = XkbNumKbdGroups; + break; + } + if (nG > nTG) { + nTG = nG; + } + } + dst->ctrls->num_groups = nTG; +} From d35a02a767017f13db4bd4742eef49293d5a30ea Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Fri, 7 Mar 2014 14:32:27 -0800 Subject: [PATCH 2/7] xkb: Repurpose XkbCopyDeviceKeymap to apply a given keymap to a device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will also make it useful for cases when we have a new keymap to apply to a device but don't have a source device. Reviewed-by: Kristian Høgsberg Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- Xi/exevents.c | 2 +- include/xkbsrv.h | 4 ++-- xkb/xkb.c | 2 +- xkb/xkbUtils.c | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index e9f670ec5..9c207eb23 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -230,7 +230,7 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) mk->sourceid = device->id; - if (!XkbCopyDeviceKeymap(master, device)) + if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc)) FatalError("Couldn't pivot keymap from device to core!\n"); } diff --git a/include/xkbsrv.h b/include/xkbsrv.h index 06f12003b..c1c1561cb 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -824,8 +824,8 @@ extern _X_EXPORT void XkbSendNewKeyboardNotify(DeviceIntPtr /* kbd */ , extern Bool XkbCopyKeymap(XkbDescPtr /* dst */ , XkbDescPtr /* src */ ); -extern _X_EXPORT Bool XkbCopyDeviceKeymap(DeviceIntPtr /* dst */ , - DeviceIntPtr /* src */ ); +extern _X_EXPORT Bool XkbDeviceApplyKeymap(DeviceIntPtr /* dst */ , + XkbDescPtr /* src */ ); extern void XkbFilterEvents(ClientPtr /* pClient */ , int /* nEvents */ , diff --git a/xkb/xkb.c b/xkb/xkb.c index 920ec7282..dc570f0e5 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5979,7 +5979,7 @@ ProcXkbGetKbdByName(ClientPtr client) continue; if (tmpd != dev) - XkbCopyDeviceKeymap(tmpd, dev); + XkbDeviceApplyKeymap(tmpd, xkb); if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { old_sli = tmpd->kbdfeed->xkb_sli; diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index b59d92550..6cf6e79df 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -1999,28 +1999,28 @@ XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src) } Bool -XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src) +XkbDeviceApplyKeymap(DeviceIntPtr dst, XkbDescPtr desc) { xkbNewKeyboardNotify nkn; Bool ret; - if (!dst->key || !src->key) + if (!dst->key || !desc) return FALSE; memset(&nkn, 0, sizeof(xkbNewKeyboardNotify)); nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code; nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code; nkn.deviceID = dst->id; - nkn.oldDeviceID = dst->id; /* maybe src->id? */ - nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code; - nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code; + nkn.oldDeviceID = dst->id; + nkn.minKeyCode = desc->min_key_code; + nkn.maxKeyCode = desc->max_key_code; nkn.requestMajor = XkbReqCode; nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */ nkn.changed = XkbNKN_KeycodesMask; - if (src->key->xkbInfo->desc->geom) + if (desc->geom) nkn.changed |= XkbNKN_GeometryMask; - ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc); + ret = XkbCopyKeymap(dst->key->xkbInfo->desc, desc); if (ret) XkbSendNewKeyboardNotify(dst, &nkn); From 6ebd838d80074075827dedb75ed4169ea1946be3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 12 Mar 2014 17:17:25 +1000 Subject: [PATCH 3/7] xkb: constify XkbDDXOpenConfigFile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Kristian Høgsberg --- xkb/ddxLoad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index f458e3bde..551f20a13 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -210,7 +210,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, } static FILE * -XkbDDXOpenConfigFile(char *mapName, char *fileNameRtrn, int fileNameRtrnLen) +XkbDDXOpenConfigFile(const char *mapName, char *fileNameRtrn, int fileNameRtrnLen) { char buf[PATH_MAX], xkm_output_dir[PATH_MAX]; FILE *file; From 4391cf27f40ec53d41ac7e437cde49848eb32bde Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 12 Mar 2014 16:08:15 +1000 Subject: [PATCH 4/7] xkb: add a callback to xkbcomp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This provides a callback to write to xkbcomp's buffer once everything is prepared. Signed-off-by: Peter Hutterer Reviewed-by: Kristian Høgsberg --- xkb/ddxLoad.c | 86 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index 551f20a13..33247cf66 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -90,11 +90,17 @@ OutputDirectory(char *outdir, size_t size) } } -static Bool -XkbDDXCompileKeymapByNames(XkbDescPtr xkb, - XkbComponentNamesPtr names, - unsigned want, - unsigned need, char *nameRtrn, int nameRtrnLen) +/** + * Callback invoked by XkbRunXkbComp. Write to out to talk to xkbcomp. + */ +typedef void (*xkbcomp_buffer_callback)(FILE *out, void *userdata); + +/** + * Start xkbcomp, let the callback write into xkbcomp's stdin. When done, + * return a strdup'd copy of the file name we've written to. + */ +static char * +RunXkbComp(xkbcomp_buffer_callback callback, void *userdata) { FILE *out; char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX]; @@ -155,7 +161,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, if (!buf) { LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp: not enough memory\n"); - return FALSE; + return NULL; } #ifndef WIN32 @@ -165,13 +171,9 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, #endif if (out != NULL) { -#ifdef DEBUG - if (xkbDebugFlags) { - ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n"); - XkbWriteXKBKeymapForNames(stderr, names, xkb, want, need); - } -#endif - XkbWriteXKBKeymapForNames(out, names, xkb, want, need); + /* Now write to xkbcomp */ + (*callback)(out, userdata); + #ifndef WIN32 if (Pclose(out) == 0) #else @@ -180,14 +182,11 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, { if (xkbDebugFlags) DebugF("[xkb] xkb executes: %s\n", buf); - if (nameRtrn) { - strlcpy(nameRtrn, keymap, nameRtrnLen); - } free(buf); #ifdef WIN32 unlink(tmpname); #endif - return TRUE; + return xnfstrdup(keymap); } else LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap); @@ -203,10 +202,57 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb, LogMessage(X_ERROR, "Could not open file %s\n", tmpname); #endif } - if (nameRtrn) - nameRtrn[0] = '\0'; free(buf); - return FALSE; + return NULL; +} + +typedef struct { + XkbDescPtr xkb; + XkbComponentNamesPtr names; + unsigned int want; + unsigned int need; +} XkbKeymapNamesCtx; + +static void +xkb_write_keymap_for_names_cb(FILE *out, void *userdata) +{ + XkbKeymapNamesCtx *ctx = userdata; +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n"); + XkbWriteXKBKeymapForNames(stderr, ctx->names, ctx->xkb, ctx->want, ctx->need); + } +#endif + XkbWriteXKBKeymapForNames(out, ctx->names, ctx->xkb, ctx->want, ctx->need); +} + +static Bool +XkbDDXCompileKeymapByNames(XkbDescPtr xkb, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, char *nameRtrn, int nameRtrnLen) +{ + char *keymap; + Bool rc = FALSE; + XkbKeymapNamesCtx ctx = { + .xkb = xkb, + .names = names, + .want = want, + .need = need + }; + + keymap = RunXkbComp(xkb_write_keymap_for_names_cb, &ctx); + + if (keymap) { + if(nameRtrn) + strlcpy(nameRtrn, keymap, nameRtrnLen); + + free(keymap); + rc = TRUE; + } else if (nameRtrn) + *nameRtrn = '\0'; + + return rc; } static FILE * From cb9a1d01468732196fd25c6422991e784639ffce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 12 Mar 2014 17:18:22 +1000 Subject: [PATCH 5/7] xkb: factor out xkb loading to LoadXkm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Kristian Høgsberg --- xkb/ddxLoad.c | 60 +++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index 33247cf66..0361b9be5 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -291,37 +291,14 @@ XkbDDXOpenConfigFile(const char *mapName, char *fileNameRtrn, int fileNameRtrnLe return file; } -unsigned -XkbDDXLoadKeymapByNames(DeviceIntPtr keybd, - XkbComponentNamesPtr names, - unsigned want, - unsigned need, - XkbDescPtr *xkbRtrn, char *nameRtrn, int nameRtrnLen) +static unsigned +LoadXKM(unsigned want, unsigned need, const char *keymap, XkbDescPtr *xkbRtrn) { - XkbDescPtr xkb; FILE *file; char fileName[PATH_MAX]; unsigned missing; - *xkbRtrn = NULL; - if ((keybd == NULL) || (keybd->key == NULL) || - (keybd->key->xkbInfo == NULL)) - xkb = NULL; - else - xkb = keybd->key->xkbInfo->desc; - if ((names->keycodes == NULL) && (names->types == NULL) && - (names->compat == NULL) && (names->symbols == NULL) && - (names->geometry == NULL)) { - LogMessage(X_ERROR, "XKB: No components provided for device %s\n", - keybd->name ? keybd->name : "(unnamed keyboard)"); - return 0; - } - else if (!XkbDDXCompileKeymapByNames(xkb, names, want, need, - nameRtrn, nameRtrnLen)) { - LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n"); - return 0; - } - file = XkbDDXOpenConfigFile(nameRtrn, fileName, PATH_MAX); + file = XkbDDXOpenConfigFile(keymap, fileName, PATH_MAX); if (file == NULL) { LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n", fileName); @@ -343,6 +320,37 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd, return (need | want) & (~missing); } +unsigned +XkbDDXLoadKeymapByNames(DeviceIntPtr keybd, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + XkbDescPtr *xkbRtrn, char *nameRtrn, int nameRtrnLen) +{ + XkbDescPtr xkb; + + *xkbRtrn = NULL; + if ((keybd == NULL) || (keybd->key == NULL) || + (keybd->key->xkbInfo == NULL)) + xkb = NULL; + else + xkb = keybd->key->xkbInfo->desc; + if ((names->keycodes == NULL) && (names->types == NULL) && + (names->compat == NULL) && (names->symbols == NULL) && + (names->geometry == NULL)) { + LogMessage(X_ERROR, "XKB: No components provided for device %s\n", + keybd->name ? keybd->name : "(unnamed keyboard)"); + return 0; + } + else if (!XkbDDXCompileKeymapByNames(xkb, names, want, need, + nameRtrn, nameRtrnLen)) { + LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n"); + return 0; + } + + return LoadXKM(want, need, nameRtrn, xkbRtrn); +} + Bool XkbDDXNamesFromRules(DeviceIntPtr keybd, const char *rules_name, From 8b6c79e19cfabd9f343884ddd91a738720c94583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 12 Mar 2014 17:20:17 +1000 Subject: [PATCH 6/7] xkb: add KeymapOrDefault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Helper function to return a default map if the keymap compilation failed. Signed-off-by: Peter Hutterer Reviewed-by: Kristian Høgsberg --- xkb/ddxLoad.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index 0361b9be5..76bf09ca7 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -444,6 +444,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) { @@ -461,20 +484,5 @@ XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo) xkb = XkbCompileKeymapForDevice(dev, rmlvo, need); - if (!xkb) { - XkbRMLVOSet dflts; - - /* 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; + return KeymapOrDefaults(dev, xkb); } From 0e531fbb97868b9a869044fc5a4f6cb58de6751e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 12 Mar 2014 16:31:25 +1000 Subject: [PATCH 7/7] xkb: add XkbLoadKeymapFromString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Kristian Høgsberg --- include/input.h | 6 ++++ include/xkbsrv.h | 4 +++ xkb/ddxLoad.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 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); +} + /***====================================================================***/ /*