我的 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 中的「監視器」一詞來自監視操作,而不是來自監視器(又稱螢幕)。所以基本上這些似乎是當 gnome 聲明用戶空閒和不空閒時調用的方法。事實上,就我而言,它與螢幕關閉同時發生。就你而言,可能不會。
- 顯然你不能將其添加為系統條目,因為它需要一個螢幕。但是,您可以將其添加到
Startup Applications
GUI 中並且它可以工作 - 我正在使用 g810-led 可執行檔來開啟和關閉鍵盤背光,這應該只是一個範例,因為它顯然不適用於其他鍵盤
PS:發現一個「bug」。如果您中斷螢幕淡入淡出,鍵盤將保持不亮狀態。
答案3
好吧之後年由於對此感到沮喪,我最終做了一些事情並編寫了一個 Python 實用程式腳本來監視 DBus 並正確接收會話鎖定/解鎖事件。
這程式碼託管在這裡,但我也會將其包含在下面。我的目標是用 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 重寫這個的眾多原因之一,我將在這個答案的末尾列出我的其他動機。
程式碼
讓我們進入代碼。
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
,它將在螢幕鎖定時執行