Если есть люди, разбирающиеся в коде иксов, помогите выяснить причину такого поведения. Суть в следующем:
Когда клиент слушает KeyPress и KeyRelease для собственных окон, все сообщения приходят как и ожидается. Если же клиент слушает ввод для окна, которое создано другим клиентом, то перед каждым KeyPress он получает фейковый KeyRelease для этой же клавиши.
Например, запускаем xev с собственным окном и запускаем второй xev, который натравливаем на окно первого. Первый получает такие события:
KeyPress event, serial 41, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7167984, (838,-77), root:(953,658),
state 0x0, keycode 65 (keysym 0x20, space), same_screen YES,
XLookupString gives 1 bytes: (20) " "
XmbLookupString gives 1 bytes: (20) " "
XFilterEvent returns: False
KeyRelease event, serial 41, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7168102, (838,-77), root:(953,658),
state 0x0, keycode 65 (keysym 0x20, space), same_screen YES,
XLookupString gives 1 bytes: (20) " "
XFilterEvent returns: False
KeyPress event, serial 41, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7174348, (838,-77), root:(953,658),
state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 41, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7174453, (838,-77), root:(953,658),
state 0x1, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
KeyPress event, serial 41, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7176414, (838,-77), root:(953,658),
state 0x0, keycode 24 (keysym 0x71, q), same_screen YES,
XLookupString gives 1 bytes: (71) "q"
XmbLookupString gives 1 bytes: (71) "q"
XFilterEvent returns: False
KeyRelease event, serial 41, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7176494, (838,-77), root:(953,658),
state 0x0, keycode 24 (keysym 0x71, q), same_screen YES,
XLookupString gives 1 bytes: (71) "q"
XFilterEvent returns: False
А второй в это же время получает такие события:
KeyRelease event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7167984, (838,-77), root:(953,658),
state 0x0, keycode 65 (keysym 0x20, space), same_screen YES,
XLookupString gives 1 bytes: (20) " "
XFilterEvent returns: False
KeyPress event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7167984, (838,-77), root:(953,658),
state 0x0, keycode 65 (keysym 0x20, space), same_screen YES,
XLookupString gives 1 bytes: (20) " "
XmbLookupString gives 1 bytes: (20) " "
XFilterEvent returns: False
KeyRelease event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7168102, (838,-77), root:(953,658),
state 0x0, keycode 65 (keysym 0x20, space), same_screen YES,
XLookupString gives 1 bytes: (20) " "
XFilterEvent returns: False
KeyRelease event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7174348, (838,-77), root:(953,658),
state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
KeyPress event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7174348, (838,-77), root:(953,658),
state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7174453, (838,-77), root:(953,658),
state 0x1, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7176414, (838,-77), root:(953,658),
state 0x0, keycode 24 (keysym 0x71, q), same_screen YES,
XLookupString gives 1 bytes: (71) "q"
XFilterEvent returns: False
KeyPress event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7176414, (838,-77), root:(953,658),
state 0x0, keycode 24 (keysym 0x71, q), same_screen YES,
XLookupString gives 1 bytes: (71) "q"
XmbLookupString gives 1 bytes: (71) "q"
XFilterEvent returns: False
KeyRelease event, serial 17, synthetic NO, window 0x1e00001,
root 0x199, subw 0x0, time 7176494, (838,-77), root:(953,658),
state 0x0, keycode 24 (keysym 0x71, q), same_screen YES,
XLookupString gives 1 bytes: (71) "q"
XFilterEvent returns: False
Поведение воспроизводится не только под xev, но в xneur. Т.е. определенно это не баг клиента, а фича иксов.
При чем, когда я вчера тестировал это поведение, то лишний KeyRelease приходил только для модификаторов. А сейчас, как видно по логу выше, он приходит и для алфавитных клавиш. Очень странно.
Используемая версия иксов: 1.10.3.901.
Копаясь в коде, я дошел до функции DeliverEventsToWindow() в файле dix/events.c, где происходит доставка сообщения сначала для «своего» клиента окна, а затем для всех остальных. Однако изучая, чем доставка для всех остальных отличается от доставки «своему», я не нашел ничего, что пролило бы свет на сабж. Единственное место, в котором подставляются фейковые KeyRelease — это функция TryClientEvents() (в том же файле), однако там KeyRelease вставляется для обработки удержания клавиши при автоповторе и, вроде бы, не имеет отношения к проблеме.
Если такое поведение в иксах было сделано специально, то для чего именно? Или же это баг? Гугл не помог.