From ff013b0da4e6d33b2b69ce1212e9bd62050574e1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 8 May 2008 16:58:31 +0930 Subject: [PATCH] config: override xkb_{r,m,l,v} with Xkb{r,m,l,v} if the latter is set. The HAL spec says that input.xkb.{rmlv}* can be sent, but if the user specifies a X-specific {rmlv}, then this is overridden through the use of input.x11_options.Xkb{RMLV}. However, the way how the server parses options--by ignoring capitalisation, underscores and spaces--the HAL and the x11_options would override each other. So we simply filter the options, letting Xkb{RMLV} override xkb_{rmlv} and only actually add them to the device after parsing _all_ options. * rmlv ... rules, model, layout, variant See Bug 13037 (cherry picked from commit fc35d1e3be201e3821413bb2eeb8d43e1e56ba17) --- config/hal.c | 100 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 87 insertions(+), 13 deletions(-) diff --git a/config/hal.c b/config/hal.c index 7794d8e8a..67ffa0304 100644 --- a/config/hal.c +++ b/config/hal.c @@ -48,6 +48,15 @@ struct config_hal_info { LibHalContext *hal_ctx; }; +/* Used for special handling of xkb options. */ +struct xkb_options { + char* layout; + char* model; + char* rules; + char* variant; +}; + + static void remove_device(DeviceIntPtr dev) { @@ -164,10 +173,11 @@ device_added(LibHalContext *hal_ctx, const char *udi) InputOption *options = NULL, *tmpo = NULL; DeviceIntPtr dev; DBusError error; + struct xkb_options xkb_opts = {0}; LibHalPropertySet *set = NULL; LibHalPropertySetIterator set_iter; - char *psi_key = NULL, *tmp_val, *tmp_key; + char *psi_key = NULL, *tmp_val; dbus_error_init(&error); @@ -241,27 +251,71 @@ device_added(LibHalContext *hal_ctx, const char *udi) tmp_val = get_prop_string(hal_ctx, udi, psi_key); if (tmp_val){ - add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val); - xfree(tmp_val); - } + char* tmp; - /* evdev's XKB options... we should probably depreciate this usage */ + /* xkb needs special handling. HAL specs include + * input.xkb.xyz options, but the x11-input.fdi specifies + * input.x11_options.Xkbxyz options. By default, we use + * the former, unless the specific X11 ones are specified. + * Since we can't predict the order in which the keys + * arrive, we need to store them. + */ + if ((tmp = strcasestr(psi_key, "xkb"))) + { + if (!strcasecmp(&tmp[3], "layout")) + { + if (xkb_opts.layout) + xfree(xkb_opts.layout); + xkb_opts.layout = strdup(tmp_val); + } else if (!strcasecmp(&tmp[3], "model")) + { + if (xkb_opts.model) + xfree(xkb_opts.model); + xkb_opts.model = strdup(tmp_val); + } else if (!strcasecmp(&tmp[3], "rules")) + { + if (xkb_opts.rules) + xfree(xkb_opts.rules); + xkb_opts.rules = strdup(tmp_val); + } else if (!strcasecmp(&tmp[3], "variant")) + { + if (xkb_opts.variant) + xfree(xkb_opts.variant); + xkb_opts.variant = strdup(tmp_val); + } + } else + { + /* all others */ + add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val); + xfree(tmp_val); + } + } } else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){ /* only support strings for all values */ tmp_val = get_prop_string(hal_ctx, udi, psi_key); if (tmp_val){ - /* add "xkb_" + NULL */ - tmp_key = xalloc(strlen(psi_key) - ( sizeof(LIBHAL_XKB_PROP_KEY) - 1) + 5); + char* tmp; - if (!tmp_key){ - LogMessage(X_ERROR, "config/hal: couldn't allocate memory for option %s\n", psi_key); - } else { - sprintf(tmp_key, "xkb_%s", psi_key + sizeof(LIBHAL_XKB_PROP_KEY)-1); - add_option(&options, tmp_key, tmp_val); + tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1]; - xfree(tmp_key); + if (!strcasecmp(tmp, "layout")) + { + if (!xkb_opts.layout) + xkb_opts.layout = strdup(tmp_val); + } else if (!strcasecmp(tmp, "rules")) + { + if (!xkb_opts.rules) + xkb_opts.rules = strdup(tmp_val); + } else if (!strcasecmp(tmp, "variant")) + { + if (!xkb_opts.variant) + xkb_opts.variant = strdup(tmp_val); + } else if (!strcasecmp(tmp, "model")) + { + if (!xkb_opts.model) + xkb_opts.model = strdup(tmp_val); } xfree(tmp_val); } @@ -272,6 +326,17 @@ device_added(LibHalContext *hal_ctx, const char *udi) libhal_psi_next(&set_iter); } + + /* Now add xkb options */ + if (xkb_opts.layout) + add_option(&options, "xkb_layout", xkb_opts.layout); + if (xkb_opts.rules) + add_option(&options, "xkb_rules", xkb_opts.rules); + if (xkb_opts.variant) + add_option(&options, "xkb_variant", xkb_opts.variant); + if (xkb_opts.model) + add_option(&options, "xkb_model", xkb_opts.model); + /* this isn't an error, but how else do you output something that the user can see? */ LogMessage(X_INFO, "config/hal: Adding input device %s\n", name); if (NewInputDeviceRequest(options, &dev) != Success) { @@ -304,6 +369,15 @@ unwind: xfree(tmpo); } + if (xkb_opts.layout) + xfree(xkb_opts.layout); + if (xkb_opts.rules) + xfree(xkb_opts.rules); + if (xkb_opts.model) + xfree(xkb_opts.model); + if (xkb_opts.variant) + xfree(xkb_opts.variant); + dbus_error_free(&error); return;