Denis Gottardello
Denis Gottardello

Reputation: 86

XKeysymToKeycode and keyboard layout

I'm trying to use the function XKeysymToKeycode to send keystrokes to the active x11 applicaiton. The function works but it is using the english keyboard. My pc is localized as italian. Now I have to send for example the character "à", defined in the italian keyboard. How can I do in order to send it?

Upvotes: 1

Views: 642

Answers (1)

samcla
samcla

Reputation: 31

I've been struggling with the same issue. It seems that:

  1. The multiple layouts feature is implemented as groups and your IT layout is partially in group 1 for characters that differ from the US keyboard and in group 0 for some invariant keys (return/enter for example).
  2. XKeysymToKeycode doesn't care about groups, it just picks the first match.

You can either do the work manually as the clutter guys did. Or use a combination of gdk and X:

//char *oksym ="KP_Enter";
char *oksym ="at";
gboolean orv;
guint okeyval;
GdkKeymapKey *okeys;
gint on_keys;
GdkKeymap *okeymap;
GdkDisplay *odisplay;

XkbGetState(display, XkbUseCoreKbd, &xkbState);
printf("Active group would be %d\n",xkbState.group);

odisplay = gdk_display_get_default();
okeymap = gdk_keymap_get_for_display(odisplay);
okeyval = gdk_keyval_from_name(oksym);
if(okeyval == GDK_KEY_VoidSymbol){
    printf("GDK keyval GDK_KEY_%s is unknown\n",oksym);
    exit(-1);
}
orv = gdk_keymap_get_entries_for_keyval(okeymap, okeyval, &okeys, &on_keys);
printf("The following hardware keys will produce keyval GDK_KEY_%s(%d):\n",oksym,okeyval);
for(int i = 0; i < on_keys; i++){
    /*Groups seems to be used to manage multiple keyboard layouts (at least using MATE) 
     * instead/on top of their orignal meaning. Getting the active layout seems to be 
     * acheivable using XkbGetState. Some keys seems to be shared/stay on group 0, example 
     * Return/Enter. So if there is more than one key bound to a keyval, we'll take the one
     * that matches the active group. If there is only one (i.e Enter/Return) we'll just take
     * it regardless of its group.
     * */
    if( okeys[i].group == xkbState.group || on_keys == 1)
        printf("\tkeycode: %d, group: %d, level: %d\n",okeys[i].keycode,okeys[i].group,okeys[i].level);
}

Upvotes: 3

Related Questions