หมายเหตุ: สิ่งนี้ได้รับการทดสอบบนแล็ปท็อปที่มีการ์ดกราฟิกขับเคลื่อน i915
พื้นหลัง
หมายเหตุ:เมื่อเสียบปลั๊กหน้าจอใหม่ไม่มีเหตุการณ์ใดถูกส่งไปยังโฮสต์สิ่งนี้ยังคงเป็นจริงแม้หลังจากการแก้ไขครั้งล่าสุดของฉัน ดังนั้นวิธีเดียวคือใช้หน่วยเลือกตั้ง พยายามทำให้มีประสิทธิภาพเท่าที่จะเป็นไปได้ ...
แก้ไข # 3
ในที่สุดก็มีทางออกที่ดีกว่า (ผ่าน ACPI):
ยังไม่มีเหตุการณ์ใด ๆ แต่ดูเหมือนว่า ACPI จะมีประสิทธิภาพมากกว่าxrandr
การสอบถาม (หมายเหตุ: ต้องมีโมดูลเคอร์เนล ACPI ที่โหลด แต่ไม่ต้องการสิทธิ์พิเศษ)
ทางออกสุดท้ายของฉัน (ใช้ทุบตี):
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}
อนุญาตให้บูลอาร์กิวเมนต์: ถ้าสิ่งที่เป็นปัจจุบัน( 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
จะให้ข้อมูลกับคุณ แต่คุณต้องสำรวจสถานะ
ฉันได้สแกนบันทึกทั้งหมด (เคอร์เนล, daemon, X และอื่น ๆ ) ค้นหาผ่าน/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
ใช้เวลาประมาณ0.140 วินาทีถึง 0.200 วินาทีในขณะที่ไม่มีการเปลี่ยนแปลงเกิดขึ้นกับปลั๊กและสูงสุด0.700 วินาทีเมื่อใดก็ตามที่มีการเสียบปลั๊กหรือถอดปลั๊กก่อนหน้านี้ ( หมายเหตุ:ดูเหมือนว่าจะไม่กินทรัพยากร)
แก้ไข # 1
เพื่อให้แน่ใจว่าฉันไม่ได้สอนอะไรบางอย่างที่ไม่ถูกต้องฉันได้ค้นหาทั่วเว็บและเอกสาร แต่ไม่พบอะไรเกี่ยวกับDBus และหน้าจอ
ในที่สุดฉันก็ทำงานในสองหน้าต่างที่แตกต่างกันdbus-monitor --system
(ฉันได้เล่นกับตัวเลือกด้วย) และสคริปต์เล็กน้อยที่ฉันเขียน:
$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done
... และเสียบอีกครั้งแทนที่จะถอดปลั๊กจอภาพหลายครั้ง ดังนั้นตอนนี้ฉันสามารถพูดได้:
- ในการกำหนดค่านี้โดยใช้ไดรเวอร์ i915ไม่มีวิธีอื่นนอกเหนือจากการทำงาน
xrandr -q
เพื่อให้ทราบว่าเสียบจอภาพหรือไม่
แต่ใช้ความระมัดระวังเพราะดูเหมือนจะไม่มีวิธีอื่น ยกตัวอย่างเช่นxrandr
ดูเหมือนว่าจะแบ่งปันข้อมูลนี้เพื่อให้สก์ท็อป GNOME ของฉันจะเปลี่ยนไปxinerama
โดยอัตโนมัติ ... เมื่อฉันวิ่งxrandr
เอกสารบางอย่าง