xmodmap теряется после сна

Вопрос или проблема

В Ubuntu 18.04 я использую следующий скрипт автозагрузки:

[Desktop Entry]
Type=Application
Exec=/home/user/.xinitrc
Version=1.0
X-GNOME-Autostart-enabled=true
Name=xmodmap
Comment=xmodmap script

который просто xmodmap /path/.Xmodmap &.

Когда система загружается, он работает. Когда система выходит из спящего режима, переназначение больше не работает. Как я могу это исправить?

ИЗМЕНЕНИЕ: (ответ на комментарий)
Это также не исправляет проблему:

$ cat /etc/systemd/system/xmodmapbindings.service
[Unit]
Description=xmodmap bindings
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStop=-/home/norake/.xinitrc

[Install]
WantedBy=sleep.target

$ cat ~/.xinitrc 
#!/bin/bash

if [ "$USER" != norake ]; then
    su norake -c 'sleep 5; /usr/bin/xmodmap /home/norake/.Xmodmap' &
    # без su, без sleep, без fork (&): тоже не работает
else
    (sleep 5; /usr/bin/xmodmap /home/norake/.Xmodmap) &
fi

sleep 30 также не работает. Конечно, скрипт, запущенный вручную, работает.

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

С точки зрения X сервера, клавиатура, подключенная после выхода из спящего режима, является новой клавиатурой, поэтому она подключается с стандартными настройками, так же как и вторая клавиатура.

Это известная проблема драйверов USB клавиатуры и будет сложной для исправления в ядре (поскольку USB переизмеряется при возобновлении, таким образом, нам нужен метод для сохранения идентичности устройства, даже если ему присваивается новый номер), и сложно исправить в X сервере (поскольку потребуется сохранять историю устройств).

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

Это мое простое кустарное решение для особого случая этой проблемы:

Моя клавиатура имеет клавишу Print, где должна быть клавиша Меню, поэтому мой xmodmap переназначает именно эту клавишу.

Я настроил сочетание клавиш (в gnome shell в моем случае) для клавиши Print, чтобы запустить

/bin/bash -c "/usr/bin/xmodmap $HOME/.Xmodmap"

Таким образом, после сна, в первый раз, когда я нажимаю клавишу Print, она вызовет xmodmap и с этого момента будет работать как клавиша меню.

(После этого у моей клавиатуры больше не будет клавиши Print.)

Этот подход должен работать, когда:

  1. Вам не жалко первоначального “слепого” нажатия клавиши.
  2. У вас есть хотя бы одна кнопка, которую вы знаете, что нажмете до того, как или как только переназначение станет актуальным.
  3. Первичный символ клавиши этой кнопки больше не присутствует в новом сопоставлении.

Обновление: С тех пор я усовершенствовал свое решение с помощью xdotool, чтобы также вызывать контекстное меню на этапе первоначального переназначения:

/bin/bash -c "xdotool keyup Print key --clearmodifiers Menu && /usr/bin/xmodmap $HOME/.Xmodmap"

Не забудьте заменить $USER на ваше реальное имя пользователя:

  1. Создайте свой файл .Xmodmap с сопоставлением, в моем случае это:

    keycode 96 = XF86AudioLowerVolume
    keycode 95 = XF86AudioMute
    keycode 76 = XF86AudioNext
    keycode 75 = XF86AudioPlay
    keycode 74 = XF86AudioPrev
    

    и поместите его по пути /home/$USER/.Xmodmap

  2. Создайте предпочтение для запуска приложения (перейдите в настройки запуска приложений из меню поиска по супер-кнопке) и добавьте следующее:

    Name: xmodmap
    Command: /bin/bash -c "sleep 7 && xmodmap ~/.Xmodmap"
    Comment: 
    

    и сохраните это. И закройте настройки запуска приложений

  3. Теперь перейдите в папку /usr/lib/systemd/system-sleep, вот так:

    cd /usr/lib/systemd/system-sleep
    
  4. Создайте файл с именем xkeyboard.sh. Вы можете сделать это так (требуются права sudo):

    sudo touch xkeyboard.sh
    
  5. Теперь получите значение вашей переменной $XAUTHORITY. Вы можете сделать это так:

    echo $XAUTHORITY
    

    В моем случае это вернёт следующее:

    /run/user/1000/gdm/Xauthority
    

    Запишите это где-нибудь.

  6. Откройте ваш вновь созданный файл для редактирования, вы можете сделать это так:

    sudo nano xkeyboard.sh
    
  7. Вставьте этот код. Убедитесь, что заменили $USER на ваше имя пользователя и $XAUTH на переменную, которую вы записали ранее:

    #!/bin/bash
    
    echo "Running xkeyboard.sh with argument: $1" >> /tmp/xkeyboard.log
    
    if [ "${1}" == "pre" ]; then
        echo "pre" >> /tmp/xkeyboard.log
        # Ничего не делать для предварительного сна
    elif [ "${1}" == "post" ]; then
        echo "post" >> /tmp/xkeyboard.log
        export DISPLAY=:0  # Установить переменную DISPLAY
        export XAUTHORITY=$XAUTH
        /bin/bash -c "sleep 7 && xmodmap home/$USER/.Xmodmap" >> /tmp/xkeyboard.log 2>&1
    fi
    

    В этом коде я добавил логирование в файл /tmp/xkeyboard.log, так что если сопоставление клавиатуры не работает, вы можете обратиться туда и проверить, в чем дело.

Вот рабочее решение, я получил помощь из различных источников, но в основном это написано мной. caps – это скрипт xmodmap (CapsLock => F13).

#!/bin/bash

USERN=cemkalyoncu
SCRIPT=/home/cemkalyoncu/Installed/caps

case $1 in
    post)
        DISPLAY=:0
        export DISPLAY
        su $USERN -c "$SCRIPT"
        #screen
        #su $USERN -c "sleep 30; kwin --replace &" &
    esac

Я также оставил kwin --replace, так как kwin иногда вызывает сбои и требует перезагрузки, но это не демон и должен быть отделен с помощью screen. Это только если вы используете KDE. Если не установлен, установите screen. Экспортирование дисплея здесь является ключом к его работе. Запуск от вашего имени также необходим. Даже если вы тот, кто возобновляет, это все равно не ваша учетная запись. Сон не требуется для xmodmap. Но kwin автоматически сбрасывается системой через несколько секунд после возобновления, но иногда может не сработать; таким образом, задержка необходима.

Если вам немного неприятно принуждать $DISPLAY и т.д. извне, маленький хак:

  1. Создайте небольшой скрипт, который будет работать постоянно:

xmodmapper.sh:

#!/bin/sh
while true; do
    echo "перезагрузка xmodmap"
    sleep 2
    xmodmap ~/.Xmodmap
    kill -STOP $$
done
  1. Запустите его как часть вашей X-сессии, например, добавьте ~/xmodmapper.sh & в ваш ~/.xinitrc

  2. Добавьте правило в какой-то файл udev правил:

например, /etc/udev/rules.d/80-keyboard.rule:

SUBSYSTEM=="usb", ACTION=="add",    ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="1b1c/1b2d/329", RUN+="/usr/bin/killall -CONT xmodmapper.sh"

и замените ENV{PRODUCT} на ваше USB-устройство – мое основано на этой строке syslog:

New USB device found, idVendor=1b1c, idProduct=1b2d, bcdDevice= 3.29

Это кажется мне немного более надежным, чем другие подходы, хотя YMMV. (Тем более, что у меня уже есть другие правила udev, связанные с клавиатурой.)

П.С. Сон важен, поскольку в противном случае возникает гонка, когда xmodmap вызывается до того, как Xorg успевает зарегистрировать клавиатуру, как только она подключена. Корректное решение, например, с помощью xev, оставлено на усмотрение читателя.

Ответ или решение

Решение проблемы с потерей xmodmap после сна в Ubuntu 18.04

Проблема

При использовании Ubuntu 18.04 после выхода из режима сна настройки клавиатуры, установленные с помощью xmodmap, теряются. Эта проблема связана с тем, что после пробуждения операционная система воспринимает подключенную клавиатуру как новое устройство, что приводит к сбросу всех нестандартных привязок.

Решения и подходы

Существует несколько подходов к решению этой проблемы, каждый из которых имеет свои плюсы и минусы.

1. Запуск xmodmap при старте сеанса

Для этого простейшего метода вам необходимо добавить команду xmodmap в настройки автозапуска приложений системы:

  1. Откройте меню «Запуск приложений» (Startup Applications).
  2. Добавьте новую запись с параметрами:
    • Название: xmodmap
    • Команда: /bin/bash -c "sleep 7 && xmodmap ~/.Xmodmap"
    • Комментарий: (оставьте пустым или добавьте пояснение).

Этот метод перезапустит настройки клавиатуры каждый раз при входе в систему, однако он не решает проблему при пробуждении из режима сна.

2. Использование системного юнита systemd для обработки спящего режима

Создание системы управления зависимостями позволит автоматизировать процесс восстановления настроек клавиатуры:

  1. Создайте файл xmodmap.service в каталоге /etc/systemd/system/:

    [Unit]
    Description=xmodmap bindings
    WantedBy=suspend.target hibernate.target
    
    [Service]
    Type=oneshot
    ExecStart=/bin/bash -c "sleep 5 && xmodmap ~/.Xmodmap"
  2. Включите сервис:

    sudo systemctl enable xmodmap
  3. Перезагрузите систему и протестируйте его работу.

3. Скрипт для обработки спящего режима

Скрипт, который будет срабатывать при пробуждении, также может эффективно восстанавливать настройки клавиатуры:

  1. Создайте скрипт в каталоге /usr/lib/systemd/system-sleep/, например xkeyboard.sh, с содержимым:

    #!/bin/bash
    
    case $1 in
       post)
           export DISPLAY=:0
           export XAUTHORITY=/run/user/$(id -u)/gdm/Xauthority
           sleep 5
           xmodmap ~/.Xmodmap
           ;;
    esac
  2. Сделайте скрипт исполняемым:

    sudo chmod +x /usr/lib/systemd/system-sleep/xkeyboard.sh

Этот скрипт обеспечит выполнение команды xmodmap при выходе из режима сна. Убедитесь, что вы используете правильный DISPLAY и XAUTHORITY.

4. Использование udev для автоматического восстановления привязок клавиатуры

Вы можете настроить udev для запуска xmodmap, когда обнаруживается клавиатура:

  1. Создайте правило 80-keyboard.rules в директории /etc/udev/rules.d/:

    SUBSYSTEM=="input", ACTION=="add", RUN+="/bin/bash -c 'sleep 5 && xmodmap ~/.Xmodmap'"
  2. Перезагрузите udev:

    sudo udevadm control --reload-rules

Этот подход будет восстанавливать привязки при каждом подключении клавиатуры.

Заключение

Каждый из предложенных методов может быть использован в зависимости от ваших предпочтений и требований. Наиболее простой и эффективный способ — это использовать системный юнит для автоматического вызова xmodmap после пробуждения системы. При этом важно корректно настроить переменные окружения DISPLAY и XAUTHORITY, чтобы обеспечить стабильную работу скрипта.

Не забывайте тестировать каждое решение, чтобы убедиться в его работоспособности. Надеюсь, эти рекомендации помогут вам решить проблему с потерей настроек клавиатуры в Ubuntu 18.04 после выхода из режима сна.

Оцените материал
Добавить комментарий

Капча загружается...