Вот решение, которое я придумал.
XEvent event;
while(1)
{
XNextEvent(display, &event);
switch(event.type)
{
// Other cases
case ...:
...
break;
...
// On KeyRelease
case KeyRelease:
{
char keys[32];
XQueryKeymap(display, keys);
if(!(keys[event.xkey.keycode>>3] & (0x1 << (event.xkey.keycode % 8))))
{
// Stuff to do on KeyRelease
...
}
}
break;
// On KeyPress
case KeyPress:
// Stuff to do on KeyPress
...
break;
default:
...
}
}
Итак, каждый раз, когда я получаю событие KeyRelease, я использую XQueryKeymap
, который будет копировать в keys
биты нажатых клавиш (8 различных клавиш char
).
Для тех, кто не привык работать с побитовыми операциями и оператором сдвига, вот простое объяснение:
keys[event.xkey.keycode>>3]
поиск индекса event.xkey.keycode / 8
с использованием «оператора сдвига вправо» (который допускает «целочисленное деление» на 2, 4, 8, 16 и т. Д., Без приведения типа к числу с плавающей или двойной и обратно к целому числу) .
0x1 << (event.xkey.keycode % 8)
делает опозит. Умножает значение 0x1
(== 1
) на 2, повышенное до (event.xkey.keycode % 8)
Битовый оператор &
между keys[event.xkey.keycode>>3]
и 0x1 << (event.xkey.keycode % 8)
будет сравниваться, если бит only , установленный в правом операнде, установлен в 1 внутри этого индекса массива. Если так, то клавиша нажимается.
Наконец, вы просто заключаете его в ()
с !
прямо перед этим, и если результат становится истинным, вы больше не нажимаете эту клавишу.
Один финал Примечание : Чтобы использовать этот метод, вам нужно постоянно кормить XServer событиями. Если нет, XQueryKeymap будет зависать до тех пор, пока это не произойдет (лучше использовать с потоками).