31710
Linuxデスクトップ環境を使用しています。しばらくキーボードやマウスを操作しないでいると、画面が真っ黒になり、キーボードやマウスを操作すると復帰します。このタイミングをトリガにして、自分の用意したスクリプトを走らせることは可能でしょうか？

具体的にやりたいことは、Raspberry
Piに接続された専用液晶モニタで、消灯時にはバックライトをオフにし、点灯時にはバックライトを元に戻したいのです。専用液晶モニタなので、HDMI等の汎用ディスプレイポートを使用しておらず、バックライトを制御するには、そのためのコマンドを実行する必要があります。

省電力イベントが発生したときに、バックライトの制御を行いたいと思っています。バックライトのオンオフを制御するコマンドはありますが、イベントでスクリプトを実行させる方法が分かりません。

環境は、Raspbery Pi, 2015-11-21-raspbian-jessie, Xfce4 です。
CC BY-SA 3.0
2016-02-26T23:58:49.437
22581
2017-01-08T13:04:16.013
2017-01-08T13:04:16.013
3337
3337
question
linux c raspberry-pi x11
Linuxデスクトップ環境で、しばらく操作しないと画面が真っ黒になるが、このタイミングで任意のスクリプトを実行したい
raspbianは分かりませんが、大抵のXのデスクトップ環境ではD-Busでコントロール出来ます。  
`xdg-screensaver`コマンドの内部でも`dbus-send`コマンドを使っていますし、それが標準に則った方法なのだと思います。  
D-Busはよく分かっていませんが以下の様な感じでよさそうです。

```

    # 状態の確認
    dbus-send --session --dest=org.freedesktop.ScreenSaver --type=method_call --print-reply /ScreenSaver org.freedesktop.ScreenSaver.GetActive
    
    # シグナルのモニタ
    dbus-monitor --session "type='signal',path=/ScreenSaver,member=ActiveChanged"
    
```

シグナルのモニタ、Python板

```

    #!/usr/bin/python3
    import dbus
    from dbus.mainloop.glib import DBusGMainLoop
    from gi.repository import GLib
    
    def changed_hdl(arg):
        print(arg)
    
    
    DBusGMainLoop(set_as_default=True)
    loop = GLib.MainLoop()
    session = dbus.SessionBus()
    saver = session.get_object('org.freedesktop.ScreenSaver', '/ScreenSaver')
    saver.connect_to_signal('ActiveChanged', changed_hdl)
    loop.run()
    
```
CC BY-SA 3.0
2016-03-01T06:22:59.003
22686
2016-03-01T06:22:59.003
3054
22581
answer
自分で調査した結果を報告します。

まず、スクリーンセーバーを無効にします。

```

    $ xset s off
    
```

DPMS (Display Power Management Signaling) の設定を行い、消灯までの時間を設定します。

```

    $ xset dpms 60 60 60
    
```

ディスプレイの状態を取得します。

```

    $ xset q|grep Monitor
      Monitor is On
    
```

この表示結果をポーリングすれば、ディスプレイがオフになったことを知ることができます。

ただし、`xset q`コマンドは、多くの情報を取得するため、無駄が多いので、知りたい情報に限定して取得するプログラムをCで書きます。

```

    #include <X11/Xlib.h>
    #include <X11/extensions/dpms.h>
    
    int main()
    {
        Display *d = XOpenDisplay(0);
        if (d) {
            int dummy;
            if (DPMSQueryExtension(d, &dummy, &dummy)) {
                if (DPMSCapable(d)) {
                    CARD16 state;
                    BOOL onoff;
                    DPMSInfo(d, &state, &onoff);
                    if (onoff) {
                        switch (state) {
                        case DPMSModeOn:      puts("on");      break;
                        case DPMSModeStandby: puts("standby"); break;
                        case DPMSModeSuspend: puts("suspend"); break;
                        case DPMSModeOff:     puts("off");     break;
                        }
                    }
                }
            }
        }
        return 0;
    }
    
```

コンパイルする際は、`X11`と`Xext`をリンクします。

```

    $ cc monitor.c -o monitor -lX11 -lXext
    
```

私がやりたかったことは、Raspberry
Pi専用モニタのバックライト制御なので、`state`の値が`DPMSModeOn`か、そうでないかに応じて、バックライト制御を行えば、目的を実現できそうです。

なお、X11とスクリーンセーバーとパワーマネジメントに関することなので、Xfceは関係ありません。

* * *

### 参考情報

DPMSに関して  
<https://wiki.archlinuxjp.org/index.php/Display_Power_Management_Signaling>

ディスプレイの状態を得る  
<https://stackoverflow.com/questions/3819255/how-to-check-if-linux-console-
screensaver-has-blanked-screen>
CC BY-SA 3.0
2017-01-08T13:01:00.487
31710
2017-01-08T13:01:00.487
2020-06-17T08:14:45.997
-1
3337
22581
answer