void init_modifier_keys() { int i, k = 0; int min_keycode, max_keycode, keysyms_per_keycode = 0; std::list<KeySym> Mod1MaskSyms, Mod2MaskSyms, Mod3MaskSyms, Mod4MaskSyms, Mod5MaskSyms; gXNumLockMask = 0; XModifierKeymap *map = XGetModifierMapping(XimServer::gDpy); XDisplayKeycodes(XimServer::gDpy, &min_keycode, &max_keycode); KeySym *sym = XGetKeyboardMapping(XimServer::gDpy, static_cast<KeyCode>(min_keycode), (max_keycode - min_keycode + 1), &keysyms_per_keycode); for (i = 0; i < 8; i++) { int j; for (j = 0; j < map->max_keypermod; j++) { if (map->modifiermap[k]) { KeySym ks; int index = 0; do { ks = XkbKeycodeToKeysym(XimServer::gDpy, map->modifiermap[k], 0, index); index++; } while (!ks && index < keysyms_per_keycode); switch (i) { case ShiftMapIndex: break; case LockMapIndex: break; case ControlMapIndex: break; case Mod1MapIndex: Mod1MaskSyms.push_back(ks); break; case Mod2MapIndex: Mod2MaskSyms.push_back(ks); break; case Mod3MapIndex: Mod3MaskSyms.push_back(ks); break; case Mod4MapIndex: Mod4MaskSyms.push_back(ks); break; case Mod5MapIndex: Mod5MaskSyms.push_back(ks); break; default: break; } // Check NumLock key if (ks == XK_Num_Lock) gXNumLockMask |= (1 << i); } k++; } } XFreeModifiermap(map); XFree(sym); gMod1Mask = check_modifier(Mod1MaskSyms); gMod2Mask = check_modifier(Mod2MaskSyms); gMod3Mask = check_modifier(Mod3MaskSyms); gMod4Mask = check_modifier(Mod4MaskSyms); gMod5Mask = check_modifier(Mod5MaskSyms); if (uim_scm_c_bool(uim_scm_callf("require-dynlib", "s", "xkb"))) uim_scm_callf("%xkb-set-display", "p", XimServer::gDpy); #if UIM_XIM_USE_JAPANESE_KANA_KEYBOARD_HACK // Init at here to sync with proper update timing although not a modifier. uim_x_kana_input_hack_init(XimServer::gDpy); #endif }
/*! * \param[in,out] sc Selection collection to registered the method to. * \param[in] name Name under which the method should be registered. * \param[in] method Method to register. * \returns 0 on success, EINVAL if there was something wrong with the * method. * * \p name does not need to match the name of the method, and the same * method can be registered multiple times under different names. * If \p name equals some previously registered name, * an error message is printed and the method is not registered. * * The function also performs some sanity checking on the input method, * and refuses to register it if there are problems. * Some problems only generate warnings. * All problems are described to \p stderr. */ int gmx_ana_selmethod_register(struct gmx_ana_selcollection_t *sc, const char *name, gmx_ana_selmethod_t *method) { gmx_bool bOk; /* Check the method */ if (method->flags & SMETH_MODIFIER) { bOk = check_modifier(stderr, method, sc->symtab); } else { bOk = check_method(stderr, method, sc->symtab); } /* Try to register the method if everything is ok */ if (bOk) { if (!_gmx_sel_add_method_symbol(sc->symtab, name, method)) { bOk = FALSE; } } if (!bOk) { report_error(stderr, name, "warning: not registered"); return EINVAL; } return 0; }
/*! * \param[in,out] symtab Symbol table to register the method to. * \param[in] name Name under which the method should be registered. * \param[in] method Method to register. * \returns 0 on success, -1 if there was something wrong with the * method. * * \p name does not need to match the name of the method, and the same * method can be registered multiple times under different names. * If \p name equals some previously registered name, * an error message is printed and the method is not registered. * * The function also performs some sanity checking on the input method, * and refuses to register it if there are problems. * Some problems only generate warnings. * All problems are described to \p stderr. */ int gmx_ana_selmethod_register(gmx::SelectionParserSymbolTable *symtab, const char *name, gmx_ana_selmethod_t *method) { bool bOk; /* Check the method */ if (method->flags & SMETH_MODIFIER) { bOk = check_modifier(stderr, method, *symtab); } else { bOk = check_method(stderr, method, *symtab); } /* Try to register the method if everything is ok */ if (bOk) { try { symtab->addMethod(name, method); } catch (const gmx::APIError &ex) { report_error(stderr, name, ex.what()); bOk = false; } } if (!bOk) { report_error(stderr, name, "warning: not registered"); return -1; } return 0; }
static void x_reset_modifier_mapping(Display * display) { int modifier_index, modifier_key, column, mkpm; int meta_bit = 0; int hyper_bit = 0; int super_bit = 0; int alt_bit = 0; int mode_bit = 0; XModifierKeymap *x_modifier_keymap; #define modwarn(name,old,other) \ wwarning(_("%s (0x%x) generates %s which is generated by %s"), \ name, code, index_to_name (old), other) #define modbarf(name,other) \ wwarning(_("%s (0x%x) generates %s which is nonsensical"), \ name, code, other) #define check_modifier(name,mask) \ if ((1<<modifier_index) != mask) \ wwarning(_("%s (0x%x) generates %s which is nonsensical"), \ name, code, index_to_name (modifier_index)) #define store_modifier(name,old) \ if (old && old != modifier_index) \ wwarning(_("%s (0x%x) generates both %s and %s which is nonsensical"), \ name, code, index_to_name (old), \ index_to_name (modifier_index)); \ if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \ else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \ else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \ else if (sym == XK_Mode_switch) \ mode_bit = modifier_index; /* Mode_switch is special, see below... */ \ else if (modifier_index == meta_bit && old != meta_bit) \ modwarn (name, meta_bit, "Meta"); \ else if (modifier_index == super_bit && old != super_bit) \ modwarn (name, super_bit, "Super"); \ else if (modifier_index == hyper_bit && old != hyper_bit) \ modwarn (name, hyper_bit, "Hyper"); \ else if (modifier_index == alt_bit && old != alt_bit) \ modwarn (name, alt_bit, "Alt"); \ else \ old = modifier_index; x_modifier_keymap = XGetModifierMapping(display); if (x_modifier_keymap == NULL) { wwarning(_("XGetModifierMapping returned NULL, there is no modifier or no memory")); return; } mkpm = x_modifier_keymap->max_keypermod; for (modifier_index = 0; modifier_index < 8; modifier_index++) for (modifier_key = 0; modifier_key < mkpm; modifier_key++) { KeySym last_sym = 0; for (column = 0; column < 4; column += 2) { KeyCode code = x_modifier_keymap->modifiermap[modifier_index * mkpm + modifier_key]; KeySym sym; if (code) { if (xext_xkb_supported) sym = XkbKeycodeToKeysym(display, code, 0, column); else sym = XKeycodeToKeysym(display, code, column); } else { sym = NoSymbol; } if (sym == last_sym) continue; last_sym = sym; switch (sym) { case XK_Mode_switch: store_modifier("Mode_switch", mode_bit); break; case XK_Meta_L: store_modifier("Meta_L", meta_bit); break; case XK_Meta_R: store_modifier("Meta_R", meta_bit); break; case XK_Super_L: store_modifier("Super_L", super_bit); break; case XK_Super_R: store_modifier("Super_R", super_bit); break; case XK_Hyper_L: store_modifier("Hyper_L", hyper_bit); break; case XK_Hyper_R: store_modifier("Hyper_R", hyper_bit); break; case XK_Alt_L: store_modifier("Alt_L", alt_bit); break; case XK_Alt_R: store_modifier("Alt_R", alt_bit); break; case XK_Control_L: check_modifier("Control_L", ControlMask); break; case XK_Control_R: check_modifier("Control_R", ControlMask); break; case XK_Shift_L: check_modifier("Shift_L", ShiftMask); break; case XK_Shift_R: check_modifier("Shift_R", ShiftMask); break; case XK_Shift_Lock: check_modifier("Shift_Lock", LockMask); break; case XK_Caps_Lock: check_modifier("Caps_Lock", LockMask); break; /* It probably doesn't make any sense for a modifier bit to be assigned to a key that is not one of the above, but OpenWindows assigns modifier bits to a couple of random function keys for no reason that I can discern, so printing a warning here would be annoying. */ } } } #undef store_modifier #undef check_modifier #undef modwarn #undef modbarf /* If there was no Meta key, then try using the Alt key instead. If there is both a Meta key and an Alt key, then the Alt key is not disturbed and remains an Alt key. */ if (!meta_bit && alt_bit) meta_bit = alt_bit, alt_bit = 0; /* mode_bit overrides everything, since it's processed down inside of XLookupString() instead of by us. If Meta and Mode_switch both generate the same modifier bit (which is an error), then we don't interpret that bit as Meta, because we can't make XLookupString() not interpret it as Mode_switch; and interpreting it as both would be totally wrong. */ if (mode_bit) { const char *warn = 0; if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0; else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0; else if (mode_bit == super_bit) warn = "Super", super_bit = 0; else if (mode_bit == alt_bit) warn = "Alt", alt_bit = 0; if (warn) { wwarning(_("%s is being used for both %s and %s"), index_to_name(mode_bit), "Mode_switch", warn); } } MetaIndex = meta_bit; HyperIndex = hyper_bit; SuperIndex = super_bit; AltIndex = alt_bit; ModeIndex = mode_bit; XFreeModifiermap(x_modifier_keymap); }