お持ちですか?どの外部モニタをノートブックのDisplayPortに接続または切断すると、イベントが発生しますか? ACPIDとUDEVはまったく反応しません。
私はIntelチップに内蔵グラフィックを使用しています。ここ同様の議論が長年行われてきた。
ポーリングを使用したくありませんが、モニターが接続されているかどうかに応じてディスプレイ設定を自動的に設定するには、いくつかの構成が必要です。
答え1
メモ: これは、i915ドライバグラフィックカードを搭載したノートブックでテストされました。
背景
メモ:新しい画面が挿入されると、最後の編集後もイベントはホストに送信されません。したがって、唯一の方法はポーリングを使用することです。できるだけ効率的に作ろうとしています。
編集#3
最後に、ACPIによるより良いソリューションがあります。
まだイベントはありませんが、ACPIはxrandr
クエリよりも効率的です。 (注:これ必要ACPIカーネルモジュールがロードされますが、root権限は必要ありません。
私の最終的な解決策(bashを使用):
isVgaConnected() {
local crtState
read -a < /proc/acpi/video/VID/CRT0/state crtState
test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}
今テストしてみてください。
$ if isVgaConnected; then echo yes; else echo no; fi
yes
接続されているので、プラグを抜きます。
$ if isVgaConnected; then echo yes; else echo no; fi
no
メモ: ${1:+*-1+1}
1つを許可ブール値買収:もし何かが存在する、答えは逆転されます: ( crtState >> 4 ) * -1 + 1
。
最終スクリプト:
#!/bin/bash
export crtProcEntry=/proc/acpi/video/VID/CRT0/state
isVgaConnected() {
local crtState
read -a < $crtProcEntry crtState
test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}
delay=.1
unset switch
isVgaConnected || switch=not
while :;do
while isVgaConnected $switch;do
sleep $delay
done
if [ "$switch" ];then
unset switch
echo VGA IS connected
# doing something while VGA is connected
else
switch=not
echo VGA is NOT connected.
# doing something else, maybe.
fi
done
警告する: 軽くてxrandr
も重要ではない次より短い遅延時間0.02数秒後、Bashスクリプトはリソース消費者プロセス(top
)の一番上に移動します!
このプロセスは約0.001秒かかります。
$ time read -a </proc/stat crtStat
これには〜0.030秒かかります。
$ read -a < /proc/acpi/video/VID/CRT0/state crtState
これはすごいです!したがって、必要に応じて〜の間で合理的に設定しdelay
てください。0.5
2
編集#2
ついにこれを使って何かを見つけました。
重要な免責事項:ジャグリング/proc
や/sys
アイテムがシステムを損傷する可能性があります!したがって、本番システムでは次のことを試みないでください。
mapfile watchFileList < <(
find /sys /proc -type f 2>/dev/null |
grep -i acpi\\\|i91
)
prompt=("/" "|" '\' '-');
l=0
while :; do
mapfile watchStat < <(
grep -H . ${watchFileList[@]} 2>/dev/null
)
for ((i=0;i<=${#watchStat[@]};i++)); do
[ "${watchStat[i]}" == "${oldStat[i]}" ] || echo ${watchStat[i]}
done
oldStat=("${watchStat[@]}")
sleep .5
printf "\r%s\r" ${prompt[l++]}
[ $l -eq 4 ]&&l=0
done
...不要なアイテムを整理した後:
for ((i=0;i<=${#watchFileList[@]};i++)); do
[[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
unset watchFileList[$i] && echo $i
done
私はこれを読むことができました:
/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d
接続するときは、モニターケーブルを抜いて再接続してください。
元の答え設定を照会すると(system/preferences/monitor
または実行xrandr
)、グラフィックカードは次のことを行います。スキャン、実行するとxrandr -q
情報が提供されますが、状態をポーリングする必要があります。
すべての/proc
ログ(カーネル、デーモン、/sys
私もこれを試しました:
export spc50="$(printf "%50s" "")"
watch -n1 '
find /proc/acpi/video -type f |
xargs grep -H . |
sed "s/^\([^:]*):/\1'$spc50'}:/;
s/^\(.\{50\}\) *:/\1 /"'
結局のところ、System/Preferences/Monitor
接続したり切り離したりせずに新しい画面を実行すると、(通常)ツールが単に表示されます。ただし、以前に画面を接続または切断したことがある場合は、このツールを実行すると、次のメッセージが表示されます。初期化または更新する(実行する場合も同様ですxrandr
)。
これは、実行時に状態を定期的にポーリングして、ツールに必要なxrandr
(または同じように動作する)ことを確認するようです。
自分で試してみてください。
$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1
10秒間接続された画面(モニター)の数を表示します。
実行中に画面/モニターを接続または切断し、何が起こるかを確認してください。したがって、小さなBashテスト機能を作成できます。
isVgaConnected() {
local xRandr=$(xrandr -q)
[ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
return 1
}
その用途は次のとおりです。
$ if isVgaConnected; then echo yes; fi
しかし注意してくださいxrandr
。約1時間かかります。0.140秒~0.200秒プラグには何も変更されていませんが、ほとんど0.700秒以前に何かが接続または切断されたときはいつでも(メモ:資源をつかむ人ではないようです。)
編集#1
私が何か間違ったことを教えていないことを確認するためにウェブと文書を検索しましたが、関連するものが見つかりませんでした。DBusと画面。
dbus-monitor --system
最後に、私が書いたこの小さなスクリプトを使って2つの異なるウィンドウ(オプションも使用しています)で実行しています。
$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done
...モニタープラグを抜かずに何度も再接続しました。今私はこう言うことができます:
- この構成ではi915ドライバの使用
xrandr -q
、モニターが実行される以外に接続されているかどうかを知る方法はありません。
しかし、他の方法はないようですので注意してください。たとえば、xrandr
この情報は共有され、自分のGNOMEデスクトップがxinerama
自動的に切り替わります。私が走るときxrandr
。
一部の文書
答え2
次の行が表示されます。udevadm monitor
KERNEL[46578.184280] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV [46578.195887] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
モニターをVGAコネクタに接続する場合。したがって、この問題を解決する方法があるかもしれません。
答え3
何らかの理由でホットプラグパスを使用したくない人のために、ポーリングなしでスクリプトでinotifywaitを引き続き使用できます。
#!/bin/bash SCREEN_LEFT=DP2 SCREEN_RIGHT=eDP1 START_DELAY = 5 Rennis+19 $$ >/dev/null 睡眠$START_DELAY OLD_DUAL="仮想" そして[1]; DUAL=$(cat /sys/class/drm/card0-DP-2/状態) if [ "$OLD_DUAL" != "$DUAL" ]; if ["$ DUAL" == "接続済み"]; echo 'デュアルモニター設定' xrandr --output $SCREEN_LEFT --auto --rotation Normal --pos 0x0 --output $SCREEN_RIGHT --auto --rotation Normal --below $SCREEN_LEFT その他 echo 'シングルモニター設定' xrandr--自動 フィリピン諸島 OLD_DUAL=“$DUAL” フィリピン諸島 inotifywait -q -e 閉じる /sys/class/drm/card0-DP-2/status >/dev/null 完璧
.xsessionrcから呼び出す方が良いでしょう。末尾&を忘れないでください。 xrandrを使用したポーリングには、私の新しいラップトップで深刻なユーザビリティの問題があります(マウスが定期的に停止しています)。
答え4
私はbash、gawk、xrandr、およびxevを使用してこの非常にクールなスクリプトを作成しました。システムデバイスに触れることなく、そのようなデバイスに関する広範な知識を必要とせず、接続されたモニタの使用と検出にのみxev
依存するという点で非常にきれいです。randr
awkスクリプトは、正しいイベントを解析して選択するために使用されます。
ノート:xev v1.2.4以降が必要です。
常に他の外部モニターを接続しているノートブックユーザーにお勧めします。
#!/bin/bash
function monitor_xevents {
local connected_monitors=()
local monitor
for monitor in $(xrandr --listactivemonitors | awk '/^\s+[0-9]+:/ {print $4}'); do
connected_monitors+=("$monitor")
done
xev -root -event randr -1 | stdbuf --output=L gawk --sandbox \
--source "BEGIN{$(printf -- 'monitors["%s"]=1\n' ${connected_monitors[@]})}" \
--source 'BEGIN {
pat=@/output (.[^,]*),.*connection RR_(\w+),/
for (monitor in monitors)
print monitor, "connected"
}
!/crtc None/ && match ($0, pat, s) {
# Newly discovered monitor at runtime
if (!(s[1] in monitors)) {
monitors[s[1]] = 1
print s[1], "connected"
next
}
switch (s[2]) {
case "Connected":
if (!monitors[s[1]])
monitors[s[1]] = 1
else next
break
case "Disconnected":
if (monitors[s[1]])
monitors[s[1]] = 0
else next
break
}
print s[1], tolower(s[2])
}'
}
while read output status; do
printf "$output was $status\n"
done < <(monitor_xevents)
systemdで実行できますユーザー提供する:
[Unit]
Description="Monitor hotplug notifier"
[Service]
ExecStart='/home/chigozirim/Dev/mon.sh'
Restart=on-failure
RestartSec=5s
RemainAfterExit=yes
[Install]
WantedBy=default.target
起動すると、最初に接続されているすべてのモニターを知らせ、次に使用し続けながらモニターが接続されたとき、または接続が切断されたときを通知します。
出力例:
Jan 06 01:48:18 ArcoB mon.sh[495478]: eDP-1 was connected
Jan 06 01:48:18 ArcoB mon.sh[495478]: HDMI-1-0 was connected
Jan 06 18:51:13 ArcoB mon.sh[495478]: HDMI-1-0 was disconnected
Jan 06 20:29:19 ArcoB mon.sh[495478]: HDMI-1-0 was connected
Jan 07 12:47:23 ArcoB mon.sh[495478]: HDMI-1-0 was disconnected
...
私はラップトップを使用しているのでeDP-1
(内蔵ディスプレイポート1)は基本的に私のラップトップなので、絶対に切断されません。
これを拡張して他のスクリプトなどを呼び出すことができます。これは上記と同等のC/C++の作成を始めたくない人のためのPOCだけです。