xcb ignoring repeated keys
Asked Answered
V

2

10

I am trying to work out how to ignore repeated keys when using xcb for input.

I need something like this acheives:

uint32_t mask = XCB_KB_AUTO_REPEAT_MODE;
uint32_t values[] = {XCB_AUTO_REPEAT_MODE_OFF, None};

xcb_change_keyboard_control(xcb_connection, mask, values);

but without affecting the whole system.

I have read Ignore auto repeat in X11 applications, but I can't translate it to xcb. Namely, I can't find an xcb equivalent to XEventsQueued.

How do I go about doing this?

Viminal answered 24/7, 2015 at 17:42 Comment(1)
Does adding a comment bump the post? Come on! I don't want to revert back to using XLib just for this :/Viminal
V
3

After getting a notification about this post just recently I thought I would add what my solution finally was when I came across the problem again.

I created my own event queue and polled that for events:

class event_queue{
    public:
        ~event_queue(){
            free(curr);
            free(prev);
            free(next);
        }

        xcb_generic_event_t *curr = nullptr, *prev = nullptr, *next = nullptr;
};

namespace {
    event_queue internal_eventq;
}

xcb_generic_event_t *poll_event(xcb_connection_t *conn){
    if(internal_eventq.curr){
        free(internal_eventq.prev);
        internal_eventq.prev = internal_eventq.curr;
    }
    internal_eventq.curr = internal_eventq.next;
    internal_eventq.next = xcb_poll_event(conn);
    return internal_eventq.curr;
}

So I can could check the previous and next events.

Next I changed my input function to use the new polling function and changed how I handle key presses:

// in same scope as 'poll_event'
void handle_events(xcb_connection_t *conn){
    while(auto ev = poll_event(conn)){
        switch(ev->response_type){
            case /* xcb key press */:{
                if(
                    (internal_eventq.next == /* xcb key release */) &&
                    (internal_eventq.next->keysym == ev->keysym) &&
                    (internal_eventq.next->time == ev->time)
                ){
                    free(internal_eventq.next);
                    internal_eventq.next = nullptr; // ignore release part of key repeat
                    return; // ignore key repeat
                }

                break;
            }

            default:
                break;
        }
    }
}

Which was a bit of a hassle, but I imagine it is similar to how Xlib handles it's event queue behind the scenes.

Viminal answered 8/3, 2016 at 23:18 Comment(0)
D
0

It's not documented. But everything you need is in XCB.

  • Make sure you link to xcb & xcb-xkb
  • #include <xcb/xcb.h> & <xcb/xkb.h>
  • After making your connection to the server do the following:


    //Initialize the X Keyboard (xkb) support extention
    xcb_xkb_use_extension(conn, 
                          XCB_XKB_MAJOR_VERSION, 
                          XCB_XKB_MINOR_VERSION);
    

    
    //Set the per client detectable auto repeat flag
    xcb_xkb_per_client_flags(conn,
                          XCB_XKB_ID_USE_CORE_KBD,                                                       
                          XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT,
                          1,0,0,0);


This will make the key messages behave like Windows. There will be no "virtual" key up messages anymore. Other apps will not be affected.

Dipteral answered 14/5, 2022 at 0:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.