it-swarm.cn

插入外接显示器时自动应用RandR配置的工具

是否有一种工具可以使您:

  • 记住每个显示器当前的RandR配置(位置,方向,分辨率等),
  • 插入显示器后,是否会自动应用最后一个已知的良好配置,而无需使用applet或xrandr(1)乱搞?

这些配置必须基于每个用户,每个显示器来应用。

如果没有这种工具,我想自己动手,但据我所知,无法告诉您已插入监视器。我是否必须使用xrandr -q进行轮询偶尔找出输出连接或断开,或者有更有效的方法吗?可以将udev调整为做到这一点吗?

58
Yaroslav Fedevych

我正在使用这个简单的(自制)脚本,该脚本不断轮询RandR,并在VGA连接/断开时在LVDS1和VGA1之间切换。 (对于[〜#〜] hdmi [〜#〜]输出,在以下脚本文件中,更改所有VGA1HDMI1

这是一个肮脏的解决方案,但效果很好。

它是针对我的设置进行定制的:您很可能需要更改RandR输出名称(LVDS1VGA1)和 与我不同 使用VGA的RandR默认模式可能会很好。

#!/bin/bash

# setting up new mode for my VGA
xrandr --newmode "1920x1080" 148.5 1920 2008 2052 2200 1080 1089 1095 1125 +hsync +vsync
xrandr --addmode VGA1 1920x1080

# default monitor is LVDS1
MONITOR=LVDS1

# functions to switch from LVDS1 to VGA and vice versa
function ActivateVGA {
    echo "Switching to VGA1"
    xrandr --output VGA1 --mode 1920x1080 --dpi 160 --output LVDS1 --off
    MONITOR=VGA1
}
function DeactivateVGA {
    echo "Switching to LVDS1"
    xrandr --output VGA1 --off --output LVDS1 --auto
    MONITOR=LVDS1
}

# functions to check if VGA is connected and in use
function VGAActive {
    [ $MONITOR = "VGA1" ]
}
function VGAConnected {
    ! xrandr | grep "^VGA1" | grep disconnected
}

# actual script
while true
do
    if ! VGAActive && VGAConnected
    then
        ActivateVGA
    fi

    if VGAActive && ! VGAConnected
    then
        DeactivateVGA
    fi

    sleep 1s
done

完整步骤:

  1. 将上方的脚本(homemadeMonitor.sh)进入您的首选目录

  2. 通过在终端中键入以下命令,使.sh文件可执行。

    chmod +x homemadeMonitor.sh

  3. 运行.sh文件

    ./homemadeMonitor.sh

20
peoro

回应问题的“ [a]告知监视器已插入”的方式:

支持仍然相差很多,但是在最近的内核中,有些支持可以在发生显示热插拔时生成udev事件。使用内核2.6.38和ATI X1400硬件,我第一次连接VGA显示器时会收到一个事件,但是在随后的显示器断开或重新连接时没有任何事件。 英特尔硬件可能会提供更好的支持。 NVIDIA专有驱动程序当前不支持KMS。我没有尝试在NVIDIA硬件上寻找热插拔事件,但是我怀疑它是否可以工作。

如果要尝试使用udev,可以尝试以下步骤:

  • 更新到最新的内核
  • 确保启用了内核模式设置(KMS)。如果启用,它应该在内核输出中报告。我的说[drm] radeon kernel modesetting enabled[drm] initializing kernel modesetting
  • udevadm monitor --property并查看(断开)连接显示器时是否报告了事件

如果在显示热插拔上收到udev事件,则可以使用udev规则触发脚本,例如:

ACTION=="change", SUBSYSTEM=="drm", HOTPLUG=="1", RUN+="/path/to/hotplug.sh"

注意:如果您将nVIDIA GPU与专有的二进制驱动程序一起使用,这将not有效,因为它不使用KMS。您将not获得任何udev事件。

21
Andy

对于可以按用户和按显示器存储监视器配置文件的工具, autorandr 可以做到这一点。

我的笔记本电脑配有NVIDIA卡,因此我使用 分散后端 代替xrandr。如果您将Autorandr称为autodisper,则将使用disper作为后端来管理您的监视器。不过,对于本文的其余部分,为了保持一致性,我将其称为autorandr

您可以使用autorandr --save profile_name保存配置文件。然后单独运行autorandr将为您提供配置文件列表,并标识检测到哪个配置文件为当前配置。

例如:

$ autorandr
laptop
syncmaster19 (detected)

您可以告诉它使用autorandr --change自动为当前配置加载适当的配置文件。该命令与udev规则配对以在热插拔时运行该命令,即可完成您所请求的操作。

作为附加的预防措施,我在该命令后附加了--default laptop,如果没有与当前配置匹配的已保存配置文件,它将默认显示在笔记本电脑的显示屏上。因此,我用来切换显示的完整命令是:

autorandr --change --default laptop

不幸的是,当我热插显示器时,我的机器没有任何udev输出。我正在使用NVIDIA专有驱动程序,所以这并不奇怪。因此,现在我将其绑定到XF68Display键(Fn-F8),几乎一样好。

19
Jack Senechal

我使用了上面建议的udev规则以及看起来像这样的Shell脚本

#!/bin/sh

dmode="$(cat /sys/class/drm/card0-VGA-1/status)"
export DISPLAY=:0
export XAUTHORITY=/home/yourusername/.Xauthority

if [ "${dmode}" = disconnected ]; then
     /usr/bin/xrandr --auto
Elif [ "${dmode}" = connected ];then
     /usr/bin/xrandr --output VGA1 --auto --right-of LVDS1
else /usr/bin/xrandr --auto
fi

Xauthority部分以及导出DISPLAY都是必不可少的,您可以使用echo $DISPLAY查看它等于哪个数字。采用 xrandr -q查看您拥有的外接显示器。最后的else声明只是为了确保您在不显示的情况下也不会卡住。

7
Cappie

一个小程序可以等待X服务器通知已更改的监视器配置,然后执行给定命令(例如,另一个答案中提到的autorandr): https:// bitbucket .org/portix/srandrd/overview

这似乎是使用udev的更干净的解决方案(在这里您不必担心找到合适的X服务器等)。

6
Joachim Breitner

如果必须让它在插入时自动检测显示,则似乎最干净的解决方案是添加UDEV规则以运行包含xrandr命令的脚本。这是一个用户解决方案的示例 (1

使用udevadm监视(输出)UDEV事件
此步骤对于每个用户而言都是最重要的。跑 udevadm monitor --environment --udev。然后连接您的HDMI电缆。

UDEV规则
根据上述命令的输出,用户在/etc/udev/rules.d/95-monitor-hotplug.rules

KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/dan/.Xauthority", RUN+="/usr/local/bin/hotplug_monitor.sh"

注意使用的环境变量,因此xrandr将在用户配置文件下运行。

x脚本hotplug_monitor.sh

您可能需要调整xrandr选项以适合您的需求。

#! /usr/bin/bash

export DISPLAY=:0
export XAUTHORITY=/home/dan/.Xauthority

function connect(){
    xrandr --output HDMI1 --right-of LVDS1 --preferred --primary --output LVDS1 --preferred 
}

function disconnect(){
      xrandr --output HDMI1 --off
}

xrandr | grep "HDMI1 connected" &> /dev/null && connect || disconnect
5
iyrin

对于出于某种原因而不想采用热插拔路由的用户,仍然可以使用inotifywait不在脚本中进行轮询:

#!/ bin/bash 
 
 SCREEN_LEFT = DP2 
 SCREEN_RIGHT = eDP1 
 START_DELAY = 5 
 
 renice +19 $$>/dev/null 
 
 sleep $ START_DELAY 
 
 OLD_DUAL =“ dummy” 
 
 1]; do 
 DUAL = $(cat /sys/class/drm/card0-DP-2/status)

如果[“ $ OLD_DUAL”!=“ $ DUAL”];然后
如果[“ $ DUAL” ==“ connected”];然后
 echo'Dual monitor setup'
 xrandr-输出$ SCREEN_LEFT-自动-正常旋转--pos 0x0-输出$ SCREEN_RIGHT-自动-正常旋转-下面$ SCREEN_LEFT 
 else 
 echo'单显示器设置'
 xrandr --auto 
 fi 
 
 OLD_DUAL =“ $ DUAL” 
 fi 
 
 inotifywait -q -e close/sys/class/drm/card0-DP-2/status>/dev/null 
完成
 

使用xrandr进行轮询在我的全新笔记本电脑上出现了严重的可用性问题(鼠标会定期停顿)。

3
Balzola

例如,为了简化Xfce,请安装“ arandr”,该发行版应在发行包中提供。使用“ arandr”配置显示,然后将其另存为“ displayLayout”。 Arandr应该为您添加“ .sh”扩展名,以便可以如上面iyrin提到的脚本“ hotplug_monitor.sh”中所写的那样直接在“ function connect()”中使用,例如:

function connect(){
 /path/to/displayLayout.sh
}

要使用断开连接机制,请在脚本顶部的“#!/ bin/bash”下方添加,如下所示:

#!/bin/bash
#
PLUGGED_EXTERNAL=`xrandr | awk /"connected [0-9]"/'{print $1}'`

xrandr将检测显示并将输出传递给awk,后者将基于正则表达式“ connected”对其进行过滤,后跟一个数字,这实际上是我们想要的。我认为没有必要在正则表达式中匹配精确的分辨率,因为主显示被报告为“已连接的主”,后跟数字即分辨率。然后awk“ print $ 1”将仅打印第一列,在这种情况下,它是外部监视器的名称,并将其存储在PLUGGED_EXTERNAL变量中。接下来,可以像这样使用脚本$ PLUGGED_EXTERNAL中的固定显示名称“ HDMI1”代替:

function disconnect(){
  xrandr --output $PLUGGED_EXTERNAL --off
}

xrandr | grep "$PLUGGED_EXTERNAL connected" &> /dev/null && connect || disconnect
1
user180381

我想看这个问题的人不是那些想使用GNOME的人,而那些使用GNOME的人不必看这个问题,而是出于完整性考虑:

GNOME内置了此功能。如果您通过gnome-control-center更改设置,则gnome-settings-daemon会记住它(在.config/monitors.xml),并在插入或拔出显示器时自动应用它。

遗憾的是,monitors.xml文件中的配置没有很好的文档说明。请参阅问题 此处 。 gnome显示工具也无法设置平移,按监视器缩放以及不进行缩小。由于许多人同时使用HiDPI笔记本电脑屏幕和常规DPI屏幕,因此这些工具不足以得到可行的解决方案。

我已经看到了 作为Wayland的路线图项目提到 ,尽管如此,当它最终出现时,我们可能会看到所提到问题的解决方案。直到在Gnome上,我在延迟手动设置xrandr之后才运行启动脚本。

1
Joachim Breitner

当使用peoro的解决方案时,我从xrandr获得了一些额外的输出,因此我在grep中使用了-c选项来计算匹配数。我将其调整为适用于HDMI,还添加了音频开关:

#!/bin/bash
# adapted from http://unix.stackexchange.com/questions/4489/

# default monitor is LVDS1
MONITOR=LVDS1

# functions to switch from LVDS1 to HDMI1
function ActivateHDMI {
    xrandr --output HDMI1 --mode 1920x1080 --dpi 160 --output LVDS1 --off
    pactl set-card-profile 0 output:hdmi-stereo-extra1
    MONITOR=HDMI1
}
function DeactivateHDMI {
    xrandr --output HDMI1 --off --output LVDS1 --auto
    pactl set-card-profile 0 output:analog-stereo
    MONITOR=LVDS1
}

# functions to check if HDMI is connected and in use
function HDMIActive {
    [ $MONITOR = "HDMI1" ]
}
function HDMIConnected {
    [[ `xrandr | grep "^HDMI1" | grep -c disconnected` -eq 0 ]]
}

# actual script
while true
do
    if ! HDMIActive && HDMIConnected
    then
        ActivateHDMI
    fi

    if HDMIActive && ! HDMIConnected
    then
        DeactivateHDMI
    fi

    sleep 1s
done
1
Aaros

编辑我的答案以使其设置更简单。

安装autorandr以自动在xrandr中进行屏幕布局,从 https://github.com/nalipaz/autorandr/releases 获取最新的.deb并运行:

dpkg -i [file]

使用存储的屏幕布局设置自动运行

autorandr --save [docked|mobile|home|etc]

举例来说,在没有插入任何显示器的笔记本电脑上,我按照自己的方式进行了设置,然后运行:

autorandr --save mobile

然后插入我的hdmi并重新配置arandr,然后运行:

autorandr --save docked

设置完每个布局后,您可以运行(用以前喜欢的名称替换“移动设备”,我使用移动设备):

autorandr --default mobile

现在已经完成了autorandr的设置,您可以通过安装一个软件包来自动化该过程,该软件包将轮询连接的显示器并在检测到时运行autorandr --change。是的,我了解udev,可以设置它是否适合您,但在我的测试中,udev不适用于我的hdmi。每20个插拔一次,它只能工作1个,有时甚至完全停止。

从此处下载最新的.deb: https://github.com/nalipaz/poll-xrandr/releases/ ,然后使用

dpkg -i [file]

autorandr --change完成后,很有可能需要运行更多任务,autorandr允许将这些命令插入一个名为〜/ .autorandr/postswitch的文件中。进行如下操作:

cd ~/.autorandr/ && touch postswitch && chmod +x postswitch

现在,编辑后切换文件,使其具有类似于以下内容的内容:

#!/bin/bash
if pidof conky > /dev/null 2>&1; then
  killall conky
fi
(sleep 2s && xrandr-adjust-brightness restore -q) &
(sleep 2s && nitrogen --restore) &
(sleep 3s && conky -q) &

另外,您可能希望将autorandr和poll-xrandr添加到您的初创公司,类似于以下两个命令:

autorandr --change &
poll-xrandr &

拔下电源插头或插入监视器,然后观看魔术!

0
nicholas.alipaz