Программирование под Linux.
в иксах (X11) при нажатии клавиши я получаю событие XKeyEvent с кодом клавиши, состоянием модификаторов (Ctrl, Alt) и прочей информацией. Но я так и не нашел информацию о том, была ли эта клавиша реально нажата, или это многократный авто-повтор при удерживании.
для сравнения: в WinAPI с событием WM_KEYDOWN приходит параметр lParam, один из битов которого как раз является флагом - "нажато руками" или "повтор при удерживании":
if (lParam & 0x40000000) { // повтор при удерживании } else { // нажато руками };
А как быть с иксами?
параметром auto_repeat_mode, устанавливамый в XKeyboardControl, здесь воспользоваться не удастся: мне не надо отключать повторы, мне надо определять их.
попробуй сохрани предыдущее состояние клавиши...
если предыдущее false и новое true => нажата
если предыдущее true и новое true => зажата
если предыдущее true и новое false => отжата
если предыдущее false и новое false => ничего
думаю так...
хм, и правда :) массив keymap я свой уже сделал, а использовать его для этой цели не подумал. спасибо, попробую.
всё же странно, что API не предусматривает такой, казалось бы важный, флаг. ничего не упустили?
Неа, так не прокатит.
При удерживании сыпятся сообщения и о нажатии (KeyPress), и об отпускании (KeyRelease), то есть никак невозможно отличить ручное многократное нажатие от автоматического.
Еще идеи? всё же кажется, что API должен предусматривать разницу...
ALPINE
> Еще идеи?
Ну, можно еще позвать XQueryKeymap(), и узнать действительное состояние кнопки.
RPGman
> Ну, можно еще позвать XQueryKeymap(), и узнать действительное состояние кнопки.
я с никсами не знаком, но рискну предположить, что не очень верная идея. сообщенияже наверняка асинхронные?
т.е. допустим FPS = 10 (100мс). за это время мы действительно несколько раз нажали и отпустили клавишу (ну например удаляем несколько введенных символов). и что покажет функция возвращающая реальное состояние клавиши - уже не поможет определить - нажали несколько раз или один и удержали.
Нажимаешь на кнопку чаще десяти раз в секунду? Сурово. Школа ниндзя?
По теме - что-то мне подсказывает, что это было бы логически неправильно и так делать нельзя. Нужны только физические события - отключай повтор.
Kloun
> рискну предположить, что не очень верная идея
keltar
> Нужны только физические события - отключай повтор.
Вы не поняли.
Суть - по приходу события KeyRelease зовем XQueryKeymap(), она возвращает битовый массив состояний кнопок - нажата/отжата. Если для кейкода в событии KeyRelease состояние кнопки "нажата" - то это стопудофф автоповтор, и этот ивент можно спокойно проигнорировать.
Я добился методом тыка, но оно отлично работает!
While XPending(Display) > 0 do begin XNextEvent ( Display, @Event ); if Event._type = KeyRelease then begin scancode:= DivineScanCode(event); //defeat the auto-repeat feature! GotNext:= No; ItsAutoRepeat:= No; if XPending(Display) > 0 then begin GotNext:= Yes; XNextEvent ( Display, @NextEvent ); ItsAutoRepeat:= (NextEvent._type = KeyPress) and (NextEvent.xkey.keycode = Event.xkey.keycode) and (NextEvent.xkey.time = Event.xkey.time); end; if f_KeyState[scancode] and not ItsAutoRepeat then begin f_KeyState[scancode]:= false; OnRelease(scancode); end; if GotNext then Event:= NextEvent; end; case Event._type of KeyPress: begin ...
Короче, в каждом эвенте отпускания считываем следующий эвент. Если следующий - эвент нажатия, с идентичным временем и идентичной клавишей - решаем что это автоповтор, и игнорируем оба. Иначе обрабатывем следующий как положено
Суть - по приходу события KeyRelease зовем XQueryKeymap(), она возвращает битовый массив состояний кнопок - нажата/отжата.
я думаю, что и при авто-повторе биты будут прыгать, имитируя как раз-таки нажатость-отжатость. и по ним мы ничего не узнаем.
я с никсами не знаком, но рискну предположить, что не очень верная идея. сообщенияже наверняка асинхронные?
т.е. допустим FPS = 10 (100мс). за это время мы действительно несколько раз нажали и отпустили клавишу <...>
...и в следующем фрейме мы получили несколько пар событий KeyPress/KeyRelease и успешно обработали все по очереди. потеряно ничего не будет.
в каждом эвенте отпускания считываем следующий эвент. Если следующий - эвент нажатия, <...>
вот это уже круто :) спасибо за идею, думаю, это сработает. алгоритм, правда, не очень внушает доверия... но по идее сбоев быть не должно.
XAutoRepeatOff никак нельзя?
ALPINE
> я думаю, что и при авто-повторе биты будут прыгать
А не надо думать-гадать. Загляни в glut, и что делает glutIgnoreKeyRepeat().
Тема в архиве.