повтор ключа xcb игнорирование не работает

Я пытался выяснить, как игнорировать повторяющиеся ключи в цикле событий 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 эквивалент в xcb поэтому я мог проверить, есть ли событие, поставленное в очередь сразу после этого, вместо того, чтобы использовать последнее событие, которое произошло, но пока не удалось этого сделать.

Кто-нибудь из вас уже сделал это и хочет поделиться своей мудростью в этом вопросе?

0

Решение

Таким образом, @ 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;
}
}

Вот как я игнорирую повторения клавиш в моем приложении, которое является инструментарием для разработки игр / графических приложений. Я не проверял, какое снижение производительности это дает, но оно должно быть минимальным.

3

Другие решения


По вопросам рекламы [email protected]