私の MacBook Pro にはキーボードのバックライトが付いていて、とても素晴らしいのですが、ちょっとしたバグがあります。一定時間が経つと画面はオフになりますが、キーボードのバックライトは点灯したままです。
スクリーン セーバーの状態が変化したときに監視するための小さな DBUS Python スクリプトをコピーして変更してみましたが、スクリーンがオフになったときにはトリガーされず、スクリーン セーバーがアクティブまたは非アクティブになったときにのみトリガーされます。
from dbus.mainloop.glib import DBusGMainLoop
import dbus
import gobject
import logging
logging.basicConfig()
logger = logging.getLogger(__name__)
dbus_loop = DBusGMainLoop(set_as_default=True)
def message_callback(bus, message):
if message.get_interface() == "org.gnome.ScreenSaver":
if message.get_member() == "ActiveChanged":
screensaver_enabled = bool(message.get_args_list()[0])
logger.info("Screen saver changed. Active: %s", screensaver_enabled)
session = dbus.SessionBus(mainloop=dbus_loop)
session.add_match_string_non_blocking("interface='org.gnome.ScreenSaver'")
session.add_message_filter(message_callback)
logger.info("Starting up.")
loop = gobject.MainLoop()
loop.run()
これは、スクリーンセーバーが起動しているときはいつでもうまく機能しますが、スクリーンの電源状態が変わっても変更されません。これはスクリーンセーバーとは関係なく発生する可能性があります。設定の明るさとロックに移動すると、1 分後に画面の電源がオフになり、ロックされないように設定できます。その後、スクリーンセーバーの時間を別の時間、たとえば 10 分に設定できます。
org.gnome.SettingsDaemon.Power.Screen
インターフェースで信号を聴いてみましたChanged
が、画面の明るさを手動で変更した場合にのみ発生します。
画面の電源状態がいつ変化したかを判断するために、何を聞くことができますか? 画面の電源がオフになるたびに実行されるスクリプトを作成して、キーボードのバックライトを無効にしたいと考えています。
答え1
まあ、「評判」がないのでコメントを残せないのは残念です。これは解決策というよりはコメントです。
私も似たようなものを探していましたが、代わりに「org.gnome.SessionManager.Presence」を監視しています。モニターの後ろにバイアス照明用の LED があり、モニターでそれらのオン/オフを切り替えたいと思っています。
これは、コンピューターを手動でロックする場合は機能しますが、「画面オフ」と「画面をロックするまでの時間」の設定を異なる間隔のままにしておくと、モニターの電源がオフになると LED もオフになりますが、スクリーンセーバー ロックが作動すると LED が再びオンになります。
_getState () {
dbus-monitor --session "type=signal,interface=org.gnome.SessionManager.Presence,member=StatusChanged" |
while read x; do
case "$x" in
*"uint32 3"*)
/home/victor/bin/devices/kasa_cntrl.sh off
echo -e "$(date)\t-\tTurned off" >> "$log"
;;
*"uint32 0"*)
/home/victor/bin/devices/kasa_cntrl.sh on
echo -e "$(date)\t-\tTurned on" >> "$log"
;;
esac
done
}
答え2
Ubuntu 18.04 をインストールしたところ、デフォルトではスクリーンセーバーがないことがわかりました。正直に言うと、スクリーンセーバーは必要ないので、わざわざインストールするつもりはありません。
しかし、gnome からのいくつかのメソッド呼び出しがうまく機能していることがわかりました。また、AddUserActiveWatch
インターフェースからRemoveWatch
も呼び出しています。org.gnome.Mutter.IdleMonitor
これが私のスクリプトです:
#!/usr/bin/env python
import dbus, gobject
from dbus.mainloop.glib import DBusGMainLoop
from subprocess import call
def filter_cb(bus,message):
if message.get_member() == "AddUserActiveWatch":
print("Monitor off")
call("/usr/bin/g810-led -dv 046d -dp c337 -a 000000", shell=True)
elif message.get_member() == "RemoveWatch":
print("Monitor on")
call("/usr/bin/g810-led -dv 046d -dp c337 -p /etc/g810-led/profile", shell=True)
return
DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
bus.add_match_string_non_blocking("interface='org.gnome.Mutter.IdleMonitor',eavesdrop='true'")
bus.add_message_filter(filter_cb)
mainloop = gobject.MainLoop ()
mainloop.run ()
結果は次のとおりです。
- ディスプレイが暗くなり始めると、キーボードのバックライトが消えます
- キーボードはログイン画面ではなく、ログインに成功した後にのみ点灯します(ただし、ほぼ点灯しています)。
免責事項:
- org.gnome.Mutter.IdleMonitor の monitor という単語は、monitor アクションから来ており、モニター、つまり画面から来ているわけではありません。つまり、基本的にこれらは、ユーザーがアイドル状態であると宣言され、gnome によってアイドル状態でないと宣言されたときに呼び出されるメソッドのようです。実際のところ、私の場合、画面の電源がオフになったときと一致します。あなたの場合はそうではないかもしれません。
- どうやらこれをsystemdエントリとして追加することはできないようです。画面が必要なためです。ただし、
Startup Applications
GUIで追加することは可能で、動作します。 - 私はキーボードのバックライトのオン/オフを切り替えるためにg810-led実行ファイルを使用していますが、これは単なる例として扱う必要があります。他のキーボードでは動作しないのは明らかです。
PS: 「バグ」を発見しました。画面のフェードを中断すると、キーボードは消灯したままになります。
答え3
さて、その後年これにイライラした後、私はついに対策を講じ、DBus を監視してセッションのロック/ロック解除イベントを適切に受信する Python ユーティリティ スクリプトを作成しました。
のコードはここにホストされていますですが、以下にも記載します。私の目標は、いくつかの理由からこれを Rust で書き直すことですが、主な理由は、適切な Python ライブラリをインストールするためのパッケージをインストールしなくても、ユーザーが簡単に使用できるようにすることです。
前提条件
このコードを実行するには、次のものが必要です。
- 最近の Python 3、私はこれを Python 3.8.5 で書きました。
- 卵:
dbus-python >=1.2,<2
PyGObject >=3.36,<4
これらの Python egg は特定の Ubuntu パッケージによって提供されていますが、適切なバージョンではない可能性があります。16.04 では、必要なパッケージは次のとおりだと思います。
python3-gi
、これはPyGObject
python3-dbus
、これはdbus-python
ディストリビューションのバージョンが異なると、これらのパッケージが異なる場合があります。これが、私がこれを Rust で書き直したい理由の 1 つです。他の動機については、この回答の最後にリストします。
コード
コードを見てみましょう。
dbus-session-lock-watcher.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
import dbus
import logging
import sys
class ScreenSaverEventListener(object):
def __init__(self):
self.logger = logging.getLogger(self.__class__.__name__)
self.mainloop = DBusGMainLoop()
self.loop = GLib.MainLoop()
self.session_bus = dbus.SessionBus(mainloop=self.mainloop)
self.receiver_args, self.receiver_kwargs = None, None
def setup(self):
self.receiver_args = (self.on_session_activity_change,)
self.receiver_kwargs = dict(dbus_interface="org.freedesktop.DBus.Properties", path="/org/gnome/SessionManager",
signal_name="PropertiesChanged",
# callback arguments
sender_keyword="sender", destination_keyword="dest",
interface_keyword="interface", member_keyword="member", path_keyword="path",
message_keyword="message")
self.session_bus.add_signal_receiver(*self.receiver_args, **self.receiver_kwargs)
def on_session_activity_change(self, target: dbus.String, changed_properties: dbus.Dictionary, *args, **kwargs):
if target != "org.gnome.SessionManager" or "SessionIsActive" not in changed_properties:
return
if changed_properties.get("SessionIsActive"):
self.on_session_unlock()
else:
self.on_session_lock()
def on_session_lock(self):
self.logger.info("Session Locked")
def on_session_unlock(self):
self.logger.info("Session Unlocked")
def run(self):
self.logger.debug("Starting event loop.")
self.loop.run()
def shutdown(self):
self.logger.debug("Stopping event loop.")
self.session_bus.remove_signal_receiver(*self.receiver_args, **self.receiver_kwargs)
self.loop.quit()
def main():
setup_logging()
listener = ScreenSaverEventListener()
listener.setup()
try:
listener.run()
except KeyboardInterrupt:
sys.stderr.write("ctrl+c received, shutting down...\n")
listener.shutdown()
def setup_logging():
console = logging.StreamHandler(sys.stderr)
console.setFormatter(
logging.Formatter("%(asctime)s [%(levelname)-5s] %(name)s: %(message)s", datefmt="%Y-%m-%dT%H:%M:%S%z"))
logging.addLevelName(logging.WARNING, "WARN")
logging.getLogger().addHandler(console)
logging.getLogger().setLevel(logging.DEBUG)
if __name__ == "__main__":
main()
このコードに何か興味深いことをさせるには、次のように編集します。
ScreenSaverEventListener.on_session_lock
画面がロックされたときに実行されます