【问题标题】:xcb key repeat ignoring not workingxcb 键重复忽略不工作
【发布时间】:2015-07-26 21:30:17
【问题描述】:

我一直试图弄清楚如何忽略 xcb 事件循环中的重复键,到目前为止已经得到了这个:

extern xcb_connection_t *connection;

// looks like there's a leak, but in the finished product there isn't    
bool poll_event(/*my_event_type e*/){
    static xcb_generic_event_t *ev = nullptr;
    static xcb_key_press_event_t *last_key_ev = nullptr;

    if(!(ev = xcb_poll_for_event(connection)))
        return false;

    switch(ev->response_type & ~0x80){
        case XCB_KEY_PRESS:{
            xcb_key_press_event_t *kp = static_cast<decltype(kp)>(ev);                

            if(last_key_ev &&
                    ((last_key_ev->response_type & ~0x80) == XCB_KEY_RELEASE) &&
                    (last_key_ev->detail == kp->detail) &&
                    (last_key_ev->time == kp->time)
                ){
                std::free(last_key_ev);
                last_key_ev = kp;

                // is repeated key, ignore this event

                return false;
            }

            std::free(last_key_ev);
            last_key_ev = kp;
            return true;
        }

        case XCB_KEY_RELEASE:{
            /* same as KEY_PRESS but looking for KEY_PRESS in 'last_key_ev' */
        }

        default:
            std::free(ev);
            return true;
    }
}

这不起作用,因为它只会丢弃重复事件对的后半部分(XCB_KEY_RELEASE 然后XCB_KEY_PRESS),所以我得到一堆XCB_KEY_RELEASE 事件而不是没有。但是在xcb中似乎没有一个函数可以在不修改队列本身的情况下测试队列中是否有事件。

我正在寻找XEventsQueued equivalent in xcb,这样我就可以测试是否有事件直接排队,而不是使用最后发生的事件,但还没有这样做。

你们中的任何人是否已经这样做并愿意在这件事上传授你的智慧?

【问题讨论】:

  • 你为什么要检查时间戳?
  • @n.m.因为重复事件作为一对同时发生的事件发生。
  • 可能发布事件和下一个新闻事件是同时发生的,而不是相反?
  • @n.m.我知道为什么它不起作用,我只是想找到一种方法来检查事件队列,而无需创建自己的包装 xcb 的方法。
  • 不,XCB 不允许您查看队列。这是他们的设计决定。

标签: c++ x11 xcb


【解决方案1】:

所以,@n.m 说 XCB 没有用于在事件队列中达到峰值的实用程序。所以我在 xcb 事件队列上编写了自己的包装器,这样我就可以进入下一个事件。如果有人感兴趣,我是这样实现的:

首先我的事件队列:

extern xcb_connection_t *connection;

struct my_event_queue_t{
    xcb_generic_event_t *prev = nullptr;
    xcb_generic_event_t *current = nullptr;
    xcb_generic_event_t *next = nullptr;
} event_queue;

void update_event_queue(){
    std::free(event_queue.prev);
    event_queue.prev = event_queue.current;
    event_queue.current = event_queue.next;
    event_queue.next = xcb_poll_for_queued_event(connection);
}

然后是事件循环:

struct my_event_type;

bool poll_event(my_event_type &ret){
    static xcb_generic_event_t *xcb_ev = nullptr;
    update_event_queue();

    xcb_ev = event_queue.current;
    if(!xcb_ev) return false;

    switch(xcb_ev->response_type & ~0x80){
        case XCB_KEY_RELEASE:{
            static xcb_key_press_event_t *kp = nullptr;
            kp = xcb_ev;

            if(event_queue.next &&
                    ((event_queue->response_type & ~0x80) == XCB_KEY_PRESS) &&
                    (reinterpret_cast<decltype(kp)>(xcb_ev)->time == kp->time) &&
                    (reinterpret_cast<decltype(kp)>(xcb_ev)->detail == kp->detail)
                ){
                update_event_queue(); // eat repeat event
                return false;
            }

            // update ret
            return true;
        }

        case XCB_KEY_PRESS:{
            // handle normally
            // update ret
            return true;
        }

        default:
            // signify unknown event
            return true;
    }
}

这就是我在我的应用程序中忽略重复键的方式,这是一个用于游戏/图形应用程序开发的工具包。我还没有测试过这会带来什么样的性能下降,但它应该是最小的。

【讨论】:

    猜你喜欢
    • 2015-10-15
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 2015-05-25
    • 2012-08-04
    相关资源
    最近更新 更多