Làm cách nào để phát hiện khi màn hình được cắm hoặc rút phích cắm?


53

bất kỳ sự kiện được kích hoạt khi tôi cắm vào hoặc ra màn hình ngoài vào DisplayPort của máy tính xách tay của tôi? ACPID và UDEV hoàn toàn không phản ứng.

Tôi đang sử dụng đồ họa trên bo mạch trên chip intel. Đây là một cuộc thảo luận tương tự đã được vài năm tuổi.

Tôi không muốn sử dụng bỏ phiếu nhưng tôi cần có một số cấu hình tự động đặt cài đặt hiển thị tùy thuộc vào việc màn hình có được kết nối hay không.


4
Nó có thể được thực hiện với udev. Phiên bản kernel của bạn là gì? Bạn đang sử dụng KMS (cài đặt chế độ kernel)?
Andy

Cảm ơn câu trả lời. Tôi không chắc chắn về KMS, nhưng như tôi đã nói trong câu hỏi, udev không gửi bất kỳ sự kiện nào. ( màn hình udevadm - không có phản ứng gì cả)
janoliver

@Andy: lần cuối cùng xuất hiện , có vẻ như hầu hết các hệ thống đều yêu cầu bỏ phiếu. Nếu bạn đã tìm được cách kích hoạt sự kiện udev, bạn có thể trả lời câu hỏi đó không?
Gilles 'SO- ngừng trở nên xấu xa'

1
Cuối cùng tôi đã có nó chạy tải i915 như mô-đun hạt nhân.
janoliver

3
Bạn có thể sử dụng xrandr hoặc disper để phát hiện nếu màn hình ngoài đã được cắm. Github.com/wertarbyte/autorandr có thể chỉ cho bạn cách sử dụng chúng. Nhưng xrandr / disper có thể không hỗ trợ thẻ video của bạn.
số

Câu trả lời:


13

LƯU Ý: Điều này đã được thử nghiệm trên máy tính xách tay với card đồ họa điều khiển i915.


Lý lịch

LƯU Ý: Khi một màn hình mới được cắm, không có sự kiện nào được gửi đến máy chủ, điều này vẫn đúng ngay cả sau lần chỉnh sửa cuối cùng của tôi. Vì vậy, cách duy nhất là sử dụng bỏ phiếu. Cố gắng làm cho chúng hiệu quả nhất có thể ...

EDIT # 3

Cuối cùng, có một giải pháp tốt hơn (thông qua ACPI):

Vẫn không có sự kiện, nhưng ACPI có vẻ hiệu quả hơn là xrandrtìm hiểu. (Nota: Điều này yêu cầu các mô-đun hạt nhân ACPI được tải, nhưng không yêu cầu quyền root).

Giải pháp cuối cùng của tôi (sử dụng bash):

isVgaConnected() {
    local crtState
    read -a < /proc/acpi/video/VID/CRT0/state crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

Bây giờ là một bài kiểm tra:

$ if isVgaConnected; then echo yes; else echo no; fi 
yes

Nó đã được cắm, vì vậy bây giờ tôi rút phích cắm:

$ if isVgaConnected; then echo yes; else echo no; fi 
no

LƯU Ý: cho ${1:+*-1+1} phép một đối số boolean : Nếu có gì đó , câu trả lời sẽ được đảo ngược : ( crtState >> 4 ) * -1 + 1.

và kịch bản cuối cùng:

#!/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

CẢNH BÁO: nhẹ hơn xrandr, nhưng không quan trọng với độ trễ nhỏ hơn 0,02 giây, tập lệnh Bash sẽ đi đầu trong quá trình ăn tài nguyên ( top)!

Trong khi chi phí này ~ 0,001 giây:

$ time read -a </proc/stat crtStat

Điều này cần ~ 0,030 giây:

$ read -a < /proc/acpi/video/VID/CRT0/state crtState

Thứ này lớn! Vì vậy, tùy thuộc vào những gì bạn cần, delaycó thể được đặt hợp lý giữa 0.52.

EDIT # 2

Cuối cùng tôi đã tìm thấy một cái gì đó, bằng cách sử dụng này:

Từ chối trách nhiệm quan trọng: Chơi với /proc/syscác mục có thể phá vỡ hệ thống của bạn !!! Vì vậy, đừng thử những điều sau đây trên các hệ thống sản xuất.

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

... Sau khi dọn dẹp các mục không mong muốn:

for ((i=0;i<=${#watchFileList[@]};i++)); do
  [[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
      unset watchFileList[$i] && echo $i
done

Tôi đã có thể đọc điều này:

/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d

Khi tôi cắm, rút ​​phích cắm và cắm lại vào cáp màn hình.

Câu trả lời gốc

Khi cấu hình được hỏi (đang chạy system/preferences/monitorhoặc xrandr), các card đồ họa thực hiện một kiểu quét , do đó, việc chạy xrandr -qsẽ cung cấp cho bạn thông tin, nhưng bạn phải thăm dò trạng thái.

Tôi đã quét tất cả các bản ghi, (kernel, daemon, X, v.v.) tìm kiếm thông qua /proc& /sys, và rõ ràng dường như không có gì tồn tại thỏa mãn yêu cầu của bạn.

Tôi cũng đã thử điều này:

export spc50="$(printf "%50s" "")"
watch -n1  '
    find /proc/acpi/video -type f |
        xargs grep -H . |
        sed "s/^\([^:]*):/\1'$spc50'}:/;
             s/^\(.\{50\}\) *:/\1 /"'

Sau tất cả, nếu bạn chạy System/Preferences/Monitortrong khi không có màn hình mới vừa được cắm, cũng không được rút ra, công cụ sẽ xuất hiện đơn giản (bình thường). Nhưng nếu bạn đã cắm hoặc rút màn hình trước đó, đôi khi bạn sẽ chạy công cụ này và bạn sẽ thấy máy tính để bàn của mình thực hiện kiểu đặt lại hoặc làm mới (giống như khi bạn chạy xrandr).

Điều này dường như xác nhận rằng công cụ này yêu cầu xrandr(hoặc hoạt động theo cách tương tự) bằng cách bỏ phiếu theo trạng thái định kỳ, bắt đầu từ thời điểm nó chạy.

Bạn có thể tự thử:

$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1

Điều này sẽ hiển thị số lượng màn hình (màn hình) được kết nối, trong 10 giây.

Trong khi điều này chạy, cắm và / hoặc rút phích cắm màn hình / màn hình của bạn và xem điều gì sẽ xảy ra. Vì vậy, bạn có thể tạo một hàm kiểm tra Bash nhỏ:

isVgaConnected() {
    local xRandr=$(xrandr -q)
    [ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
    return 1
}

có thể sử dụng như trong:

$ if isVgaConnected; then echo yes; fi

Nhưng hãy cẩn thận, xrandrmất khoảng 0.140 giây đến 0.200 giây trong khi không có thay đổi nào xảy ra đối với phích cắm và tối đa 0,700 giây mỗi khi có thứ gì đó được cắm hoặc rút phích cắm ngay trước đó ( LƯU Ý: Có vẻ như không phải là người ăn tài nguyên).

EDIT # 1

Để đảm bảo tôi không dạy điều gì đó không chính xác, tôi đã tìm kiếm trên Web và các tài liệu, nhưng không tìm thấy gì về DBus và Screens .

Cuối cùng, tôi đã chạy trong hai cửa sổ khác nhau dbus-monitor --system(tôi cũng đã chơi với các tùy chọn) và kịch bản nhỏ tôi đã viết:

$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done

... và một lần nữa cắm, hơn là rút phích cắm màn hình, nhiều lần. Vì vậy, bây giờ tôi có thể nói:

  • Trong cấu hình này, sử dụng trình điều khiển i915 , không có cách nào khác ngoài chạy xrandr -qđể biết màn hình có được cắm hay không.

Nhưng hãy cẩn thận, vì dường như không có cách nào khác. Chẳng hạn, xrandrdường như chia sẻ thông tin này, vì vậy máy tính để bàn Gnome của tôi sẽ xineramatự động chuyển sang ... khi tôi chạyxrandr .

Một số tài liệu


4

Các dòng sau xuất hiện trong 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)

khi gắn màn hình vào Đầu nối VGA. Vì vậy, có thể có một cách để tìm ra điều này.


Với nVidia 9800 GT và trình điều khiển độc quyền, màn hình udevadm không hiển thị gì khi tôi kết nối màn hình HDMI. Bạn đang sử dụng phần cứng / trình điều khiển nào?
frankster

Đáng tiếc, điều đó không làm việc đáng tin cậy đối với tôi. Đôi khi tôi nhận được các thông báo sự kiện này khi tôi cắm vào màn hình của mình và đôi khi không.
Tobias

3

Đối với những người, vì bất kỳ lý do gì, không muốn đi theo con đường cắm nóng, vẫn có thể không bỏ phiếu trong một tập lệnh bằng cách sử dụng inotifywait:

#! / bin / bash

SCREEN_LEFT = DP2
SCREEN_RIGHT = eDP1
START_DELAY = 5

gia hạn +19 $$> / dev / null

ngủ $ START_DELAY

OLD_DUAL = "giả"

trong khi [1]; làm
    DUAL = $ (cat / sys / class / drm / card0-DP-2 / status)

    if ["$ OLD_DUAL"! = "$ DUAL"]; sau đó
        if ["$ DUAL" == "đã kết nối"]; sau đó
            echo 'Thiết lập màn hình kép'
            xrandr --output $ SCREEN_LEFT --auto --rotate bình thường --pose 0x0 --output $ SCREEN_RIGHT --auto --rotate bình thường - tin $ SCREEN_LEFT
        khác
            echo 'Thiết lập màn hình đơn'
            xrandr --auto
        fi

        OLD_DUAL = "$ DUAL"
    fi

    inotifywait -q -e close / sys / class / drm / card0-DP-2 / status> / dev / null
làm xong

Nó được gọi tốt nhất từ ​​.xsessionrc của bạn, không quên kết thúc &. Thăm dò ý kiến ​​với xrandr đã đưa ra các vấn đề về khả năng sử dụng nghiêm trọng trên máy tính xách tay hoàn toàn mới của tôi (chuột sẽ bị đình trệ định kỳ).


Tôi sẽ không có thể nghĩ rằng bạn có thể sử dụng inotify trên /procvà chỉ cần làm inotifywait -q -e close /sys/class/drm/card0-DP-2/status thực sự đã không dừng lại khi ngắt kết nối DP-2 trên hệ thống của tôi
nhed

3

Tôi bị mắc kẹt để sử dụng srandrd . Nó theo dõi các sự kiện X và kích hoạt tập lệnh của bạn khi màn hình được kết nối hoặc ngắt kết nối.


0

Rõ ràng là nên có một cái gì đó! Hệ thống tập tin :) / sys cho không gian người dùng biết phần cứng nào có sẵn, vì vậy các công cụ không gian người dùng (như udev hoặc mdev) có thể tự động điền vào thư mục "/ dev" với các nút thiết bị đại diện cho phần cứng hiện có. Linux cung cấp hai giao diện hotplug: / sbin / hotplug và netlink.

Có một bản demo C nhỏ trong tệp sau. http://www.kernel.org/doc/pending/hotplug.txt


0

Hầu hết các phần mềm hệ thống / ứng dụng trên Linux ngày nay đã sử dụng một số kỹ thuật ipc để giao tiếp với nhau. D-Bus hiện được sử dụng chủ yếu với các ứng dụng Gnome và có thể giúp ích.

Tạp chí Linux:

D-BUS có thể tạo điều kiện gửi các sự kiện hoặc tín hiệu thông qua hệ thống, cho phép các thành phần khác nhau trong hệ thống giao tiếp và cuối cùng để tích hợp tốt hơn. Ví dụ: thiết bị Bluetooth có thể gửi tín hiệu cuộc gọi đến mà trình phát nhạc của bạn có thể chặn, tắt âm lượng cho đến khi cuộc gọi kết thúc.

wiki:

D-Bus cung cấp cả trình nền hệ thống (cho các sự kiện như "thiết bị phần cứng mới được thêm vào" hoặc "hàng đợi máy in đã thay đổi") và trình nền phiên cho mỗi người dùng đăng nhập (cho nhu cầu giao tiếp giữa các quy trình chung giữa các ứng dụng người dùng)

Thậm chí còn có một thư viện Python cho việc này và gần đây, ubfox đã sử dụng khả năng này có tên là " zeitgeist ".


-6

Về mặt đồ họa bạn có thể thấy nếu màn hình được nhận dạng Monitor, tôi biết rằng bạn có thể tìm thấy điều này trên Ubuntu, Fedora và những người khác ở vị trí này (hoặc tương tự).

Hệ thống / Tùy chọn / Màn hình

Và bạn có thể bật / tắt bất kỳ màn hình nào bạn muốn hoặc sử dụng cả hai cùng lúc với hình ảnh trùng lặp trong cả hai màn hình hoặc màn hình độc lập


2
Anh ấy đã yêu cầu một sự kiện được kích hoạt khi màn hình được cắm / rút phích cắm
Michael Mrozek

Bạn đã nhìn vào đây? stackoverflow.com/questions/5469828/ từ
Satish
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.