2012-04-14 30 views
8

我只是試圖使用KeyCode和修改器掩碼並將其轉換爲使用Xkb擴展名的KeySym。我似乎無法弄清楚爲什麼這不起作用。顯然,修飾符不匹配,但我不知道爲什麼。我甚至不知道我是否正確轉換組。Xkb:如何將keycode轉換爲keysym

#include <stdio.h> 
#include <stdlib.h> 
#include <X11/X.h> 
#include <X11/XKBlib.h> 

void check(XkbDescPtr keyboard_map, KeyCode keycode, unsigned int mask) { 
    //What the hell is diff between XkbKeyGroupInfo and XkbKeyNumGroups? 
    unsigned char info = XkbKeyGroupInfo(keyboard_map, keycode); 
    int num_groups = XkbKeyNumGroups(keyboard_map, keycode); 

    int key_width = XkbKeyGroupsWidth(keyboard_map, keycode); 
    //int num_syms = XkbKeyNumSyms(keyboard_map, keycode); 

    //Get the group 
    unsigned int group = 0; // What should this default to? 
    switch (XkbOutOfRangeGroupAction(info)) { 
     case XkbRedirectIntoRange: 
      /* If the RedirectIntoRange flag is set, the four least significant 
      * bits of the groups wrap control specify the index of a group to 
      * which all illegal groups correspond. If the specified group is 
      * also out of range, all illegal groups map to Group1. 
      */ 
      printf("XkbRedirectIntoRange\n"); 
      group = XkbOutOfRangeGroupInfo(info); 
      if (group >= num_groups) { 
       group = 0; 
      } 
     break; 

     case XkbClampIntoRange: 
      /* If the ClampIntoRange flag is set, out-of-range groups correspond 
      * to the nearest legal group. Effective groups larger than the 
      * highest supported group are mapped to the highest supported group; 
      * effective groups less than Group1 are mapped to Group1 . For 
      * example, a key with two groups of symbols uses Group2 type and 
      * symbols if the global effective group is either Group3 or Group4. 
      */ 
      printf("XkbClampIntoRange\n"); 
      group = num_groups - 1; 
     break; 

     case XkbWrapIntoRange: 
      /* If neither flag is set, group is wrapped into range using integer 
      * modulus. For example, a key with two groups of symbols for which 
      * groups wrap uses Group1 symbols if the global effective group is 
      * Group3 or Group2 symbols if the global effective group is Group4. 
      */ 
      printf("XkbWrapIntoRange\n"); 
     default: 
      printf("Default\n"); 
      if (num_groups != 0) { 
       group %= num_groups; 
      } 
     break; 
    } 
    printf("Group Info %d, %d, %d\n", group, num_groups, key_width); 
    //printf("Mask Info %d, %d, %d, %d, %d, %d, %d, %d\n", ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask); 

    XkbKeyTypePtr key_type = XkbKeyKeyType(keyboard_map, keycode, group); 

    KeySym keysym = NoSymbol; 
    int i; 
    for (i = 0; i < key_type->map_count; i++) { 
     if (key_type->map[i].active && key_type->map[i].mods.mask == mask) { 
      keysym = XkbKeySymEntry(keyboard_map, keycode, i, group); 
     } 
    } 

    //printf("%s\n", XKeysymToString(keysym)); 
    printf("KeyCode: %d\n", (int) keycode); 
    printf("KeySym: %d\n", (int) keysym); 
} 

int main(int argc, const char * argv[]) { 
    Display * display; 

    //Try to attach to the default X11 display. 
    display = XOpenDisplay(NULL); 
    if(display == NULL) { 
     printf("Error: Could not open display!\n"); 
     return EXIT_FAILURE; 
    } 

    //Get the map 
    XkbDescPtr keyboard_map = XkbGetMap(display, XkbAllClientInfoMask, XkbUseCoreKbd); 

    KeyCode keycode = 56; // b 
    check(keyboard_map, keycode, ShiftMask | LockMask | ControlMask); 

    //Close the connection to the selected X11 display. 
    XCloseDisplay(display); 

    return EXIT_SUCCESS; 
} 

回答

5

經過大量的試驗和錯誤後,我終於弄清楚了。 XKeycodeToKeysym明顯中斷,並且沒有爲擴展索引定義索引值計算。

#include <stdbool.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <X11/X.h> 
#include <X11/XKBlib.h> 

KeySym KeyCodeToKeySym(Display * display, KeyCode keycode, unsigned int event_mask) { 
    KeySym keysym = NoSymbol; 

    //Get the map 
    XkbDescPtr keyboard_map = XkbGetMap(display, XkbAllClientInfoMask, XkbUseCoreKbd); 
    if (keyboard_map) { 
     //What is diff between XkbKeyGroupInfo and XkbKeyNumGroups? 
     unsigned char info = XkbKeyGroupInfo(keyboard_map, keycode); 
     unsigned int num_groups = XkbKeyNumGroups(keyboard_map, keycode); 

     //Get the group 
     unsigned int group = 0x00; 
     switch (XkbOutOfRangeGroupAction(info)) { 
      case XkbRedirectIntoRange: 
       /* If the RedirectIntoRange flag is set, the four least significant 
       * bits of the groups wrap control specify the index of a group to 
       * which all illegal groups correspond. If the specified group is 
       * also out of range, all illegal groups map to Group1. 
       */ 
       group = XkbOutOfRangeGroupInfo(info); 
       if (group >= num_groups) { 
        group = 0; 
       } 
      break; 

      case XkbClampIntoRange: 
       /* If the ClampIntoRange flag is set, out-of-range groups correspond 
       * to the nearest legal group. Effective groups larger than the 
       * highest supported group are mapped to the highest supported group; 
       * effective groups less than Group1 are mapped to Group1 . For 
       * example, a key with two groups of symbols uses Group2 type and 
       * symbols if the global effective group is either Group3 or Group4. 
       */ 
       group = num_groups - 1; 
      break; 

      case XkbWrapIntoRange: 
       /* If neither flag is set, group is wrapped into range using integer 
       * modulus. For example, a key with two groups of symbols for which 
       * groups wrap uses Group1 symbols if the global effective group is 
       * Group3 or Group2 symbols if the global effective group is Group4. 
       */ 
      default: 
       if (num_groups != 0) { 
        group %= num_groups; 
       } 
      break; 
     } 

     XkbKeyTypePtr key_type = XkbKeyKeyType(keyboard_map, keycode, group); 
     unsigned int active_mods = event_mask & key_type->mods.mask; 

     int i, level = 0; 
     for (i = 0; i < key_type->map_count; i++) { 
      if (key_type->map[i].active && key_type->map[i].mods.mask == active_mods) { 
       level = key_type->map[i].level; 
      } 
     } 

     keysym = XkbKeySymEntry(keyboard_map, keycode, level, group); 
     XkbFreeClientMap(keyboard_map, XkbAllClientInfoMask, true); 
    } 

    return keysym; 
} 

int main(int argc, const char * argv[]) { 
    Display * display; 

    //Try to attach to the default X11 display. 
    display = XOpenDisplay(NULL); 
    if(display == NULL) { 
     printf("Error: Could not open display!\n"); 
     return EXIT_FAILURE; 
    } 

    KeyCode keycode = 56; // b 
    unsigned int event_mask = ShiftMask | LockMask; 
    KeySym keysym = KeyCodeToKeySym(display, keycode, event_mask); 

    printf("KeySym: %s\n", XKeysymToString(keysym)); 

    //Close the connection to the selected X11 display. 
    XCloseDisplay(display); 

    return EXIT_SUCCESS; 
} 
0

XKeycodeToKeysym手冊頁:

The XKeycodeToKeysym function uses internal Xlib tables and returns the 
    KeySym defined for the specified KeyCode and the element of the KeyCode 
    vector. If no symbol is defined, XKeycodeToKeysym returns NoSymbol. 
    XKeycodeToKeysym predates the XKB extension. If you want to lookup a 
    KeySym while using XKB you have to use XkbKeycodeToKeysym. 

我不明白,在你的示例代碼。

閱讀完整的手冊頁獲取更多信息。

相關問題