XKeysymToKeycode et al. - Xwindows

This is a discussion on XKeysymToKeycode et al. - Xwindows ; Hello, I'm trying to translate a string into XKeysymcodes. What am I doing wrong? // ------------------------------------------------------------------ // /* gcc -g -Wall -o test test.c -L /usr/X11R6/lib/ -lX11 -lXtst */ #include #include //#include int main() { Display *dpy = XOpenDisplay( NULL ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: XKeysymToKeycode et al.

  1. XKeysymToKeycode et al.

    Hello,

    I'm trying to translate a string into XKeysymcodes. What am I doing
    wrong?

    // ------------------------------------------------------------------ //
    /* gcc -g -Wall -o test test.c -L /usr/X11R6/lib/ -lX11 -lXtst */

    #include
    #include
    //#include

    int main() {

    Display *dpy = XOpenDisplay( NULL );
    char *teststr = "Hello World";
    int i = 0, pdone = 0;
    KeyCode kcode;
    KeySym ksym;
    char *kcodestr, a[2];

    while(!pdone) {
    if(teststr[i]) {
    a[0] = teststr[i];
    a[1] = '\0';
    ksym = XStringToKeysym(a);
    kcode = XKeysymToKeycode(dpy, ksym);
    kcodestr = XKeysymToString(kcode);
    // XTestFakeKeyEvent( dpy, ksym, True, CurrentTime );
    printf("%s:%d ", kcodestr, teststr[i]);
    i++;
    }
    else pdone = 1;
    }

    XCloseDisplay( dpy );
    return 0;
    }
    // ------------------------------------------------------------------ //

    TIA,
    olli

    --
    GnuPG-Key: http://www.sopos.org/pgp/olli.asc
    GnuPG-Fingerprint: F27A BA8C 1CFB B905 65A8 2544 0F07 B675 9A00 D827
    NP: Nothing

  2. Re: XKeysymToKeycode et al.

    Oliver Heins writes:
    > I'm trying to translate a string into XKeysymcodes. What am I doing
    > wrong?


    This is the situation for which the famous quote "Let me count the ways..."
    was created. :-)

    1) You're using C++ comment conventions in what appears to be C code
    based on your suggested compilation command. (Just because some
    compiler supports non-standard extensions doesn't mean that using
    them is a good idea.)

    > /* gcc -g -Wall -o test test.c -L /usr/X11R6/lib/ -lX11 -lXtst */


    2) should be:

    /* gcc -g -Wall -o xtst xtst.c -L/usr/X11R6/lib -lX11 -lXtst -lXext */

    in part to ensure that ./test won't get confused with the similarly-
    named shell function regardless of your $PATH.

    > KeyCode kcode;
    > KeySym ksym;

    ...
    > while(!pdone) {
    > if(teststr[i]) {


    3) as coded, pdone is useless; "while(teststr[i])" takes less code

    > a[1] = '\0';


    4) A constant subexpression that should be outside the loop.

    > ksym = XStringToKeysym(a);
    > kcode = XKeysymToKeycode(dpy, ksym);
    > kcodestr = XKeysymToString(kcode);


    5) This is bug you were actually looking for. :-) Read your own code
    carefully: XKeysymToString expects a KeySym, but you passed kcode.
    The compiler doesn't complain because type KeyCode can be promoted to
    type KeySym.


    Here's a modified version that should work better:
    ------------------------------
    /* gcc -g -Wall -o xtst xtst.c -L/usr/X11R6/lib -lX11 -lXtst -lXext */

    #include
    #include

    int main() {
    Display *dpy = XOpenDisplay( NULL );
    static char *teststr = "Hello World";
    int i;
    KeyCode kcode;
    KeySym ksym;
    char *kcodestr, a[2];

    a[1] = '\0';
    for (i = 0; teststr[i] != '\0'; ++i) {
    *a = teststr[i];
    ksym = XStringToKeysym(a);
    kcode = XKeysymToKeycode(dpy, ksym);
    kcodestr = XKeysymToString(ksym);
    printf("%c(%d)->%lu->%d->%s\n", *a, *a, ksym, kcode, kcodestr);
    }

    XCloseDisplay(dpy);
    return 0;
    }
    ------------------------------

    Don't confuse KeyCodes with ASCII. They're equivalent to "keyboard
    row 2, third key from the left" and the meaning differs if you have a
    QWERTY keysym mapping instead of a Dvorak mapping.

    > TIA,


    You're welcome.
    -WBE

  3. Re: XKeysymToKeycode et al.

    Hi Winston,

    thank you very much for your critics and your constructive help. As you
    probably have noticed, I'm not a C programmer (not even a
    whatever-language-you-want-to-put-here programmer, to be honest).
    However I try to do something which have to be done in C.

    wbe @ubeblock.psr.com.invalid (Winston) writes:

    > Oliver Heins writes:
    >> I'm trying to translate a string into XKeysymcodes. What am I doing
    >> wrong?

    >
    > This is the situation for which the famous quote "Let me count the ways..."
    > was created. :-)


    Yes, I did know that my code (even if it's short) must look
    horrible... :-)

    > 1) You're using C++ comment conventions in what appears to be C code
    > based on your suggested compilation command. (Just because some
    > compiler supports non-standard extensions doesn't mean that using
    > them is a good idea.)


    Thanks, I did not know that C only allows the /* */ convention.

    >> /* gcc -g -Wall -o test test.c -L /usr/X11R6/lib/ -lX11 -lXtst */

    >
    > 2) should be:
    >
    > /* gcc -g -Wall -o xtst xtst.c -L/usr/X11R6/lib -lX11 -lXtst -lXext */
    >
    > in part to ensure that ./test won't get confused with the similarly-
    > named shell function regardless of your $PATH.


    Thanks.

    >> KeyCode kcode;
    >> KeySym ksym;

    > ...
    >> while(!pdone) {
    >> if(teststr[i]) {

    >
    > 3) as coded, pdone is useless; "while(teststr[i])" takes less code


    Yes, I like that more then my code.

    >> a[1] = '\0';

    >
    > 4) A constant subexpression that should be outside the loop.


    For unknown reasons (at least to me ;-), this did not work in the bigger
    program from which I stripped down my minimal example. But you're
    right, of course.

    >> ksym = XStringToKeysym(a);
    >> kcode = XKeysymToKeycode(dpy, ksym);
    >> kcodestr = XKeysymToString(kcode);

    >
    > 5) This is bug you were actually looking for. :-) Read your own code
    > carefully: XKeysymToString expects a KeySym, but you passed kcode.
    > The compiler doesn't complain because type KeyCode can be promoted to
    > type KeySym.


    Ahhh, thanks.

    > Here's a modified version that should work better:


    [...]

    > Don't confuse KeyCodes with ASCII. They're equivalent to "keyboard
    > row 2, third key from the left" and the meaning differs if you have a
    > QWERTY keysym mapping instead of a Dvorak mapping.


    Yes, I use the NEO mapping[1] and had to modify my .xmodmap therefore.
    However, this seems to be more complicated and difficult than I first
    thought. What I try to do is to pass a string of text to an application
    in a way that it thinks the text was typed on a keyboard and thus gets
    inserted. I want to use the XTestFakeKeyEvent function therefore. But
    only a view characters get translated correctly, most just fall behind.
    Take the string "Hello World" as an example: The output through
    XTestFakeEvent() is "helloworld". While it is quite simple to add
    capital letters, I have no idea how to get the space translated, not to
    say of all the other characters not printed.

    For example, the text: "Hello World! We are international (or at least
    we try to, as the world is per definition): "
    gets transformed to this:
    HelloWorldWeareinternationaloratleastwetrytoasthew orldisperdefinition

    This is what the printf() statement puts out:

    H(72)->72->30->H
    e(101)->101->41->e
    l(108)->108->26->l
    l(108)->108->26->l
    o(111)->111->42->o
    (32)->0->125->(null)
    W(87)->87->28->W
    o(111)->111->42->o
    r(114)->114->45->r
    l(108)->108->26->l
    d(100)->100->47->d
    !(33)->0->125->(null)
    (32)->0->125->(null)
    W(87)->87->28->W
    e(101)->101->41->e
    (32)->0->125->(null)
    a(97)->97->40->a
    r(114)->114->45->r
    e(101)->101->41->e
    (32)->0->125->(null)
    i(105)->105->39->i
    n(110)->110->44->n
    t(116)->116->46->t
    e(101)->101->41->e
    r(114)->114->45->r
    n(110)->110->44->n
    a(97)->97->40->a
    t(116)->116->46->t
    i(105)->105->39->i
    o(111)->111->42->o
    n(110)->110->44->n
    a(97)->97->40->a
    l(108)->108->26->l
    (32)->0->125->(null)
    ((40)->0->125->(null)
    o(111)->111->42->o
    r(114)->114->45->r
    (32)->0->125->(null)
    a(97)->97->40->a
    t(116)->116->46->t
    (32)->0->125->(null)
    l(108)->108->26->l
    e(101)->101->41->e
    a(97)->97->40->a
    s(115)->115->43->s
    t(116)->116->46->t
    (32)->0->125->(null)
    w(119)->119->28->w
    e(101)->101->41->e
    (32)->0->125->(null)
    t(116)->116->46->t
    r(114)->114->45->r
    y(121)->121->48->y
    (32)->0->125->(null)
    t(116)->116->46->t
    o(111)->111->42->o
    ,(44)->0->125->(null)
    (32)->0->125->(null)
    a(97)->97->40->a
    s(115)->115->43->s
    (32)->0->125->(null)
    t(116)->116->46->t
    h(104)->104->30->h
    e(101)->101->41->e
    (32)->0->125->(null)
    w(119)->119->28->w
    o(111)->111->42->o
    r(114)->114->45->r
    l(108)->108->26->l
    d(100)->100->47->d
    (32)->0->125->(null)
    i(105)->105->39->i
    s(115)->115->43->s
    (32)->0->125->(null)
    p(112)->112->55->p
    e(101)->101->41->e
    r(114)->114->45->r
    (32)->0->125->(null)
    d(100)->100->47->d
    e(101)->101->41->e
    f(102)->102->32->f
    i(105)->105->39->i
    n(110)->110->44->n
    i(105)->105->39->i
    t(116)->116->46->t
    i(105)->105->39->i
    o(111)->111->42->o
    n(110)->110->44->n
    )(41)->0->125->(null)
    58)->0->125->(null)
    (32)->0->125->(null)
    (-42)->0->125->(null)
    (-36)->0->125->(null)
    (-60)->0->125->(null)
    (32)->0->125->(null)
    (-10)->0->125->(null)
    (-4)->0->125->(null)
    (-28)->0->125->(null)
    (-33)->0->125->(null)
    (32)->0->125->(null)
    (-55)->0->125->(null)
    (-23)->0->125->(null)
    (32)->0->125->(null)
    (-56)->0->125->(null)
    (-24)->0->125->(null)

    As one can see, a lot of characters get mapped to keysym 0/keycode 125.

    Here's the example code:

    ------------------------------------------------------------------------
    /* gcc -g -Wall -o xtst xtst.c -L/usr/X11R6/lib -lX11 -lXtst -lXext */

    #include
    #include
    #include

    int main() {
    Display *dpy = XOpenDisplay( NULL );
    static char *teststr = "Hello World! We are international (or at least we try to, as the world is per definition): ";
    int i;
    KeyCode kcode, cshift = XKeysymToKeycode(dpy, XStringToKeysym ("Shift_L"));
    KeySym ksym;
    char *kcodestr, a[2];

    a[1] = '\0';
    for (i = 0; teststr[i] != '\0'; ++i) {
    *a = teststr[i];
    ksym = XStringToKeysym(a);
    kcode = XKeysymToKeycode(dpy, ksym);
    kcodestr = XKeysymToString(ksym);
    /* printf("%c(%d)->%lu->%d->%s\n", *a, *a, ksym, kcode, kcodestr); */
    if(teststr[i] > 'A'-1 && teststr[i] < 'Z'+1)
    XTestFakeKeyEvent( dpy, cshift, True, CurrentTime );
    XTestFakeKeyEvent( dpy, kcode, True, CurrentTime );
    XTestFakeKeyEvent( dpy, kcode, False, CurrentTime );
    XTestFakeKeyEvent( dpy, cshift, False, CurrentTime );
    }

    XCloseDisplay(dpy);
    return 0;
    }
    ------------------------------------------------------------------------


    TIA again,
    olli

    Footnotes:
    [1] http://pebbles.schattenlauf.de/layout.php -- A mapping optimized
    for german.

    --
    GnuPG-Key: http://www.sopos.org/pgp/olli.asc
    GnuPG-Fingerprint: F27A BA8C 1CFB B905 65A8 2544 0F07 B675 9A00 D827
    NP: Citizen Fish - "Mind Bomb"

  4. Re: XKeysymToKeycode et al.

    I previously posted:
    >> Don't confuse KeyCodes with ASCII. They're equivalent to "keyboard
    >> row 2, third key from the left" and the meaning differs if you have a
    >> QWERTY keysym mapping instead of a Dvorak mapping.


    Oliver Heins writes:
    > Yes, I use the NEO mapping[1] and had to modify my .xmodmap therefore.
    > However, this seems to be more complicated and difficult than I first
    > thought. What I try to do is to pass a string of text to an application
    > in a way that it thinks the text was typed on a keyboard and thus gets
    > inserted. I want to use the XTestFakeKeyEvent function therefore.


    I'm not sure why you prefer XTestFakeKeyEvent() over XSendEvent(), since:

    1) the event recipient with XTestFakeKeyEvent depends on where the cursor
    is,

    2) it only works if the X server supports the XTEST extension, and

    3) XSendEvent lets you specify the modifiers directly instead of having to
    simulate modifier keypress and keyrelease events (although, depending
    on what exactly you're doing, complete simulation may be important),

    but that's your choice.

    [I'd never even heard of XTestFakeKeyEvent before. My thanks to Google
    for finding a description of it quickly. ]

    > For example, the text: "Hello World! We are international (or at least
    > we try to, as the world is per definition): "


    Anything that isn't a graphic ASCII character is going to be a bit of a
    problem. Ask yourself how exactly you entered those characters when you
    were typing the sentence above. I suspect it either involved some
    combination of modifier keys (Shift, Alt, Control, AltGraph, etc.) or used
    a multi-key sequence.

    XKeysymToKeycode doesn't get you the modifiers! It also won't tell you
    about any multikey sequences an application may have. If the KeyCodes for
    'M' and 'm' are the same, your program will have to know which modifiers to
    set if you need the recipient of the simulated Event to see 'M' instead of
    'm'.

    I'm not even sure how to build a char[1] => keycode+modifiers table in a
    general way. I guess one could try all possible keycode and modifier
    combinations, record the result, and build an inverse map, using
    XKeysymToKeycode to resolve cases where >1 keycode produces the same
    KeySym. Of course, that completely ignores the problem that there can be
    single keys (like F1 or keypad keys) that can produce multicharacter
    sequences.

    If that's not a problem, or if you're willing to build in some mapping
    between char[1] and keycode+modifiers, then you can make the built-in table
    have enough info for an XSendEvent event. (With XTestFakeKeyEvent, it
    looks like you'd need to simulate however many presses and releases of the
    modifier keys are needed to get to the next state.)

    OTOH, if it's important to your test to emulate modifier key presses and
    releases, I'd say your best bet is going to be to write a program to log
    actual key events as some user types them to do whatever, then edit that
    log as needed for your test.


    > I have no idea how to get the space translated,

    ...
    > (32)->0->125->(null)


    StringToKeysym is not (Char)ToKeysym -- it wants a KeySym name, not the
    ASCII/UTF-8/etc. character. The reason spaces were getting deleted by the
    test program is that the keysym string name for 0x20/' ' is "Space", not
    " " (as the simple a[2] was doing). To get the space to work in the
    example of "Hello World",

    ksym = (*a == ' ') ? "space" : XStringToKeysym(a);

    should be enough. However, see /usr/include/X11/keysymdef.h for the very
    long list of ASCII Keysym names for the non-ASCII and non-graphic
    characters.

    > TIA again,


    You're welcome again.
    -WBE

+ Reply to Thread