xmodmap 睡眠后丢失

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' &
    # without su, without sleep, without fork (&): doesn't work either
else
    (sleep 5; /usr/bin/xmodmap /home/norake/.Xmodmap) &
fi

sleep 30也不行。当然,手动运行脚本是有效的。

答案1

当您拔下并重新插入键盘时,您修改的设置也会“丢失”,这就是这里发生的情况:挂起会生成热插拔事件,因为键盘在进入挂起时被禁用并在退出时重新启用。

从 X 服务器的角度来看,从挂起返回后连接的键盘是一个新键盘,因此它是用标准绑定启动的,就像第二个键盘一样。

这是 USB 键盘驱动程序的一个已知缺点,并且很难在内核中修复(因为 USB 在恢复时会重新枚举,因此我们需要一种方法来保持设备的身份,即使它被分配了一个新号码),并且很难在 X 服务器中修复(因为它需要保留设备的历史记录)。

您能做的最好的事情可能是运行该命令作为会话启动的一部分和键盘热插拔处理的一部分,但我在这里想不出一个完全干净的解决方案。

答案2

这是我针对此问题的特殊情况的低技术黑客解决方案:

我的键盘有一个打印键,菜单键应该在该位置,因此我的 xmodmap 只重新映射该键。

我为要运行的 Print 键设置了一个键绑定(在我的例子中是在 gnome shell 中)

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

因此,在挂起后,第一次按 Print 键时,它将触发 xmodmap,从那时起它就充当菜单键。

(之后我的键盘就不再有打印键了。)

这种方法应该在以下情况下有效:

  1. 您不介意最初的“盲目”按键。
  2. 您至少有一个按钮,您知道在重新映射变得相关之前或一旦重新映射变得相关,您将按下该按钮。
  3. 该按钮的初始按键符号不再出现在新映射上。

更新:此后我使用 xdotool 改进了我的解决方案,以便在初始重新绑定步骤中触发上下文菜单本身:

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

答案3

请记住替换$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
        # Nothing to do for pre-sleep
    elif [ "${1}" == "post" ]; then
        echo "post" >> /tmp/xkeyboard.log
        export DISPLAY=:0  # Set the DISPLAY variable
        export XAUTHORITY=$XAUTH
        /bin/bash -c "sleep 7 && xmodmap home/$USER/.Xmodmap" >> /tmp/xkeyboard.log 2>&1
    fi
    

    在此代码中,我已将日志记录添加到/tmp/xkeyboard.log文件中,因此如果键盘映射不起作用,您可以去那里检查发生了什么问题。

答案4

这是一个可行的解决方案,从各种来源获得了帮助,但大部分是我写的。 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 --replaceas kwin 有时会导致故障并且需要重置,但它不是守护进程,应该使用屏幕分离。仅当您使用 KDE 时才如此。如果未安装,请安装屏幕。此处导出显示是使其正常工作的关键。与您的用户一起运行也是必要的。即使您是第一个恢复的帐户,它仍然不是您的帐户。 xmodmap 不需要睡眠。但kwin在resume后几秒会被系统自动重置,但有时会失败;因此延迟是必要的。

相关内容