/* * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of Conectiva Linux shall * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from * Conectiva Linux. * * Author: Paulo César Pereira de Andrade * */ #include "xf86config.h" #include "keyboard-cfg.h" #include #include #include #include #include #include #define IS_KBDDRIV(X) ((strcasecmp((X),"kbd") == 0) || \ (strcasecmp((X), "keyboard") == 0)) /* * Types */ typedef struct { char *rules; XkbRF_RulesPtr list; XF86XkbDescInfo model; XF86XkbDescInfo layout; XF86XkbDescInfo variant; XF86XkbDescInfo option; } XF86XkbRulesDescInfo; /* * Prototypes */ static void KeyboardRulesCallback(Widget, XtPointer, XtPointer); static void KeyboardModelCallback(Widget, XtPointer, XtPointer); static void KeyboardLayoutCallback(Widget, XtPointer, XtPointer); static void KeyboardVariantCallback(Widget, XtPointer, XtPointer); static void KeyboardOptionsCallback(Widget, XtPointer, XtPointer); static void KeyboardApplyCallback(Widget, XtPointer, XtPointer); static Bool KeyboardConfigCheck(void); static void XkbUIEventHandler(Widget, XtPointer, XEvent*, Boolean*); static XF86XkbRulesDescInfo *GetXkbRulesDesc(char*); static void UpdateRulesPopups(void); /* * Initialization */ static XF86XkbRulesDescInfo **xkb_desc, *xkb_rules; static int num_xkb_desc; static char *XkbRulesDir = "share/X11/xkb/rules/"; #ifdef XFREE98_XKB static char *XkbRulesFile = "xfree98"; #else static char *XkbRulesFile = __XKBDEFRULES__; #endif static XF86ConfInputPtr current_input; static char *rules, *model, *layout, *variant, *options; static Widget kbd, rulesb, modelb, layoutb, variantb, optionsb, modelp, layoutp, variantp, optionsp; static XkbInfo **xkb_infos; static int num_xkb_infos; XkbInfo *xkb_info; static Widget apply; /* * Implementation */ /*ARGSUSED*/ XtPointer KeyboardConfig(XtPointer config) { XF86ConfInputPtr keyboard = (XF86ConfInputPtr)config; XF86OptionPtr option; Arg args[1]; static char *XkbRules = "XkbRules", *XkbModel = "XkbModel", *XkbLayout = "XkbLayout", *XkbVariant = "XkbVariant", *XkbOptions = "XkbOptions"; XF86XkbRulesDescInfo *info; char *omodel, *olayout, *ovariant, *ooptions; InitializeKeyboard(); rules = xkb_rules->rules; if (xkb_info->config.rules_file == NULL) xkb_info->config.rules_file = rules; if (options) XtFree(options); options = NULL; if (xkb_info->conf == NULL) xkb_info->conf = keyboard; if (xkb_info->conf != keyboard) { int i; for (i = 0; i < num_xkb_infos; i++) if (xkb_infos[i]->conf == keyboard) { xkb_info = xkb_infos[i]; break; } if (i >= num_xkb_infos) { int timeout = 10; xkb_info = (XkbInfo*)XtCalloc(1, sizeof(XkbInfo)); xkb_info->conf = keyboard; xkb_infos = (XkbInfo**) XtRealloc((XtPointer)xkb_infos, sizeof(XkbInfo*) * (num_xkb_infos + 1)); xkb_infos[num_xkb_infos++] = xkb_info; xkb_info->conf = keyboard; bzero((char*)&(xkb_info->defs), sizeof(XkbRF_VarDefsRec)); while (timeout > 0) { xkb_info->xkb = XkbGetKeyboard(XtDisplay(configp), XkbGBN_AllComponentsMask, XkbUseCoreKbd); if (xkb_info->xkb == NULL) { timeout -= 1; sleep(1); } else break; } if (timeout <= 0) { fprintf(stderr, "Couldn't get keyboard\n"); } if (xkb_info->xkb && xkb_info->xkb->names && xkb_info->xkb->geom && xkb_info->xkb->names->geometry == 0) xkb_info->xkb->names->geometry = xkb_info->xkb->geom->name; } /* check for removed devices */ for (i = 0; i < num_xkb_infos; i++) { XF86ConfInputPtr key = XF86Config->conf_input_lst; while (key != NULL) { if (IS_KBDDRIV(key->inp_driver) && xkb_infos[i]->conf == key) break; key = (XF86ConfInputPtr)(key->list.next); } if (xkb_infos[i]->conf != NULL && key == NULL) { XkbFreeKeyboard(xkb_infos[i]->xkb, 0, False); XtFree((XtPointer)xkb_infos[i]); if (--num_xkb_infos > i) memmove(&xkb_infos[i], &xkb_infos[i + 1], (num_xkb_infos - i) * sizeof(XkbInfo*)); } } } current_input = keyboard; if (keyboard != NULL) { if ((option = xf86findOption(keyboard->inp_option_lst, XkbRules)) != NULL) { if (strcmp(rules, option->opt_val)) { XF86XkbRulesDescInfo *info = GetXkbRulesDesc(option->opt_val); if (info) { rules = info->rules; UpdateRulesPopups(); } } } if ((option = xf86findOption(keyboard->inp_option_lst, XkbModel)) != NULL) xkb_info->defs.model = model = option->opt_val; else xkb_info->defs.model = model = xkb_rules->model.name[0]; if ((option = xf86findOption(keyboard->inp_option_lst, XkbLayout)) != NULL) xkb_info->defs.layout = layout = option->opt_val; else xkb_info->defs.layout = layout = xkb_rules->layout.name[0]; if ((option = xf86findOption(keyboard->inp_option_lst, XkbVariant)) != NULL) xkb_info->defs.variant = variant = option->opt_val; else xkb_info->defs.variant = variant = NULL; if ((option = xf86findOption(keyboard->inp_option_lst, XkbOptions)) != NULL) xkb_info->defs.options = options = XtNewString(option->opt_val); else xkb_info->defs.options = options = NULL; XtSetArg(args[0], XtNstring, keyboard->inp_identifier); XtSetValues(ident_widget, args, 1); (void)UpdateKeyboard(False); } else { XF86ConfInputPtr input = XF86Config->conf_input_lst; char keyboard_name[48]; int nkeyboards = 0; while (input != NULL) { if (IS_KBDDRIV(input->inp_driver)) ++nkeyboards; input = (XF86ConfInputPtr)(input->list.next); } do { XmuSnprintf(keyboard_name, sizeof(keyboard_name), "Keyboard%d", nkeyboards); ++nkeyboards; } while (xf86findInput(keyboard_name, XF86Config->conf_input_lst)); model = xkb_rules->model.name[0]; layout = xkb_rules->layout.name[0]; variant = ""; options = XtNewString(""); XtSetArg(args[0], XtNstring, keyboard_name); XtSetValues(ident_widget, args, 1); } info = xkb_rules; omodel = model; olayout = layout; ovariant = variant; ooptions = options ? XtNewString(options) : NULL; xf86info.cur_list = KEYBOARD; XtSetSensitive(back, xf86info.lists[KEYBOARD].cur_function > 0); XtSetSensitive(next, xf86info.lists[KEYBOARD].cur_function < xf86info.lists[KEYBOARD].num_functions - 1); (xf86info.lists[KEYBOARD].functions[xf86info.lists[KEYBOARD].cur_function]) (&xf86info); if (ConfigLoop(KeyboardConfigCheck) == True) { if (keyboard == NULL) { keyboard = XtNew(XF86ConfInputRec); keyboard->list.next = NULL; keyboard->inp_identifier = XtNewString(ident_string); #if defined(USE_DEPRECATED_KEYBOARD_DRIVER) keyboard->inp_driver = XtNewString("keyboard"); #else keyboard->inp_driver = XtNewString("kbd"); #endif keyboard->inp_option_lst = xf86newOption(XtNewString(XkbRules), XtNewString(rules)); xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbModel), XtNewString(model)); xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbLayout), XtNewString(layout)); if (variant && *variant) xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbVariant), XtNewString(variant)); if (options && *options) { xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbOptions), options); options = NULL; } keyboard->inp_comment = NULL; } else { int i; char *str; XtSetArg(args[0], XtNlabel, &str); XtGetValues(modelb, args, 1); for (i = 0; i < xkb_rules->model.nelem; i++) if (strcmp(xkb_rules->model.desc[i], str) == 0) { model = xkb_rules->model.name[i]; break; } XtSetArg(args[0], XtNlabel, &str); XtGetValues(layoutb, args, 1); for (i = 0; i < xkb_rules->layout.nelem; i++) if (strcmp(xkb_rules->layout.desc[i], str) == 0) { layout = xkb_rules->layout.name[i]; break; } if ((option = xf86findOption(keyboard->inp_option_lst, XkbRules)) != NULL) { XtFree(option->opt_val); option->opt_val = XtNewString(rules); XtFree(option->opt_comment); option->opt_comment = NULL; } else keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbRules), XtNewString(rules)); if ((option = xf86findOption(keyboard->inp_option_lst, XkbModel)) != NULL) { XtFree(option->opt_val); option->opt_val = XtNewString(model); XtFree(option->opt_comment); option->opt_comment = NULL; } else keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbModel), XtNewString(model)); XtFree(xkb_info->config.model); xkb_info->config.model = XtNewString(model); if ((option = xf86findOption(keyboard->inp_option_lst, XkbLayout)) != NULL) { XtFree(option->opt_val); option->opt_val = XtNewString(layout); } else keyboard->inp_option_lst = xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbLayout), XtNewString(layout)); XtFree(xkb_info->config.layout); xkb_info->config.layout = XtNewString(layout); if ((option = xf86findOption(keyboard->inp_option_lst, XkbVariant)) != NULL) { if (variant && *variant) { XtFree(option->opt_val); option->opt_val = XtNewString(variant); } else xf86removeOption(&keyboard->inp_option_lst, XkbVariant); } else if (variant && *variant) xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbVariant), XtNewString(variant)); XtFree(xkb_info->config.variant); xkb_info->config.variant = variant && *variant ? XtNewString(variant) : NULL; XtFree(xkb_info->config.options); xkb_info->config.options = options && *options ? XtNewString(options) : NULL; if ((option = xf86findOption(keyboard->inp_option_lst, XkbOptions)) != NULL) { if (options && *options) { XtFree(option->opt_val); option->opt_val = options; options = NULL; } else xf86removeOption(&keyboard->inp_option_lst, XkbOptions); } else if (options && *options) { xf86addNewOption(keyboard->inp_option_lst, XtNewString(XkbOptions), options); options = NULL; } } if (strcasecmp(keyboard->inp_identifier, ident_string)) xf86renameInput(XF86Config, keyboard, ident_string); xkb_info->conf = keyboard; xkb_info->config.rules_file = rules; return ((XtPointer)keyboard); } xkb_rules = info; rules = info->rules; model = omodel; layout = olayout; variant = ovariant; XtFree(options); options = ooptions; return (NULL); } static Bool KeyboardConfigCheck(void) { XF86ConfInputPtr keyboard = XF86Config->conf_input_lst; while (keyboard != NULL) { if (keyboard != current_input && strcasecmp(ident_string, keyboard->inp_identifier) == 0) return (False); keyboard = (XF86ConfInputPtr)(keyboard->list.next); } return (True); } /*ARGSUSED*/ static void XkbUIEventHandler(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch) { XkbUI_ViewOptsRec opts; XkbUI_ViewPtr view; int width, height, bd; if (event->xexpose.count > 1) return; bzero((char *)&opts, sizeof(opts)); bd = 1; opts.present = XkbUI_SizeMask | XkbUI_ColormapMask | XkbUI_MarginMask | XkbUI_OffsetMask; opts.margin_width = opts.margin_height = 0; opts.viewport.x = opts.viewport.y = bd; width = opts.viewport.width = w->core.width - 2 * bd; height = opts.viewport.height = w->core.height - 2 * bd; opts.cmap = w->core.colormap; if ((view = XkbUI_Init(XtDisplay(w), XtWindow(w), width, height, xkb_info->xkb, &opts)) != NULL) { XkbUI_DrawRegion(view, NULL); free(view); } } void InitializeKeyboard(void) { int major, minor, op, event, error; static int first = 1; int timeout = 5; XF86ConfInputPtr keyboard = XF86Config->conf_input_lst; XF86OptionPtr option; char name[PATH_MAX]; FILE *file; if (!first) return; first = 0; major = XkbMajorVersion; minor = XkbMinorVersion; if (XkbQueryExtension(DPY, &op, &event, &error, &major, &minor) == 0) { fprintf(stderr, "Unable to initialize XKEYBOARD extension"); exit(1); } xkb_info = (XkbInfo *)XtCalloc(1, sizeof(XkbInfo)); xkb_info->conf = NULL; xkb_infos = (XkbInfo**)XtCalloc(1, sizeof(XkbInfo*)); num_xkb_infos = 1; xkb_infos[0] = xkb_info; bzero((char*)&(xkb_info->defs), sizeof(XkbRF_VarDefsRec)); while (timeout > 0) { xkb_info->xkb = XkbGetKeyboard(DPY, XkbGBN_AllComponentsMask, XkbUseCoreKbd); if (xkb_info->xkb == NULL) { timeout -= 1; sleep(1); } else break; } if (timeout <= 0) { fprintf(stderr, "Couldn't get keyboard\n"); } if (xkb_info->xkb && xkb_info->xkb->names && xkb_info->xkb->geom && xkb_info->xkb->names->geometry == 0) xkb_info->xkb->names->geometry = xkb_info->xkb->geom->name; /* Load configuration */ XmuSnprintf(name, sizeof(name), "%s%s", XkbConfigDir, XkbConfigFile); file = fopen(name, "r"); if (file != NULL) { if (XkbCFParse(file, XkbCFDflts, xkb_info->xkb, &xkb_info->config) == 0) { fprintf(stderr, "Error parsing config file: "); XkbCFReportError(stderr, name, xkb_info->config.error, xkb_info->config.line); } fclose(file); } xkb_rules = GetXkbRulesDesc(xkb_info->config.rules_file != NULL ? xkb_info->config.rules_file : XkbRulesFile); if (xkb_rules == NULL) /* error message was printed */ exit(1); /* XXX Assumes the first keyboard is the core keyboard */ while (keyboard != NULL) { if (IS_KBDDRIV(keyboard->inp_driver)) break; keyboard = (XF86ConfInputPtr)(keyboard->list.next); } if (keyboard == NULL) return; if (xkb_info->config.rules_file != NULL) rules = xkb_info->config.rules_file; else if ((option = xf86findOption(keyboard->inp_option_lst, "XkbRules")) != NULL) rules = option->opt_val; else rules = XkbRulesFile; if (strcmp(rules, xkb_rules->rules)) { xkb_rules = GetXkbRulesDesc(rules); if (xkb_rules == NULL) /* error message was printed */ exit(1); } { FILE *fp; char filename[1024]; XmuSnprintf(filename, sizeof(filename), "%s%s", XkbRulesDir, xkb_rules->rules); if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "Can't open rules file\n"); exit(1); } if (!XkbRF_LoadRules(fp, xkb_rules->list)) { fclose(fp); fprintf(stderr, "Can't load rules\n"); exit(1); } fclose(fp); } if (xkb_info->config.rules_file == NULL) xkb_info->config.rules_file = xkb_rules->rules; if (xkb_info->config.model != NULL) xkb_info->defs.model = xkb_info->config.model; else if ((option = xf86findOption(keyboard->inp_option_lst, "XkbModel")) != NULL) xkb_info->defs.model = option->opt_val; else xkb_info->defs.model = xkb_rules->model.name[0]; if (xkb_info->config.layout != NULL) xkb_info->defs.layout = xkb_info->config.layout; else if ((option = xf86findOption(keyboard->inp_option_lst, "XkbLayout")) != NULL) xkb_info->defs.layout = option->opt_val; else xkb_info->defs.layout = xkb_rules->layout.name[0]; if (xkb_info->config.variant != NULL) xkb_info->defs.variant = xkb_info->config.variant; else if ((option = xf86findOption(keyboard->inp_option_lst, "XkbVariant")) != NULL) xkb_info->defs.variant = option->opt_val; else xkb_info->defs.variant = NULL; if (xkb_info->config.options != NULL) xkb_info->defs.options = xkb_info->config.options; else if ((option = xf86findOption(keyboard->inp_option_lst, "XkbOptions")) != NULL) xkb_info->defs.options = option->opt_val; else xkb_info->defs.options = NULL; if (xkb_info->xkb == NULL) { /* Try again */ XkbComponentNamesRec comps; bzero((char*)&comps, sizeof(XkbComponentNamesRec)); XkbRF_GetComponents(xkb_rules->list, &(xkb_info->defs), &comps); xkb_info->xkb = XkbGetKeyboardByName(DPY, XkbUseCoreKbd, &comps, XkbGBN_AllComponentsMask, 0, 0); } } static XF86XkbRulesDescInfo * GetXkbRulesDesc(char *rules) { int i; XkbRF_RulesPtr list; char filename[1024]; XF86XkbRulesDescInfo *info; if (rules == NULL) return (NULL); for (i = 0; i < num_xkb_desc; i++) if (strcmp(rules, xkb_desc[i]->rules) == 0) return (xkb_desc[i]); XmuSnprintf(filename, sizeof(filename), "%s%s", XkbRulesDir, rules); if ((list = XkbRF_Create(0, 0)) == NULL || !XkbRF_LoadDescriptionsByName(filename, NULL, list)) { fprintf(stderr, "Can't create rules structure\n"); return (NULL); } info = (XF86XkbRulesDescInfo*)XtCalloc(1, sizeof(XF86XkbRulesDescInfo)); xkb_desc = (XF86XkbRulesDescInfo**) XtRealloc((XtPointer)xkb_desc, sizeof(XF86XkbRulesDescInfo*) * (num_xkb_desc + 1)); xkb_desc[num_xkb_desc++] = info; info->rules = XtNewString(rules); for (i = 0; i < list->models.num_desc; i++) { if (i % 16 == 0) { info->model.name = (char**)XtRealloc((XtPointer)info->model.name, (i + 16) * sizeof(char*)); info->model.desc = (char**)XtRealloc((XtPointer)info->model.desc, (i + 16) * sizeof(char*)); } info->model.name[i] = XtNewString(list->models.desc[i].name); info->model.desc[i] = XtNewString(list->models.desc[i].desc); } info->model.nelem = i; for (i = 0; i < list->layouts.num_desc; i++) { if (i % 16 == 0) { info->layout.name = (char**)XtRealloc((XtPointer)info->layout.name, (i + 16) * sizeof(char*)); info->layout.desc = (char**)XtRealloc((XtPointer)info->layout.desc, (i + 16) * sizeof(char*)); } info->layout.name[i] = XtNewString(list->layouts.desc[i].name); info->layout.desc[i] = XtNewString(list->layouts.desc[i].desc); } info->layout.nelem = i; for (i = 0; i < list->variants.num_desc; i++) { if (i % 16 == 0) { info->variant.name = (char**)XtRealloc((XtPointer)info->variant.name, (i + 16) * sizeof(char*)); info->variant.desc = (char**)XtRealloc((XtPointer)info->variant.desc, (i + 16) * sizeof(char*)); } info->variant.name[i] = XtNewString(list->variants.desc[i].name); info->variant.desc[i] = XtNewString(list->variants.desc[i].desc); } info->variant.nelem = i; for (i = 0; i < list->options.num_desc; i++) { if (i % 16 == 0) { info->option.name = (char**)XtRealloc((XtPointer)info->option.name, (i + 16) * sizeof(char*)); info->option.desc = (char**)XtRealloc((XtPointer)info->option.desc, (i + 16) * sizeof(char*)); } info->option.name[i] = XtNewString(list->options.desc[i].name); info->option.desc[i] = XtNewString(list->options.desc[i].desc); } info->option.nelem = i; info->list = list; return (info); } static xf86ConfigSymTabRec ax_controls[] = { {XkbRepeatKeysMask, "RepeatKeys"}, {XkbSlowKeysMask, "SlowKeys"}, {XkbBounceKeysMask, "BounceKeys"}, {XkbStickyKeysMask, "StickyKeys"}, {XkbMouseKeysMask, "MouseKeys"}, {XkbMouseKeysAccelMask, "MouseKeysAccel"}, {XkbAccessXKeysMask, "AccessxKeys"}, {XkbAccessXTimeoutMask, "AccessxTimeout"}, {XkbAccessXFeedbackMask, "AccessxFeedback"}, {XkbAudibleBellMask, "AudibleBell"}, {XkbOverlay1Mask, "Overlay1"}, {XkbOverlay2Mask, "Overlay2"}, {XkbIgnoreGroupLockMask, "IgnoreGroupLock"}, {-1, ""}, }; static xf86ConfigSymTabRec ax_feedback[] = { {XkbAX_SKPressFBMask, "SlowKeysPress"}, {XkbAX_SKAcceptFBMask, "SlowKeysAccept"}, {XkbAX_FeatureFBMask, "Feature"}, {XkbAX_SlowWarnFBMask, "SlowWarn"}, {XkbAX_IndicatorFBMask, "Indicator"}, {XkbAX_StickyKeysFBMask, "StickyKeys"}, {XkbAX_TwoKeysMask, "TwoKeys"}, {XkbAX_LatchToLockMask, "LatchToLock"}, {XkbAX_SKReleaseFBMask, "SlowKeysRelease"}, {XkbAX_SKRejectFBMask, "SlowkeysReject"}, {XkbAX_BKRejectFBMask, "BounceKeysReject"}, {XkbAX_DumbBellFBMask, "DumbBell"}, {-1, ""}, }; Bool WriteXKBConfiguration(char *filename, XkbConfigRtrnPtr conf) { FILE *fp; int i, count; if (filename == NULL || conf == NULL || (fp = fopen(filename, "w")) == NULL) return (False); if (conf->rules_file != NULL) fprintf(fp, "Rules = \"%s\"\n", conf->rules_file); if (conf->model != NULL) fprintf(fp, "Model = \"%s\"\n", conf->model); if (conf->layout != NULL) fprintf(fp, "Layout = \"%s\"\n", conf->layout); if (conf->variant != NULL) fprintf(fp, "Variant = \"%s\"\n", conf->variant); if (conf->options != NULL) fprintf(fp, "Options = \"%s\"\n", conf->options); if (conf->keymap != NULL) fprintf(fp, "Keymap = %s\n", conf->keymap); if (conf->keycodes != NULL) fprintf(fp, "Keycodes = %s\n", conf->keycodes); if (conf->geometry != NULL) fprintf(fp, "Geometry = %s\n", conf->geometry); if (conf->phys_symbols != NULL) fprintf(fp, "RealSymbols = %s\n", conf->phys_symbols); if (conf->symbols != NULL) fprintf(fp, "Symbols = %s\n", conf->symbols); if (conf->types != NULL) fprintf(fp, "Types = %s\n", conf->types); if (conf->compat != NULL) fprintf(fp, "Compat = %s\n", conf->compat); if (conf->click_volume > 0) fprintf(fp, "ClickVolume = %d\n", conf->click_volume); if (conf->bell_volume > 0) fprintf(fp, "BellVolume = %d\n", conf->bell_volume); if (conf->bell_pitch > 0) fprintf(fp, "BellPitch = %d\n", conf->bell_pitch); if (conf->bell_duration > 0) fprintf(fp, "BellDuration = %d\n", conf->bell_duration); if (conf->repeat_delay > 0) fprintf(fp, "RepeatDelay = %d\n", conf->repeat_delay); if (conf->repeat_interval > 0) fprintf(fp, "RepeatInterval = %d\n", conf->repeat_interval); if (conf->slow_keys_delay > 0) fprintf(fp, "SlowKeysDelay = %d\n", conf->slow_keys_delay); if (conf->debounce_delay > 0) fprintf(fp, "DebounceDelay = %d\n", conf->debounce_delay); if (conf->mk_delay > 0) fprintf(fp, "MouseKeysDelay = %d\n", conf->mk_delay); if (conf->mk_interval > 0) fprintf(fp, "MouseKeysInterval = %d\n", conf->mk_interval); if (conf->mk_time_to_max > 0) fprintf(fp, "MouseKeysTimeToMax = %d\n", conf->mk_time_to_max); if (conf->mk_max_speed > 0) fprintf(fp, "MouseKeysMaxSpeed = %d\n", conf->mk_max_speed); fprintf(fp, "MouseKeysCurve = %d\n", conf->mk_curve); if (conf->ax_timeout) fprintf(fp, "AccessXTimeout = %d\n", conf->ax_timeout); if (conf->initial_ctrls != 0) { fprintf(fp, "Controls %c= ", conf->replace_initial_ctrls ? ' ' : '+'); for (i = count = 0; *ax_controls[i].name; i++) if ((conf->initial_ctrls & ax_controls[i].token) == ax_controls[i].token) fprintf(fp, "%s%s", count++ ? " + " : "", ax_controls[i].name); fprintf(fp, "\n"); } if (conf->axt_ctrls_on != 0) { fprintf(fp, "AcessXTimeoutCtrlsOn %c= ", conf->replace_axt_ctrls_on ? ' ' : '+'); for (i = count = 0; *ax_controls[i].name; i++) if ((conf->axt_ctrls_on & ax_controls[i].token) == ax_controls[i].token) fprintf(fp, "%s%s", count++ ? " + " : "", ax_controls[i].name); fprintf(fp, "\n"); } if (conf->axt_ctrls_off != 0) { fprintf(fp, "AcessXTimeoutCtrlsOff %c= ", conf->replace_axt_ctrls_off ? ' ' : '-'); for (i = count = 0; *ax_controls[i].name; i++) if ((conf->axt_ctrls_off & ax_controls[i].token) == ax_controls[i].token) fprintf(fp, "%s%s", count++ ? " + " : "", ax_controls[i].name); fprintf(fp, "\n"); } if (conf->initial_opts != 0) { fprintf(fp, "Feedback %c= ", conf->replace_initial_opts ? ' ' : '+'); for (i = count = 0; *ax_feedback[i].name; i++) if ((conf->initial_opts & ax_feedback[i].token) == ax_feedback[i].token) fprintf(fp, "%s%s", count++ ? " + " : "", ax_feedback[i].name); fprintf(fp, "\n"); } if (conf->axt_opts_on != 0) { fprintf(fp, "AcessXTimeoutFeedbackOn %c= ", conf->replace_axt_opts_on ? ' ' : '+'); for (i = count = 0; *ax_controls[i].name; i++) if ((conf->axt_opts_on & ax_feedback[i].token) == ax_feedback[i].token) fprintf(fp, "%s%s", count++ ? " + " : "", ax_feedback[i].name); fprintf(fp, "\n"); } if (conf->axt_opts_off != 0) { fprintf(fp, "AcessXTimeoutFeedbackOff%c= ", conf->replace_axt_opts_off ? ' ' : '-'); for (i = count = 0; *ax_feedback[i].name; i++) if ((conf->axt_opts_off & ax_feedback[i].token) == ax_feedback[i].token) fprintf(fp, "%s%s", count++ ? " + " : "", ax_feedback[i].name); fprintf(fp, "\n"); } fclose(fp); return (True); } Bool UpdateKeyboard(Bool load) { XkbComponentNamesRec comps; XkbDescPtr xkb; bzero((char*)&comps, sizeof(XkbComponentNamesRec)); XkbRF_GetComponents(xkb_rules->list, &(xkb_info->defs), &comps); xkb = XkbGetKeyboardByName(DPY, XkbUseCoreKbd, &comps, XkbGBN_AllComponentsMask, 0, load); if (xkb == NULL || xkb->geom == NULL) { fprintf(stderr, "Couldn't get keyboard\n"); return (False); } if (xkb_info->xkb && xkb_info->xkb->names && xkb_info->xkb->geom && xkb_info->xkb->names->geometry == 0) xkb_info->xkb->names->geometry = xkb_info->xkb->geom->name; XkbFreeKeyboard(xkb_info->xkb, 0, False); xkb_info->xkb = xkb; XtFree(comps.keymap); XtFree(comps.keycodes); XtFree(comps.compat); XtFree(comps.types); XtFree(comps.symbols); XtFree(comps.geometry); if (kbd != NULL) XClearArea(XtDisplay(configp), XtWindow(kbd), 0, 0, 0, 0, True); return (True); } static void KeyboardRulesCallback(Widget w, XtPointer user_data, XtPointer call_data) { int i; FILE *fp; Arg args[1]; char filename[1024], *omodel, *olayout, *ovariant, *ooptions, *dmodel, *dlayout, *dvariant; XF86XkbRulesDescInfo *oxkb_rules, *info = GetXkbRulesDesc(XtName(w)); if (strcmp(XtName(w), rules) == 0 || info == NULL) /* a error message was printed */ return; XmuSnprintf(filename, sizeof(filename), "%s%s", XkbRulesDir, info->rules); if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "Can't open rules file\n"); return; } if (!XkbRF_LoadRules(fp, info->list)) { fclose(fp); fprintf(stderr, "Can't load rules\n"); return; } fclose(fp); oxkb_rules = xkb_rules; omodel = xkb_info->defs.model; olayout = xkb_info->defs.layout; ovariant = xkb_info->defs.variant; ooptions = xkb_info->defs.options; if (omodel) { for (i = 0; i < info->model.nelem; i++) { if (strcmp(omodel, info->model.name[i]) == 0) break; } } else i = 0; model = xkb_info->defs.model = info->model.name [i < info->model.nelem ? i : 0]; dmodel = info->model.desc[i < info->model.nelem ? i : 0]; if (olayout) { for (i = 0; i < info->layout.nelem; i++) { if (strcmp(olayout, info->layout.name[i]) == 0) break; } } else i = 0; layout = xkb_info->defs.layout = info->layout.name [i < info->layout.nelem ? i : 0]; dlayout = info->layout.desc[i < info->layout.nelem ? i : 0]; if (ovariant) { for (i = 0; i < info->variant.nelem; i++) { if (strcmp(ovariant, info->variant.name[i]) == 0) break; } } else i = info->variant.nelem; variant = xkb_info->defs.variant = i < info->variant.nelem ? info->variant.name[i] : NULL; dvariant = i < info->variant.nelem ? info->variant.desc[i] : NULL; if (ooptions) { char *ptr, *tmp = XtNewString(options); for (ptr = strtok(tmp, ","); ptr != NULL; ptr = strtok(NULL, ",")) { if (strchr(ptr, ':') == NULL) continue; for (i = 0; i < xkb_rules->option.nelem; i++) if (strcmp(xkb_rules->option.name[i], ptr) == 0) break; if (i == xkb_rules->option.nelem) { XtFree(options); options = NULL; /* no option with the same name */ break; } } XtFree(tmp); } else { XtFree(options); options = NULL; } oxkb_rules = xkb_rules; xkb_rules = info; rules = info->rules; if (!UpdateKeyboard(False)) { model = xkb_info->defs.model = omodel; layout = xkb_info->defs.layout = olayout; variant = xkb_info->defs.variant = ovariant; options = XtNewString(xkb_info->defs.options = ooptions); xkb_rules = oxkb_rules; rules = xkb_rules->rules; XmuSnprintf(filename, sizeof(filename), "%s%s", XkbRulesDir, rules); if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "Can't open rules file\n"); return; } if (!XkbRF_LoadRules(fp, xkb_rules->list)) { fprintf(stderr, "Can't load rules\n"); } fclose(fp); return; } UpdateRulesPopups(); XtSetArg(args[0], XtNlabel, rules); XtSetValues(rulesb, args, 1); XtSetArg(args[0], XtNlabel, dmodel); XtSetValues(modelb, args, 1); XtSetArg(args[0], XtNlabel, dlayout); XtSetValues(layoutb, args, 1); XtSetArg(args[0], XtNlabel, dvariant ? dvariant : ""); XtSetValues(variantb, args, 1); XtSetArg(args[0], XtNlabel, options ? options : ""); XtSetValues(variantb, args, 1); } static void KeyboardModelCallback(Widget w, XtPointer user_data, XtPointer call_data) { Arg args[1]; int i; char *oldval = xkb_info->defs.model; for (i = 0; i < xkb_rules->model.nelem; i++) if (strcmp(XtName(w), xkb_rules->model.name[i]) == 0) break; model = xkb_info->defs.model = xkb_rules->model.name[i]; if (!UpdateKeyboard(False)) model = xkb_info->defs.model = oldval; else { XtSetArg(args[0], XtNlabel, xkb_rules->model.desc[i]); XtSetValues(modelb, args, 1); } } static void KeyboardLayoutCallback(Widget w, XtPointer user_data, XtPointer call_data) { Arg args[1]; int i; char *oldval = xkb_info->defs.layout; for (i = 0; i < xkb_rules->layout.nelem; i++) if (strcmp(XtName(w), xkb_rules->layout.name[i]) == 0) break; layout = xkb_info->defs.layout = xkb_rules->layout.name[i]; if (!UpdateKeyboard(False)) layout = xkb_info->defs.layout = oldval; else { XtSetArg(args[0], XtNlabel, xkb_rules->layout.desc[i]); XtSetValues(layoutb, args, 1); } } static void KeyboardVariantCallback(Widget w, XtPointer user_data, XtPointer call_data) { Arg args[1]; int i; char *label, *oldval = xkb_info->defs.variant; for (i = 0; i < xkb_rules->variant.nelem; i++) if (strcmp(XtName(w), xkb_rules->variant.name[i]) == 0) break; variant = i < xkb_rules->variant.nelem ? xkb_rules->variant.name[i] : ""; xkb_info->defs.variant = variant && *variant ? variant : NULL; if (!UpdateKeyboard(False)) xkb_info->defs.variant = variant = oldval; else { label = i < xkb_rules->variant.nelem ? xkb_rules->variant.desc[i] : ""; XtSetArg(args[0], XtNlabel, label); XtSetValues(variantb, args, 1); } } static void KeyboardOptionsCallback(Widget w, XtPointer user_data, XtPointer call_data) { Arg args[1]; int i; for (i = 0; i < xkb_rules->option.nelem; i++) if (strcmp(XtName(w), xkb_rules->option.name[i]) == 0) break; if (i < xkb_rules->option.nelem) { char *delim, *ptr, str[256]; /* remove old string, don't check if the same */ if ((delim = strchr(XtName(w), ':')) != NULL) { if (delim - XtName(w) >= sizeof(str) - 2) return; strncpy(str, XtName(w), delim - XtName(w) + 1); str[delim - XtName(w) + 1] = '\0'; } else XmuSnprintf(str, sizeof(str), "%s:", XtName(w)); if (options && (delim = strstr(options, str)) != NULL) { if ((ptr = strchr(delim, ',')) != NULL) { *delim = *ptr = '\0'; XmuSnprintf(str, sizeof(str), "%s%s", options, ptr + 1); XtFree(options); options = XtNewString(str); } else { if (delim > options) delim[-1] = '\0'; else delim[0] = '\0'; } } /* update string, if required */ if ((delim = strchr(XtName(w), ':')) != NULL) { if (options && *options) XmuSnprintf(str, sizeof(str), "%s,%s", options, XtName(w)); else XmuSnprintf(str, sizeof(str), "%s", XtName(w)); XtFree(options); options = XtNewString(str); } } else { XtFree(options); options = XtNewString(""); } if (options == NULL) options = XtNewString(""); xkb_info->defs.options = options; if (!UpdateKeyboard(False)) { *options = '\0'; xkb_info->defs.options = NULL; } XtSetArg(args[0], XtNlabel, options); XtSetValues(optionsb, args, 1); XtSetArg(args[0], XtNtip, options); XtSetValues(optionsb, args, 1); } /*ARGSUSED*/ static void KeyboardApplyCallback(Widget w, XtPointer user_data, XtPointer call_data) { (void)UpdateKeyboard(True); } static void UpdateRulesPopups(void) { int i; char *optname; Widget sme, optpopup = NULL, optparent; /* MODEL */ if (modelp) XtDestroyWidget(modelp); modelp = XtCreatePopupShell("modelP", simpleMenuWidgetClass, modelb, NULL, 0); for (i = 0; i < xkb_rules->model.nelem; i++) { sme = XtVaCreateManagedWidget(xkb_rules->model.name[i], smeBSBObjectClass, modelp, XtNlabel, xkb_rules->model.desc[i], NULL); XtAddCallback(sme, XtNcallback, KeyboardModelCallback, NULL); } /* LAYOUT */ if (layoutp) XtDestroyWidget(layoutp); layoutp = XtCreatePopupShell("layoutP", simpleMenuWidgetClass, layoutb, NULL, 0); for (i = 0; i < xkb_rules->layout.nelem; i++) { sme = XtVaCreateManagedWidget(xkb_rules->layout.name[i], smeBSBObjectClass, layoutp, XtNlabel, xkb_rules->layout.desc[i], NULL); XtAddCallback(sme, XtNcallback, KeyboardLayoutCallback, NULL); } /* VARIANT */ if (variantp) XtDestroyWidget(variantp); variantp = XtCreatePopupShell("variantP", simpleMenuWidgetClass, variantb, NULL, 0); sme = XtVaCreateManagedWidget("None", smeBSBObjectClass, variantp, XtNlabel, "None", NULL); XtAddCallback(sme, XtNcallback, KeyboardVariantCallback, NULL); for (i = 0; i < xkb_rules->variant.nelem; i++) { sme = XtVaCreateManagedWidget(xkb_rules->variant.name[i], smeBSBObjectClass, variantp, XtNlabel, xkb_rules->variant.desc[i], NULL); XtAddCallback(sme, XtNcallback, KeyboardVariantCallback, NULL); } /* OPTIONS */ if (optionsp) XtDestroyWidget(optionsp); optionsp = XtCreatePopupShell("optionsP", simpleMenuWidgetClass, optionsb, NULL, 0); sme = XtVaCreateManagedWidget("None", smeBSBObjectClass, optionsp, XtNlabel, "None", NULL); XtAddCallback(sme, XtNcallback, KeyboardOptionsCallback, NULL); optparent = optionsp; optname = NULL; for (i = 0; i < xkb_rules->option.nelem; i++) { if (!strchr(xkb_rules->option.name[i], ':')) { optpopup = XtCreatePopupShell(optname = xkb_rules->option.desc[i], simpleMenuWidgetClass, optparent = optionsp, NULL, 0); sme = XtVaCreateManagedWidget(xkb_rules->option.name[i], smeBSBObjectClass, optpopup, XtNlabel, "None", NULL); XtAddCallback(sme, XtNcallback, KeyboardOptionsCallback, NULL); } else { optparent = optpopup; optname = NULL; } sme = XtVaCreateManagedWidget(xkb_rules->option.name[i], smeBSBObjectClass, optparent, XtNlabel, xkb_rules->option.desc[i], XtNmenuName, optname, XtNleftBitmap, optname ? menuPixmap : None, NULL); if (optparent != optionsp) XtAddCallback(sme, XtNcallback, KeyboardOptionsCallback, NULL); } } void KeyboardModelAndLayout(XF86SetupInfo *info) { static int first = 1; static Widget kbdml; Arg args[1]; int i; if (first) { Widget popup, sme; first = 0; kbdml = XtCreateWidget("keyboardML", formWidgetClass, configp, NULL, 0); /* RULES */ XtCreateManagedWidget("labelR", labelWidgetClass, kbdml, NULL, 0); rulesb = XtVaCreateManagedWidget("rules", menuButtonWidgetClass, kbdml, XtNmenuName, "rulesP", NULL); popup = XtCreatePopupShell("rulesP", simpleMenuWidgetClass, rulesb, NULL, 0); { struct dirent *ent; DIR *dir; if ((dir = opendir(XkbRulesDir)) != NULL) { (void)readdir(dir); (void)readdir(dir); while ((ent = readdir(dir)) != NULL) { if (strchr(ent->d_name, '.')) continue; sme = XtVaCreateManagedWidget(ent->d_name, smeBSBObjectClass, popup, XtNlabel, ent->d_name, NULL); XtAddCallback(sme, XtNcallback, KeyboardRulesCallback, NULL); } closedir(dir); } } /* MODEL */ XtCreateManagedWidget("labelM", labelWidgetClass, kbdml, NULL, 0); modelb = XtVaCreateManagedWidget("model", menuButtonWidgetClass, kbdml, XtNmenuName, "modelP", NULL); /* LAYOUT */ XtCreateManagedWidget("labelL", labelWidgetClass, kbdml, NULL, 0); layoutb = XtVaCreateManagedWidget("layout", menuButtonWidgetClass, kbdml, XtNmenuName, "layoutP", XtNlabel, xkb_rules->layout.desc[0], NULL); /* VARIANT */ XtCreateManagedWidget("labelV", labelWidgetClass, kbdml, NULL, 0); variantb = XtVaCreateManagedWidget("variant", menuButtonWidgetClass, kbdml, XtNmenuName, "variantP", XtNlabel, "", NULL); /* OPTIONS */ XtCreateManagedWidget("labelO", labelWidgetClass, kbdml, NULL, 0); optionsb = XtVaCreateManagedWidget("options", menuButtonWidgetClass, kbdml, XtNmenuName, "optionsP", XtNlabel, "", NULL); UpdateRulesPopups(); kbd = XtCreateManagedWidget("keyboard", coreWidgetClass, kbdml, NULL, 0); apply = XtCreateManagedWidget("apply", commandWidgetClass, kbdml, NULL, 0); XtAddCallback(apply, XtNcallback, KeyboardApplyCallback, NULL); XtRealizeWidget(kbdml); XtAddEventHandler(kbd, ExposureMask, False, XkbUIEventHandler, NULL); /* Force the first update */ XClearArea(XtDisplay(kbd), XtWindow(kbd), 0, 0, 0, 0, True); } XtSetArg(args[0], XtNlabel, xkb_rules->rules); XtSetValues(rulesb, args, 1); for (i = 0; i < xkb_rules->model.nelem; i++) if (strcmp(model, xkb_rules->model.name[i]) == 0) { XtSetArg(args[0], XtNlabel, xkb_rules->model.desc[i]); XtSetValues(modelb, args, 1); break; } for (i = 0; i < xkb_rules->layout.nelem; i++) if (strcmp(layout, xkb_rules->layout.name[i]) == 0) { XtSetArg(args[0], XtNlabel, xkb_rules->layout.desc[i]); XtSetValues(layoutb, args, 1); break; } if (variant) for (i = 0; i < xkb_rules->variant.nelem; i++) if (strcmp(variant, xkb_rules->variant.name[i]) == 0) { XtSetArg(args[0], XtNlabel, xkb_rules->variant.desc[i]); XtSetValues(variantb, args, 1); break; } if (options) { XtSetArg(args[0], XtNlabel, options); XtSetValues(optionsb, args, 1); } XtChangeManagedSet(¤t, 1, NULL, NULL, &kbdml, 1); current = kbdml; }