XKB_EXPORT xkb_keysym_t xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags) { const struct name_keysym *entry; char *tmp; xkb_keysym_t val; bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE); if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE) return XKB_KEY_NoSymbol; entry = bsearch(s, name_to_keysym, ARRAY_SIZE(name_to_keysym), sizeof(*name_to_keysym), compare_by_name); entry = find_sym(entry, s, icase); if (entry) return entry->keysym; if (*s == 'U' || (icase && *s == 'u')) { val = strtoul(&s[1], &tmp, 16); if (tmp && *tmp != '\0') return XKB_KEY_NoSymbol; if (val < 0x20 || (val > 0x7e && val < 0xa0)) return XKB_KEY_NoSymbol; if (val < 0x100) return val; if (val > 0x10ffff) return XKB_KEY_NoSymbol; return val | 0x01000000; } else if (s[0] == '0' && (s[1] == 'x' || (icase && s[1] == 'X'))) { val = strtoul(&s[2], &tmp, 16); if (tmp && *tmp != '\0') return XKB_KEY_NoSymbol; return val; } /* Stupid inconsistency between the headers and XKeysymDB: the former has * no separating underscore, while some XF86* syms in the latter did. * As a last ditch effort, try without. */ if (strncmp(s, "XF86_", 5) == 0 || (icase && strncasecmp(s, "XF86_", 5) == 0)) { xkb_keysym_t ret; tmp = strdup(s); if (!tmp) return XKB_KEY_NoSymbol; memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1); ret = xkb_keysym_from_name(tmp, flags); free(tmp); return ret; } return XKB_KEY_NoSymbol; }
static int test_casestring(const char *string, xkb_keysym_t expected) { xkb_keysym_t keysym; keysym = xkb_keysym_from_name(string, XKB_KEYSYM_CASE_INSENSITIVE); fprintf(stderr, "Expected casestring %s -> %x\n", string, expected); fprintf(stderr, "Received casestring %s -> %x\n\n", string, keysym); return keysym == expected; }
static int test_string(const char *string, xkb_keysym_t expected) { xkb_keysym_t keysym; keysym = xkb_keysym_from_name(string, 0); fprintf(stderr, "Expected string %s -> %x\n", string, expected); fprintf(stderr, "Received string %s -> %x\n\n", string, keysym); return keysym == expected; }
int uxkb_string_to_keysym(const char *n, uint32_t *out) { uint32_t keysym; /* TODO: fix xkbcommon upstream to be case-insensitive if case-sensitive * match fails. */ keysym = xkb_keysym_from_name(n); if (!keysym) return -EFAULT; *out = keysym; return 0; }
uint32_t gram_keysym_from_name(char* name) { uint32_t sym = xkb_keysym_from_name(name, XKB_KEYSYM_CASE_INSENSITIVE); static uint32_t symbols[GRAM_NUM_SYMS][2] = {{'.', XKB_KEY_period }, {'$', XKB_KEY_dollar }, {',', XKB_KEY_comma }, {'#', XKB_KEY_numbersign}}; if(sym == XKB_KEY_NoSymbol && strlen(name) == 1) { /* check symbols */ for(int i = 0; i < GRAM_NUM_SYMS; i++) { if(name[0] == symbols[i][0]) { return symbols[i][1]; } } } return sym; }
static xkb_keysym_t cached_keysym_from_name(struct keysym_from_name_cache *cache, const char *name, size_t len) { xkb_keysym_t keysym; if (len >= sizeof(cache->cache[0].name)) return XKB_KEY_NoSymbol; for (unsigned i = 0; i < KEYSYM_FROM_NAME_CACHE_SIZE; i++) if (cache->cache[i].len == len && memcmp(cache->cache[i].name, name, len) == 0) return cache->cache[i].keysym; keysym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS); strcpy(cache->cache[cache->next].name, name); cache->cache[cache->next].len = len; cache->cache[cache->next].keysym = keysym; cache->next = (cache->next + 1) % KEYSYM_FROM_NAME_CACHE_SIZE; return keysym; }
static gboolean accelerator_parse (const gchar *accelerator, MetaKeyCombo *combo) { guint keyval, keycode; MetaVirtualModifier mods; gint len; combo->keysym = 0; combo->keycode = 0; combo->modifiers = 0; if (accelerator == NULL) return FALSE; keyval = 0; keycode = 0; mods = 0; len = strlen (accelerator); while (len) { if (*accelerator == '<') { if (len >= 9 && is_primary (accelerator)) { /* Primary is treated the same as Control */ accelerator += 9; len -= 9; mods |= META_VIRTUAL_CONTROL_MASK; } else if (len >= 9 && is_control (accelerator)) { accelerator += 9; len -= 9; mods |= META_VIRTUAL_CONTROL_MASK; } else if (len >= 7 && is_shift (accelerator)) { accelerator += 7; len -= 7; mods |= META_VIRTUAL_SHIFT_MASK; } else if (len >= 6 && is_shft (accelerator)) { accelerator += 6; len -= 6; mods |= META_VIRTUAL_SHIFT_MASK; } else if (len >= 6 && is_ctrl (accelerator)) { accelerator += 6; len -= 6; mods |= META_VIRTUAL_CONTROL_MASK; } else if (len >= 6 && is_modx (accelerator)) { static const guint mod_vals[] = { META_VIRTUAL_ALT_MASK, META_VIRTUAL_MOD2_MASK, META_VIRTUAL_MOD3_MASK, META_VIRTUAL_MOD4_MASK, META_VIRTUAL_MOD5_MASK, }; len -= 6; accelerator += 4; mods |= mod_vals[*accelerator - '1']; accelerator += 2; } else if (len >= 5 && is_ctl (accelerator)) { accelerator += 5; len -= 5; mods |= META_VIRTUAL_CONTROL_MASK; } else if (len >= 5 && is_alt (accelerator)) { accelerator += 5; len -= 5; mods |= META_VIRTUAL_ALT_MASK; } else if (len >= 6 && is_meta (accelerator)) { accelerator += 6; len -= 6; mods |= META_VIRTUAL_META_MASK; } else if (len >= 7 && is_hyper (accelerator)) { accelerator += 7; len -= 7; mods |= META_VIRTUAL_HYPER_MASK; } else if (len >= 7 && is_super (accelerator)) { accelerator += 7; len -= 7; mods |= META_VIRTUAL_SUPER_MASK; } else { gchar last_ch; last_ch = *accelerator; while (last_ch && last_ch != '>') { last_ch = *accelerator; accelerator += 1; len -= 1; } } } else { if (len >= 4 && is_keycode (accelerator)) { keycode = strtoul (accelerator, NULL, 16); goto out; } else if (strcmp (accelerator, "Above_Tab") == 0) { keyval = META_KEY_ABOVE_TAB; goto out; } else { keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE); if (keyval == XKB_KEY_NoSymbol) { char *with_xf86 = g_strconcat ("XF86", accelerator, NULL); keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE); g_free (with_xf86); if (keyval == XKB_KEY_NoSymbol) return FALSE; } } accelerator += len; len -= len; } } out: combo->keysym = keyval; combo->keycode = keycode; combo->modifiers = mods; return TRUE; }
int main(void) { assert(test_string("Undo", 0xFF65)); assert(test_string("ThisKeyShouldNotExist", XKB_KEY_NoSymbol)); assert(test_string("XF86_Switch_VT_5", 0x1008FE05)); assert(test_string("VoidSymbol", 0xFFFFFF)); assert(test_string("U4567", 0x1004567)); assert(test_string("0x10203040", 0x10203040)); assert(test_string("a", 0x61)); assert(test_string("A", 0x41)); assert(test_string("ch", 0xfea0)); assert(test_string("Ch", 0xfea1)); assert(test_string("CH", 0xfea2)); assert(test_string("THORN", 0x00de)); assert(test_string("Thorn", 0x00de)); assert(test_string("thorn", 0x00fe)); assert(test_keysym(0x1008FF56, "XF86Close")); assert(test_keysym(0x0, "NoSymbol")); assert(test_keysym(0x1008FE20, "XF86Ungrab")); assert(test_keysym(0x01001234, "U1234")); /* 16-bit unicode padded to width 4. */ assert(test_keysym(0x010002DE, "U02DE")); /* 32-bit unicode padded to width 8. */ assert(test_keysym(0x0101F4A9, "U0001F4A9")); assert(test_casestring("Undo", 0xFF65)); assert(test_casestring("UNDO", 0xFF65)); assert(test_casestring("A", 0x61)); assert(test_casestring("a", 0x61)); assert(test_casestring("ThisKeyShouldNotExist", XKB_KEY_NoSymbol)); assert(test_casestring("XF86_Switch_vT_5", 0x1008FE05)); assert(test_casestring("xF86_SwitcH_VT_5", 0x1008FE05)); assert(test_casestring("xF86SwiTch_VT_5", 0x1008FE05)); assert(test_casestring("xF86Switch_vt_5", 0x1008FE05)); assert(test_casestring("VoidSymbol", 0xFFFFFF)); assert(test_casestring("vOIDsymBol", 0xFFFFFF)); assert(test_casestring("U4567", 0x1004567)); assert(test_casestring("u4567", 0x1004567)); assert(test_casestring("0x10203040", 0x10203040)); assert(test_casestring("0X10203040", 0x10203040)); assert(test_casestring("THORN", 0x00fe)); assert(test_casestring("Thorn", 0x00fe)); assert(test_casestring("thorn", 0x00fe)); assert(test_utf8(XKB_KEY_y, "y")); assert(test_utf8(XKB_KEY_u, "u")); assert(test_utf8(XKB_KEY_m, "m")); assert(test_utf8(XKB_KEY_Cyrillic_em, "м")); assert(test_utf8(XKB_KEY_Cyrillic_u, "у")); assert(test_utf8(XKB_KEY_exclam, "!")); assert(test_utf8(XKB_KEY_oslash, "ø")); assert(test_utf8(XKB_KEY_hebrew_aleph, "א")); assert(test_utf8(XKB_KEY_Arabic_sheen, "ش")); assert(test_utf8(XKB_KEY_space, " ")); assert(test_utf8(XKB_KEY_KP_Space, " ")); assert(test_utf8(XKB_KEY_BackSpace, "\b")); assert(test_utf8(XKB_KEY_Escape, "\033")); assert(test_utf8(XKB_KEY_KP_Separator, ",")); assert(test_utf8(XKB_KEY_KP_Decimal, ".")); assert(test_utf8(XKB_KEY_Tab, "\t")); assert(test_utf8(XKB_KEY_KP_Tab, "\t")); assert(test_utf8(XKB_KEY_hyphen, "")); assert(test_utf8(XKB_KEY_Linefeed, "\n")); assert(test_utf8(XKB_KEY_Return, "\r")); assert(test_utf8(XKB_KEY_KP_Enter, "\r")); assert(test_utf8(XKB_KEY_KP_Equal, "=")); assert(test_utf8(XKB_KEY_9, "9")); assert(test_utf8(XKB_KEY_KP_9, "9")); assert(test_utf8(XKB_KEY_KP_Multiply, "*")); assert(test_utf8(XKB_KEY_KP_Subtract, "-")); assert(xkb_keysym_is_lower(XKB_KEY_a)); assert(xkb_keysym_is_lower(XKB_KEY_Greek_lambda)); assert(xkb_keysym_is_lower(xkb_keysym_from_name("U03b1", 0))); /* GREEK SMALL LETTER ALPHA */ assert(xkb_keysym_is_lower(xkb_keysym_from_name("U03af", 0))); /* GREEK SMALL LETTER IOTA WITH TONOS */ assert(xkb_keysym_is_upper(XKB_KEY_A)); assert(xkb_keysym_is_upper(XKB_KEY_Greek_LAMBDA)); assert(xkb_keysym_is_upper(xkb_keysym_from_name("U0391", 0))); /* GREEK CAPITAL LETTER ALPHA */ assert(xkb_keysym_is_upper(xkb_keysym_from_name("U0388", 0))); /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ assert(!xkb_keysym_is_upper(XKB_KEY_a)); assert(!xkb_keysym_is_lower(XKB_KEY_A)); assert(!xkb_keysym_is_lower(XKB_KEY_Return)); assert(!xkb_keysym_is_upper(XKB_KEY_Return)); assert(!xkb_keysym_is_lower(XKB_KEY_hebrew_aleph)); assert(!xkb_keysym_is_upper(XKB_KEY_hebrew_aleph)); assert(!xkb_keysym_is_upper(xkb_keysym_from_name("U05D0", 0))); /* HEBREW LETTER ALEF */ assert(!xkb_keysym_is_lower(xkb_keysym_from_name("U05D0", 0))); /* HEBREW LETTER ALEF */ assert(!xkb_keysym_is_lower(XKB_KEY_8)); assert(!xkb_keysym_is_upper(XKB_KEY_8)); assert(xkb_keysym_is_keypad(XKB_KEY_KP_Enter)); assert(xkb_keysym_is_keypad(XKB_KEY_KP_6)); assert(xkb_keysym_is_keypad(XKB_KEY_KP_Add)); assert(!xkb_keysym_is_keypad(XKB_KEY_Num_Lock)); assert(!xkb_keysym_is_keypad(XKB_KEY_1)); assert(!xkb_keysym_is_keypad(XKB_KEY_Return)); assert(xkb_keysym_to_upper(XKB_KEY_a) == XKB_KEY_A); assert(xkb_keysym_to_upper(XKB_KEY_A) == XKB_KEY_A); assert(xkb_keysym_to_lower(XKB_KEY_a) == XKB_KEY_a); assert(xkb_keysym_to_lower(XKB_KEY_A) == XKB_KEY_a); assert(xkb_keysym_to_upper(XKB_KEY_Return) == XKB_KEY_Return); assert(xkb_keysym_to_lower(XKB_KEY_Return) == XKB_KEY_Return); assert(xkb_keysym_to_upper(XKB_KEY_Greek_lambda) == XKB_KEY_Greek_LAMBDA); assert(xkb_keysym_to_upper(XKB_KEY_Greek_LAMBDA) == XKB_KEY_Greek_LAMBDA); assert(xkb_keysym_to_lower(XKB_KEY_Greek_lambda) == XKB_KEY_Greek_lambda); assert(xkb_keysym_to_lower(XKB_KEY_Greek_LAMBDA) == XKB_KEY_Greek_lambda); assert(xkb_keysym_to_upper(XKB_KEY_eacute) == XKB_KEY_Eacute); assert(xkb_keysym_to_lower(XKB_KEY_Eacute) == XKB_KEY_eacute); return 0; }
void TableGenerator::parseKeySequence(char *line) { // we are interested in the lines with the following format: // <Multi_key> <numbersign> <S> : "♬" U266c # BEAMED SIXTEENTH NOTE char *keysEnd = strchr(line, ':'); if (!keysEnd) return; QComposeTableElement elem; // find the composed value - strings may be direct text encoded in the locale // for which the compose file is to be used, or an escaped octal or hexadecimal // character code. Octal codes are specified as "\123" and hexadecimal codes as "\0x123a". char *composeValue = strchr(keysEnd, '"'); if (!composeValue) return; ++composeValue; char *composeValueEnd = strchr(composeValue, '"'); if (!composeValueEnd) return; // if composed value is a quotation mark adjust the end pointer if (composeValueEnd[1] == '"') ++composeValueEnd; if (*composeValue == '\\' && composeValue[1] >= '0' && composeValue[1] <= '9') { // handle octal and hex code values char detectBase = composeValue[2]; if (detectBase == 'x') { // hexadecimal character code elem.value = keysymToUtf8(fromBase16(composeValue + 3, composeValueEnd)); } else { // octal character code elem.value = keysymToUtf8(fromBase8(composeValue + 1, composeValueEnd)); } } else { // handle direct text encoded in the locale if (*composeValue == '\\') ++composeValue; elem.value = QString::fromLocal8Bit(composeValue, composeValueEnd - composeValue).at(0).unicode(); ++composeValue; } #ifdef DEBUG_GENERATOR // find the comment elem.comment = QString::fromLocal8Bit(composeValueEnd + 1).trimmed(); #endif // find the key sequence and convert to X11 keysym char *k = line; const char *kend = keysEnd; for (int i = 0; i < QT_KEYSEQUENCE_MAX_LEN; i++) { // find the next pair of angle brackets and get the contents within while (k < kend && *k != '<') ++k; char *sym = ++k; while (k < kend && *k != '>') ++k; *k = '\0'; if (k < kend) { elem.keys[i] = xkb_keysym_from_name(sym, (xkb_keysym_flags)0); if (elem.keys[i] == XKB_KEY_NoSymbol) { if (!strcmp(sym, "dead_inverted_breve")) elem.keys[i] = XKB_KEY_dead_invertedbreve; else if (!strcmp(sym, "dead_double_grave")) elem.keys[i] = XKB_KEY_dead_doublegrave; #ifdef DEBUG_GENERATOR else qWarning() << QString("Qt Warning - invalid keysym: %1").arg(sym); #endif } } else { elem.keys[i] = 0; } } m_composeTable.append(elem); }
void fill_keycodes() { struct xkb_keymap *keymap; struct xkb_context *context; const struct xkb_rule_names rules={ .rules=xkb_names[0], .model=xkb_names[1], .layout=xkb_names[2], .variant=xkb_names[3], .options=xkb_names[4] }; struct xkb_state *state; enum xkb_state_component current_state; int counter; int i,j,k; char mods[256]; char keysym_asc[256]; char file_path[256]; char command[15]; uint32_t max_keys; int w,h,retval; int jumpto; context=xkb_context_new(0); keymap=xkb_keymap_new_from_names(context,&rules,0); state=NULL; // Get all the modifier keys for(i=8;i<256;i++) { state=xkb_state_new(keymap); current_state=xkb_state_update_key(state, i,XKB_KEY_DOWN); if (current_state!=0) { mods[i]=1; } else { mods[i]=0; } xkb_state_unref(state); } mods[7]=1; // fake mod, used for "no mod" // Read the keyboard definition files sprintf(file_path,"%s/%s.keymap",BASE_CONFIG_DIR,lang_onscreen); FILE *keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Can't open keyboard definition file %s. Trying with US file\n",file_path); sprintf(file_path,"%s/us.keymap",BASE_CONFIG_DIR); keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Also failed to open the US keymap file. Aborting.\n"); exit(-1); } } retval=fscanf(keyboard_file,"%s %d",command,&keyboard_blocks); if (retval!=2) { printf("Can't read the number of blocks\n"); } else { max_keys=keyboard_blocks*4*KEYS_PER_ROW; keyboard_lowercase=(struct key_element *)malloc(max_keys*sizeof(struct key_element)); memset(keyboard_lowercase,0,max_keys*sizeof(struct key_element)); for(counter=0;(!feof(keyboard_file))&&(counter<max_keys);counter++) { retval=fscanf(keyboard_file,"%s %d %d",command,&w,&h); if(retval!=3) { break; } keyboard_lowercase[counter].size=KEYS_FONT_SIZE; keyboard_lowercase[counter].g_element[0]=0; keyboard_lowercase[counter].w=w; keyboard_lowercase[counter].h=h; keyboard_lowercase[counter].keycode=0; keyboard_lowercase[counter].modifier=0; if (!strcmp(command,"BLANK")) { keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } else if (!strcmp(command,"KEY")) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].keysym=init_utf8_to_keysym(keyboard_lowercase[counter].g_element); if (keyboard_lowercase[counter].keysym==0) { keyboard_lowercase[counter].type=KEY_BLANK; } } else if ((!strcmp(command,"KEYSYM"))||(!strcmp(command,"KEYSYMTEXT"))) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keysym_asc); keyboard_lowercase[counter].keysym=xkb_keysym_from_name(keysym_asc,0); if (keyboard_lowercase[counter].keysym==0) { printf("Unknown keysym %s\n",keysym_asc); keyboard_lowercase[counter].type=KEY_BLANK; } else { if (!strcmp(command,"KEYSYMTEXT")) { retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].size=KEYS_TEXT_FONT_SIZE; } else { retval=xkb_keysym_to_utf8(keyboard_lowercase[counter].keysym,keyboard_lowercase[counter].g_element,7); if (retval==-1) { retval++; } keyboard_lowercase[counter].g_element[retval]=0;// terminate string } } } else if (!strcmp(command,"TAB")) { keyboard_lowercase[counter].type=KEY_TAB; keyboard_lowercase[counter].keysym=XK_Tab; } else if (!strcmp(command,"SPACE")) { keyboard_lowercase[counter].type=KEY_SPACE; keyboard_lowercase[counter].keysym=XK_space; } else if (!strcmp(command,"RETURN")) { keyboard_lowercase[counter].type=KEY_RETURN; keyboard_lowercase[counter].keysym=XK_Return; } else if (!strcmp(command,"DELETE")) { keyboard_lowercase[counter].type=KEY_DELETE; keyboard_lowercase[counter].keysym=XK_BackSpace; } else if (!strcmp(command,"JUMPTO")) { retval=fscanf(keyboard_file,"%d %s",&jumpto,command); keyboard_lowercase[counter].type=KEY_JUMPTO; keyboard_lowercase[counter].keycode=jumpto; keyboard_lowercase[counter].keysym=0; if (!strcmp(command,"GEN")) { keyboard_lowercase[counter].modifier=0; } else if (!strcmp(command,"SHIFT")) { keyboard_lowercase[counter].modifier=1; } else if (!strcmp(command,"SYMBOLS")) { keyboard_lowercase[counter].modifier=2; } else if (!strcmp(command,"LETTERS")) { keyboard_lowercase[counter].modifier=3; } if (jumpto>=keyboard_blocks) { printf("Ilegal jump to block %d (max. is %d)\n",jumpto,keyboard_blocks); keyboard_lowercase[counter].type=KEY_BLANK; } } else if (!strcmp(command,"UP")) { keyboard_lowercase[counter].type=KEY_UP; keyboard_lowercase[counter].keysym=XK_Up; } else if (!strcmp(command,"DOWN")) { keyboard_lowercase[counter].type=KEY_DOWN; keyboard_lowercase[counter].keysym=XK_Down; } else if (!strcmp(command,"LEFT")) { keyboard_lowercase[counter].type=KEY_LEFT; keyboard_lowercase[counter].keysym=XK_Left; } else if (!strcmp(command,"RIGHT")) { keyboard_lowercase[counter].type=KEY_RIGHT; keyboard_lowercase[counter].keysym=XK_Right; } else { printf("Unknown command %s\n",command); keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } } xkb_keysym_t keysym; xkb_keycode_t keycode_mod; for(i=7;i<256;i++) { // do a loop on every modifier if (!mods[i]) { continue; // In this loop we test each modifier with each keycode } state=xkb_state_new(keymap); if (i!=7) { xkb_state_update_key(state, i,XKB_KEY_DOWN); // press the modifier key keycode_mod=i; } else { keycode_mod=0; } for(j=8;j<256;j++) { if (mods[j]) { continue; // Don't test modifiers; we want "normal" keys } keysym=xkb_state_key_get_one_sym(state, j); if (keysym==XKB_KEY_NoSymbol) { continue; } for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].keysym==keysym)) { keyboard_lowercase[k].keycode=j; keyboard_lowercase[k].modifier=keycode_mod; } } } xkb_state_unref(state); } /*for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained printf("Texto: %s, Keysym: %d, mod: %d\n",keyboard_lowercase[k].g_element,keyboard_lowercase[k].keycode,keyboard_lowercase[k].modifier); }*/ // Now assign new keysyms to keycodes not used, to allow other keysyms not available in US keyboards xcb_key_symbols_t *symbols; symbols=xcb_key_symbols_alloc(conn); xcb_flush(conn); xcb_keycode_t keycode=8; xcb_keycode_t keycode_found; xcb_keysym_t keysyms[4]; xcb_keycode_t keycode_shift; struct lower_upper_t {xcb_keysym_t upper_first; xcb_keysym_t upper_last; xcb_keysym_t lower_first; xcb_keysym_t lower_last; }; struct lower_upper_t lower_upper[] = { {XKB_KEY_Agrave,XKB_KEY_Odiaeresis,XKB_KEY_agrave,XKB_KEY_odiaeresis}, {XKB_KEY_Oslash,XKB_KEY_THORN,XKB_KEY_oslash,XKB_KEY_thorn}, {0,0,0,0} }; struct lower_upper_t *iter_lu; keycode_shift=*xcb_key_symbols_get_keycode(symbols,XKB_KEY_Shift_L); for(k=0;k<max_keys;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].type!=KEY_JUMPTO)) { // this key is not available in US keyboards; let's redefine a keycode for it keycode_found=0; while(keycode<256) { if ((0==xcb_key_symbols_get_keysym(symbols,keycode,0))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,1))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,2))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,3))) { keycode_found=keycode; break; } keycode++; } if (keycode_found==0) { printf("No more codes available\n"); break; // there are no more free keycodes available } keycode=keycode_found; keysyms[0]=keyboard_lowercase[k].keysym; keysyms[1]=0; keysyms[2]=keyboard_lowercase[k].keysym; keysyms[3]=0; for(iter_lu=lower_upper;iter_lu->upper_first;iter_lu++) { if ((keysyms[0]>=iter_lu->upper_first)&&(keysyms[0]<=iter_lu->upper_last)) { // it's an uppercase special character keysyms[0]|=0x20; // first character as lowercase break; } if ((keysyms[0]>=iter_lu->lower_first)&&(keysyms[0]<=iter_lu->lower_last)) { // it's a lowercase special character keysyms[2]&=0xDF; // second character as uppercase break; } } xcb_change_keyboard_mapping(conn,1,keycode,4,keysyms); // insert the new keysym for(j=k;j<max_keys;j++) { // set the keycode and the shift modifier, if needed, to all keys with that keysyms if (keyboard_lowercase[j].keysym==keysyms[0]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=0; continue; } if (keyboard_lowercase[j].keysym==keysyms[2]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=keycode_shift; continue; } } keycode++; } } xcb_key_symbols_free(symbols); } fclose(keyboard_file); keyboard_current_block=0; xkb_keymap_unref(keymap); xkb_context_unref(context); }
int conf_parse_grab(struct conf_option *opt, bool on, const char *arg) { char *buf, *tmp, *start; struct conf_grab grab, *gnew; memset(&grab, 0, sizeof(grab)); buf = strdup(arg); if (!buf) return -ENOMEM; tmp = buf; next_mod: if (*tmp == '<') { start = tmp; while (*tmp && *tmp != '>') ++tmp; if (*tmp != '>') { log_error("missing '>' in grab '%s' near '%s'", arg, start); goto err_free; } *tmp++ = 0; ++start; if (!strcasecmp(start, "shift")) { grab.mods |= SHL_SHIFT_MASK; } else if (!strcasecmp(start, "lock")) { grab.mods |= SHL_LOCK_MASK; } else if (!strcasecmp(start, "control") || !strcasecmp(start, "ctrl")) { grab.mods |= SHL_CONTROL_MASK; } else if (!strcasecmp(start, "alt")) { grab.mods |= SHL_ALT_MASK; } else if (!strcasecmp(start, "logo")) { grab.mods |= SHL_LOGO_MASK; } else { log_error("invalid modifier '%s' in grab '%s'", start, arg); goto err_free; } goto next_mod; } if (!*tmp) { log_error("missing key in grab '%s'", arg); goto err_free; } grab.keysym = xkb_keysym_from_name(tmp); if (!grab.keysym) { log_error("invalid key '%s' in grab '%s'", tmp, arg); goto err_free; } gnew = malloc(sizeof(*gnew)); if (!gnew) goto err_free; memcpy(gnew, &grab, sizeof(*gnew)); opt->type->free(opt); *(void**)opt->mem = gnew; free(buf); return 0; err_free: free(buf); return -EFAULT; }
// convert a Mod+key arg to mod mask and keysym gboolean x11_parse_key ( char *combo, unsigned int *mod, xkb_keysym_t *key ) { GString *str = g_string_new ( "" ); unsigned int modmask = 0; if ( strcasestr ( combo, "shift" ) ) { modmask |= x11_mod_masks[X11MOD_SHIFT]; if ( x11_mod_masks[X11MOD_SHIFT] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Shift</b> key.\n" ); } } if ( strcasestr ( combo, "control" ) ) { modmask |= x11_mod_masks[X11MOD_CONTROL]; if ( x11_mod_masks[X11MOD_CONTROL] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Control</b> key.\n" ); } } if ( strcasestr ( combo, "alt" ) ) { modmask |= x11_mod_masks[X11MOD_ALT]; if ( x11_mod_masks[X11MOD_ALT] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Alt</b> key.\n" ); } } if ( strcasestr ( combo, "super" ) ) { modmask |= x11_mod_masks[X11MOD_SUPER]; if ( x11_mod_masks[X11MOD_SUPER] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Super</b> key.\n" ); } } if ( strcasestr ( combo, "meta" ) ) { modmask |= x11_mod_masks[X11MOD_META]; if ( x11_mod_masks[X11MOD_META] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Meta</b> key.\n" ); } } if ( strcasestr ( combo, "hyper" ) ) { modmask |= x11_mod_masks[X11MOD_HYPER]; if ( x11_mod_masks[X11MOD_HYPER] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Hyper</b> key.\n" ); } } int seen_mod = FALSE; if ( strcasestr ( combo, "Mod" ) ) { seen_mod = TRUE; } *mod = modmask; // Skip modifier (if exist) and parse key. char i = strlen ( combo ); while ( i > 0 && !strchr ( "-+", combo[i - 1] ) ) { i--; } xkb_keysym_t sym = XKB_KEY_NoSymbol; if ( ( modmask & x11_mod_masks[X11MOD_SHIFT] ) != 0 ) { gchar * str = g_utf8_next_char ( combo + i ); // If it is a single char, we make a capital out of it. if ( str != NULL && *str == '\0' ) { int l = 0; char buff[8]; gunichar v = g_utf8_get_char ( combo + i ); gunichar u = g_unichar_toupper ( v ); if ( ( l = g_unichar_to_utf8 ( u, buff ) ) ) { buff[l] = '\0'; sym = xkb_keysym_from_name ( buff, XKB_KEYSYM_NO_FLAGS ); } } } if ( sym == XKB_KEY_NoSymbol ) { sym = xkb_keysym_from_name ( combo + i, XKB_KEYSYM_CASE_INSENSITIVE ); } if ( sym == XKB_KEY_NoSymbol || ( !modmask && ( strchr ( combo, '-' ) || strchr ( combo, '+' ) ) ) ) { g_string_append_printf ( str, "Sorry, rofi cannot understand the key combination: <i>%s</i>\n", combo ); g_string_append ( str, "\nRofi supports the following modifiers:\n\t" ); g_string_append ( str, "<i>Shift,Control,Alt,Super,Meta,Hyper</i>" ); if ( seen_mod ) { g_string_append ( str, "\n\n<b>Mod1,Mod2,Mod3,Mod4,Mod5 are no longer supported, use one of the above.</b>" ); } } if ( str->len > 0 ) { rofi_view_error_dialog ( str->str, TRUE ); g_string_free ( str, TRUE ); return FALSE; } g_string_free ( str, TRUE ); *key = sym; return TRUE; }