X11 Keyboard issues

This is a discussion on X11 Keyboard issues within the Linux Programming forums, part of the Platform Specific Boards category; In a nutshell, a program of mine uses KeyPress and KeyRelease events to know the state of some keys. I ...

  1. #1
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    1,625

    X11 Keyboard issues

    In a nutshell, a program of mine uses KeyPress and KeyRelease events to know the state of some keys.

    I have noticed that the system sends my application both keyups AND keydowns when a key stays pressed, mostly like this:
    two makes, a break
    three makes, a break,
    two make, a break
    etc, etc
    I know that this is no hardware issue, because I run the same application on the same machine using Windows and it's doesn't display that strange behaviour.

    I'd like to know if there's a way to fix/change that.

    Using Ubuntu with Linux 3.0.0-13-generic
    And latest X11 libraries

    PS: I have also seen the same thing with Bochs.

    EDIT: Ops, my bad, please rellocate it.
    Devoted my life to programming...

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by GReaper View Post
    In a nutshell, a program of mine uses KeyPress and KeyRelease events to know the state of some keys.
    And these are X library events? Or something higher up? Just asking because:

    I run the same application on the same machine using Windows and it's doesn't display that strange behaviour.
    Implies this actually isn't about the X lib interface, since it doesn't exist on windows.

    Sounds like a pretty simple thing to demonstrate, tho. Why don't you post "the shortest possible program" doing so?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    1,625
    Quote Originally Posted by MK27 View Post
    Implies this actually isn't about the X lib interface, since it doesn't exist on windows.
    Oh, yeah, I didn't clarify. I meant that after converting it from X11 to Windows, WM_KEYDOWN and WM_KEYUP performed as expected, meaning there was no WM_KEYUP while the key was down!

    I'll return with a demostration program in a while.
    Devoted my life to programming...

  4. #4
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    1,625
    Sorry for taking so long, here it comes:

    The Windows code and screenshot:
    Code:
    #include <iostream>
    
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
    {
        WNDCLASSEX windowClass;
        HWND hwnd;
        MSG msg;
    
        windowClass.cbSize = sizeof(WNDCLASSEX);
        windowClass.style = CS_HREDRAW | CS_VREDRAW;
        windowClass.lpfnWndProc = WndProc;
        windowClass.cbClsExtra = 0;
        windowClass.cbWndExtra = 0;
        windowClass.hInstance = hInstance;
        windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        windowClass.hbrBackground = NULL;
        windowClass.lpszMenuName = NULL;
        windowClass.lpszClassName = "MyClass";
        windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
    
        if (!RegisterClassEx(&windowClass))
        {
            MessageBox(0, "Failed to register window!", "Error", 0);
            return -1;
        }
    
        hwnd = CreateWindowEx(0,
        "MyClass",
        "Press The Button!",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE |
        WS_SYSMENU | WS_CLIPCHILDREN |
        WS_CLIPSIBLINGS,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);
    
        if (!hwnd)
        {
            MessageBox(0, "Failed to create window!", "Error", 0);
            return -2;
        }
    
        ShowWindow(hwnd, SW_SHOW);
    
        while (GetMessage(&msg, NULL, 0, 0) != WM_QUIT)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            case WM_KEYDOWN:
                if (wParam == 'W')
                    std::cout << "Button Pressed!\n";
            break;
            case WM_KEYUP:
                if (wParam == 'W')
                    std::cout << "Button Released!\n";
            break;
            case WM_DESTROY:
                PostQuitMessage(0);
            break;
            default:
                return DefWindowProc(hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    Name:  WindowsTry.jpg
Views: 603
Size:  34.1 KB

    And here's Linux's:
    Code:
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <X11/XKBlib.h>
    #include <X11/Xatom.h>
    #include <X11/keysym.h>
    
    int main()
    {
        XVisualInfo* visual = 0;
        Window window = 0;   
        XSetWindowAttributes attributes;
        
        memset(&attributes, 0, sizeof(attributes));
        
        Display* display;
        int screennr;
        
        display = XOpenDisplay(0);
        if (!display)
            return -1;
        
        screennr = DefaultScreen(display);
        
        XVisualInfo visTemp;
        int visNumber;
        
        visTemp.screen = screennr;
        visTemp.depth = 24;
        while (!visual && visTemp.depth >= 16)
        {
            visual = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask, &visTemp, &visNumber);
            visTemp.depth -= 8;
        }
        
        Colormap colormap;
        colormap = XCreateColormap(display,
                RootWindow(display, visual->screen),
                visual->visual, AllocNone);
    
        attributes.colormap = colormap;
        attributes.border_pixel = 0;
        attributes.event_mask = StructureNotifyMask | FocusChangeMask | ExposureMask;
        attributes.event_mask |= PointerMotionMask |
                    ButtonPressMask | KeyPressMask |
                    ButtonReleaseMask | KeyReleaseMask;
        attributes.override_redirect = 0;
        
        window = XCreateWindow(display, RootWindow(display, visual->screen), 
                               0, 0, 800, 600, 0, visual->depth, 
                               InputOutput, visual->visual,
                               CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
                               &attributes);
        XMapRaised(display, window);
    	
        for (;;)
        {
            XEvent event;
            XNextEvent(display, &event);
                
            switch (event.type)
            {
                case KeyPress:
                {
                    long unsigned int X11Key;
                    char buf[8]={0};
                    XLookupString(&event.xkey, buf, sizeof(buf), &X11Key, NULL);
        
                    if (X11Key == XK_w)
                        std::cout << "Button Pressed!\n";
                }
                break;
                case KeyRelease:
                {
                    long unsigned int X11Key;
                    char buf[8]={0};
                    XLookupString(&event.xkey, buf, sizeof(buf), &X11Key, NULL);
        
                    if (X11Key == XK_w)
                        std::cout << "Button Released!\n";
                }
                break;
            }
        }
        
        return 0;
    }
    Name:  LinuxTry.png
Views: 320
Size:  61.0 KB

    In both I kept the button pressed as long as needed to fill the console with new data. You can see that the Linux case is hopeless... Am I doing something wrong?
    Devoted my life to programming...

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    It's because AutoRepeat is enabled by default on the X server. Notice the first press/release is longer than the subsequent ones? If you press and hold 'w' in a terminal or other window, after a second you start getting wwwwwwwwwwwwwww.

    There's some solutions suggested here:

    keyboard - Ignore auto repeat in X11 applications - Stack Overflow
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    1,625
    Thanks, that's what I've been looking for!
    Devoted my life to programming...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. New keyboard
    By VirtualAce in forum General Discussions
    Replies: 18
    Last Post: 06-04-2011, 05:32 PM
  2. Keyboard accelerator issues
    By Viper187 in forum Windows Programming
    Replies: 2
    Last Post: 09-02-2008, 10:25 AM
  3. Keyboard port using other that a keyboard
    By antoinelac in forum C++ Programming
    Replies: 4
    Last Post: 06-12-2008, 03:46 PM
  4. The OR || on keyboard, where is it?
    By Bassglider in forum C Programming
    Replies: 12
    Last Post: 12-11-2007, 12:17 AM
  5. Keyboard
    By alanair23 in forum C++ Programming
    Replies: 2
    Last Post: 01-17-2003, 06:42 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21