LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-02-2016, 11:18 PM   #1
mdooligan
Member
 
Registered: Feb 2009
Location: Vancouver BC
Distribution: Mandrake10/ArchHackery/Gentoo
Posts: 179

Rep: Reputation: 22
xterm, key modifiers, and /dev/event0...


This all started by wanting to tell the difference between CTRL-A and CTRL-SHIFT-A in ncurses list app in xterm.

I used to get keymods with this:
Code:
#include <sys/ioctl.h>
unsigned int key_get_mods ( void ) {
    unsigned int mods = 0;
    unsigned char modifiers;
    modifiers = 6;
    if ( ioctl ( 0, TIOCLINUX, &modifiers ) < 0 )
        return 0;
    mods = (unsigned int) modifiers;
    return mods;
}
but it returns 0 under xterm, and all of it's ilk. So I go looking and discover /dev/input/event0. I like to program in C so I knock together a little set of routines that work in loop like GTK/etc, you just call keyhandler_init(), then keyhandler_iter() every time through.

I works great. It works so good it reads ALL events, even when you hide window/change workspaces. It works like Kalashnikov, so good it's dangerous. I realize I could log in to other PC and read keystrokes of person typing at that box. I realize this is why I don't hear much about /dev/event0. This is not for civilian use. I have to teach it to watch window focus and sleep when window_id != focus_id, then wake up, clear out last event mess, and get back to work when window_id == focus_id. It needs mandatory usleep(1000) just to be reasonable.

So I have little power library of about 300 lines with a keytable lookup of about the same. I get perfect keyboard input without all that ncurses/terminfo dog and pony show. You want Cyryllic? Tweak the keytable. Klingon? ditto.

Why has this not been done yet? I can't find anything out there.
 
Old 01-03-2016, 12:57 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,863
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Or xmodmap/xkb could be used for this.
 
Old 01-04-2016, 06:39 PM   #3
mdooligan
Member
 
Registered: Feb 2009
Location: Vancouver BC
Distribution: Mandrake10/ArchHackery/Gentoo
Posts: 179

Original Poster
Rep: Reputation: 22
I don't think you can redefine CTRL-SHIFT-A with xmodmap to something ncurses can understand. The entries are normal, shift, mode_switch, and shift+mode_switch. Mode_switch is usually Right Alt key. Then that affects everything system wide, and I don't want to modify the whole system just so one little app can read the shift key.

All I needs is XGetKeyModifiers(display, &mods) or something like it, but I can't find the command. If you know of one, please enlighten me.

If I read XEvents, xterm gobbles up the keyboard ones before I can get to them, so all I get is what xterm didn't use.

But still, I stopped actually using ncurses years ago. I still copy the #defines and stuff because they seem kinda standard, but I stay as far away from terminfo etal as I can. Even gnome-terminal uses 'xterm' settings.

As far as screen drawing goes, you only need a few functions: term_goto(), term_printf(), term_hide_cursor(), term_color(), and term_raw(). I also have clrtoeol(), and a couple funny ones like term_graf_map() for line drawing and term_save/restore(), but they seem to use the same codes in all terminals.

How many terminfo db entries are still in common use these days? 3 or 4? "linux", "xterm*", "rxvt"...
Why did every terminal emulator think they needed to make their own custom F-Key sequences? How about the HOME/END gong show? They never work in ncurses without some special define_key() hocus pocus anyway. I'm beginning to rant

Anyway, this bypasses the issue completely and reads the keyboard directly. Scancodes are universal. No "\033[OP" and stuff anymore. Linux kernel has had /dev/input/event0 for more than a decade, so it's here to stay. I just wonder why I have no luck finding anything about it. I'd like to see how others handled the few issues I encountered.
 
Old 01-13-2016, 06:40 AM   #4
mdooligan
Member
 
Registered: Feb 2009
Location: Vancouver BC
Distribution: Mandrake10/ArchHackery/Gentoo
Posts: 179

Original Poster
Rep: Reputation: 22
Well, I figured out why /dev/event0 isn't used much.

I has a major limitation: It only reads the actual physical input device attached to the PC.

That means it cannot be used during remote logins. Unless you like lots of zeroes.

I suppose that also means it can be used to determine if the user is actually sitting at the PC. Maybe some kind of security thing.

Anyone know how to reliably read the modifier keys in xterm/etc? How to peek events before xterm nabs them? Even just watch a single key for activity?
 
Old 01-13-2016, 07:20 AM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,863
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
I suggest you either create an X-application, and use every features of XKeyEvent; or create a console-application, and settle for the functions of ncurses/terminfo.
 
Old 01-17-2016, 02:32 AM   #6
mdooligan
Member
 
Registered: Feb 2009
Location: Vancouver BC
Distribution: Mandrake10/ArchHackery/Gentoo
Posts: 179

Original Poster
Rep: Reputation: 22
I found something: XQueryKeymap().
Code:
#include <X11/Xlib.h>
int main (int argc, char **argv)
{
    int done = 0;
    char keymap[32];
    Display *mydisplay;

    mydisplay = XOpenDisplay("");

    while ( !done ) {
        XQueryKeymap(mydisplay, keymap);
        int i;
        for (i = 0; i < 32; i++) {
            printf("02X", keymap[i]);
        }
        printf("\n");
        usleep (1000000);
    }

    return done;
}
This test code shows the keyboard state once per second. You only need to include one extra header, and use gcc -lX11. Simple.

XQueryKeymap() shows the state of the keyboard even if something else (like xterm) is gobbling key events. Just call it when you need to know, and parse keymap to your liking.

The keyboard state is returned as a 256 bitfield. SHIFT_L is byte 6 bit 2, and SHIFT_R is byte 7 bit 6.
Code:
KEYMOD_SHIFT_L = keymap[6] & (1<<2);
KEYMOD_SHIFT_R = keymap[7] & (1<<6);
I think I've solved my problem with a portable solution. /dev/event0 is a pain to handle too, very low level, a lot of parsing to get something usable. Now I can go back to using getc(), which is very convenient. Check getenv("DISPLAY") to see if X is running, and use this function if so, the other ioctl() if not.

Ba-ding!

Last edited by mdooligan; 01-17-2016 at 03:24 AM.
 
Old 01-17-2016, 02:59 AM   #7
mdooligan
Member
 
Registered: Feb 2009
Location: Vancouver BC
Distribution: Mandrake10/ArchHackery/Gentoo
Posts: 179

Original Poster
Rep: Reputation: 22
https://tronche.com/gui/x/xlib/input/XQueryKeymap.html
 
Old 01-17-2016, 03:30 AM   #8
mdooligan
Member
 
Registered: Feb 2009
Location: Vancouver BC
Distribution: Mandrake10/ArchHackery/Gentoo
Posts: 179

Original Poster
Rep: Reputation: 22
XQueryKeymap() also reads keyboard regardless of window focus. So if you called it 3 or 4 times per second you could potentially get key "events" by watching the bits change, even when the window doesn't have focus.
 
Old 01-17-2016, 04:14 AM   #9
mdooligan
Member
 
Registered: Feb 2009
Location: Vancouver BC
Distribution: Mandrake10/ArchHackery/Gentoo
Posts: 179

Original Poster
Rep: Reputation: 22
This should tell you everything you need to know about the state of your keyboard modifiers in a XWindows terminal emulator of any sort:
Code:
#include <X11/Xlib.h>
/*--------------------------------------------------------------------------*/
int main (int argc, char **argv)
{
    int done = 0;
    char keymap[32];
    char keypressed = 0;
    Display *mydisplay = XOpenDisplay("");

    while ( !done ) {
        keypressed = 0;
        XQueryKeymap(mydisplay, keymap);
        int i;
        for (i = 0; i < 32; i++) {
            if (keymap[i])
                printf("%02i:%02X.", i, keymap[i]);
            keypressed |= keymap[i];
        }
        char KEY_SHIFT_L  = keymap[6]  & (1<<2);
        char KEY_SHIFT_R  = keymap[7]  & (1<<6);
        char KEY_CAPSLOCK = keymap[8]  & (1<<2);
        char KEY_CTRL_L   = keymap[4]  & (1<<5);
        char KEY_CTRL_R   = keymap[13] & (1<<1);
        char KEY_WIN_L    = keymap[16] & (1<<5);
        char KEY_WIN_R    = keymap[16] & (1<<6);
        char KEY_ALT_L    = keymap[8]  & (1<<0);
        char KEY_ALT_R    = keymap[13] & (1<<4);
        char KEY_MENU     = keymap[16] & (1<<7);
        if (KEY_SHIFT_L||KEY_SHIFT_R||KEY_CAPSLOCK) 
            printf("SHIFT");
        if (KEY_WIN_L||KEY_WIN_R) 
            printf("WIN");
        if (KEY_CTRL_L||KEY_CTRL_R) 
            printf("CTRL");
        if (KEY_ALT_L||KEY_ALT_R) 
            printf("ALT");
        if (KEY_MENU) 
            printf("MENU");
        if (keypressed)
            printf("\n");
        usleep (1000000);
    }
    return done;
}
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to simulate arrow keys and key up / key down events to /dev/input phishGuy22 Linux - Software 1 10-17-2012 03:56 PM
Who owns /dev/input/event0 ? Xaphoid Linux - Hardware 1 10-30-2006 06:22 PM
xterm and key shortcuts dame Linux - Software 3 03-28-2005 07:02 PM
xterm meta key bob66 Linux - Software 0 03-25-2005 09:26 AM
kde "keyboard shortcuts": can't change modifiers & says no windows key peb Linux - Newbie 0 01-02-2004 04:41 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:48 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration