xdotool, клавиша ctrl и раскладки клавиатуры

Проблема

Я использую xdotool keydown Control и xdotool keyup Control из своего приложения для эмуляции нажатий Ctrl. Когда макет установлен на us, все работает, но когда макет меняется на что-то другое (fr или ru), приложения перестают видеть события ctrl.

Вопрос

Почему это происходит? Что я могу сделать, чтобы манипуляции с клавишей Ctrl работали одинаково во всех макетах?

Некоторая информация

Команда, которую я использую для настройки макетов:

setxkbmap -layout us,fr -option -option "grp:lctrl_lshift_toggle,ctrl:nocaps"

Вывод из xev с макетом us:

KeyPress event, serial 25, synthetic NO, window 0x4a00001,
    root 0x5c, subw 0x0, time 11278564, (317,709), root:(1279,736),
    state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

KeyRelease event, serial 28, synthetic NO, window 0x4a00001,
    root 0x5c, subw 0x0, time 11278676, (317,709), root:(1279,736),
    state 0x14, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False

Вывод из xev с макетом fr:

KeyPress event, serial 109, synthetic NO, window 0x4a00001,
    root 0x5c, subw 0x0, time 11343218, (312,520), root:(1274,547),
    state 0x2010, keycode 8 (keysym 0xffe3, Control_L), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

MappingNotify event, serial 109, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 109, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 109, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 109, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 109, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 109, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 109, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 116, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 116, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 116, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 116, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 116, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 116, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 116, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

KeyRelease event, serial 123, synthetic NO, window 0x4a00001,
    root 0x5c, subw 0x0, time 11343460, (312,520), root:(1274,547),
    state 0x2010, keycode 8 (keysym 0xffe3, Control_L), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False

MappingNotify event, serial 123, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 123, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 123, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 123, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 123, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 123, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

MappingNotify event, serial 123, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 1

Подробный вывод setxkbmap:

Setting verbose level to 10
locale is C
Applied rules from evdev:
rules:      evdev
model:      pc105
layout:     us,fr
options:    grp:lctrl_lshift_toggle,ctrl:nocaps
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete
compat:     complete
symbols:    pc+us+fr:2+inet(evdev)+group(lctrl_lshift_toggle)+ctrl(nocaps)
geometry:   pc(pc105)
xkb_keymap {
  xkb_keycodes  { include "evdev+aliases(qwerty)"   };
  xkb_types     { include "complete"    };
  xkb_compat    { include "complete"    };
  xkb_symbols   { include "pc+us+fr:2+inet(evdev)+group(lctrl_lshift_toggle)+ctrl(nocaps)"  };
  xkb_geometry  { include "pc(pc105)"   };
};

Вывод xmodmap для управления:

$  xmodmap -pme | grep -i control
control     Control_L (0x25),  Control_L (0x42),  Control_R (0x69)
$  xmodmap -pke | grep -i control
keycode  37 = Control_L Control_L Control_L Control_L
keycode  66 = Control_L Control_L Control_L Control_L
keycode 105 = Control_R NoSymbol Control_R

person Rogach    schedule 11.08.2015    source источник


Ответы (1)


Как видно из вывода xev, в режиме us нажатие клавиши Control_L эквивалентно коду клавиши 37 с изменением состояния с 0x10 на 0x14, тогда как в режиме fr В режиме у вас есть ключевой код 8 и состояние 0x2010, которое не меняется, и несколько событий MappingNotify.

состояние – это растровое изображение модификаторов, применяемых в данный момент, например, shift, control, alt и т. д. Их можно показать с

xmodmap -pme

который, например, для меня (на совершенно другой настройке клавиатуры) в настоящее время

shift       Shift_L (0x32),  Shift_R (0x3e)
lock      
control     Control_L (0x25),  Control_L (0x42),  Control_R (0x69)
mod1        Meta_R (0x86)
mod2        Num_Lock (0x4d)
mod3      
mod4      
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

В них перечислены 8-битные позиции в состоянии со следующими параметрами:

  1. сдвиг = бит 0 (состояние 0x1),
  2. замок = бит 1 (состояние 0x2),
  3. управление = бит 2 (состояние 0x4) и т. д.

Ваше состояние 0x2010 включает в себя значение 0x2000 за пределами этих 8 бит, так реализуются две раскладки клавиатуры в одной, и показывает, когда вы находитесь в режиме fr.

Если мы посмотрим, как работает xdotool, когда вы находитесь во втором сопоставлении клавиш, как показано в состоянии 0x2000, он ищет Control_L, чтобы найти код клавиши, затем ищет код клавиши в столбцах xmodmap -pke для текущего состояния и не находит Control_L. Таким образом, он берет запасной код клавиши 8 и временно изменяет сопоставление таким образом, что код клавиши 8 = keysym Control_L, а затем отправляет это событие клавиши. К сожалению, этого кода клавиши нет в отображении модификатора для управляющего бита.


Так что, возможно, сработает, если вы измените сопоставление, которое у вас есть для кода ключа 37, чтобы все столбцы имели Control_L. Я не знаю, сколько у вас столбцов, но сделайте xmodmap -pke | grep 'keycode 37' и посчитайте их, а затем измените их все, например:

xmodmap -e 'keycode 37 = Control_L Control_L Control_L Control_L'

Как упоминалось в комментариях, xdotool key может принимать десятичные числа кода клавиши вместо аргументов keysym. Это не упоминается на справочных страницах.

person meuh    schedule 11.08.2015
comment
У меня уже есть 'код ключа 66 = Control_L Control_L Control_L Control_L' в моей настройке, поэтому, исходя из этого, он должен найти Control_L в сопоставлении? - person Rogach; 11.08.2015
comment
Замена 37 на все Control_L также не меняет этого. - person Rogach; 11.08.2015
comment
@Rogach, не могли бы вы добавить вывод xmodmap -pme|grep control и xmodmap -pke|grep Control в свой исходный пост? - person meuh; 11.08.2015
comment
Конечно, добавлено в нижней части вопроса. - person Rogach; 11.08.2015
comment
@Rogach В вашем выводе xev исходное состояние равно 0x2010, поэтому у вас должен быть отключен еще один модификатор, поэтому, возможно, 4 столбца недостаточно. попробовать 6 или 8? - person meuh; 11.08.2015
comment
xmodmap -e игнорирует все остальные столбцы (по-прежнему получает 4 в выводе xmodmap -e). В настоящее время я пытаюсь отправить 37-й код ключа напрямую с помощью библиотеки xdotool c, но пока без особого успеха. - person Rogach; 11.08.2015
comment
@Rogach, вы можете использовать xdotool для отправки кода ключа, просто используйте десятичное число вместо символа ключа. xdotool key 37. - person meuh; 11.08.2015
comment
Отправка кода ключа напрямую работает. Здорово! Я должен был читать документацию более тщательно. Большое спасибо! - person Rogach; 11.08.2015
comment
Я не думаю, что использование кода ключа упоминается на странице руководства. Я видел это в источниках. - person meuh; 11.08.2015