在 Linux 中禁用屏幕保护程序的更好的跨 DE 方法是什么?我在这里找到了一些东西,但它仅适用于 gnome-screensaver。我想知道是否有任何方法可以模拟击键或某些 X.Org API 来禁用屏幕保护程序激活。
3 回答
我前段时间一直在研究这个问题,最后最终使用xdg-screensaver
了我调用的 via subprocess
。
import subprocess
def suspend_screensaver():
window_id = subprocess.Popen('xwininfo -root | grep xwininfo | cut -d" " -f4', stdout=subprocess.PIPE, shell=True).stdout.read().strip()
#run xdg-screensaver on root window
subprocess.call(['xdg-screensaver', 'suspend', window_id])
def resume_screensaver(window_id):
subprocess.Popen('xdg-screensaver resume ' + window_id, shell=True)
这并不理想,但显然没有其他解决方案不涉及与特定于 DE 的东西(如dbus
or )混在一起gnome-screensaver-command
。
我真的不喜欢打电话xwininfo
并希望有一种更清洁的方式,但到目前为止找不到更好的方法。该方法的另一个问题xwininfo
是它使用根窗口的 id 而不是应用程序窗口。使用应用程序窗口 id 而不是根窗口将不再需要该resume_screensaver
方法,因为它会在窗口被销毁后立即恢复。
如果你想在这里模拟击键,我已经使用了一段时间的一个简单的 bash 脚本。它确实需要xdotool
单独安装。
#!/bin/bash
while :
do
sleep 200
nice -n 1 xdotool key shift
echo .
done
更新
在使用了上面的 python 解决方案一年多之后,发现它偶尔会创建僵尸进程和/或太多的实例xdg-screensaver
,所以在四处挖掘之后,我找到了一个更简单的替代方案,它是Gnome 特定的,但即使在一个非 Gnome DE (XFCE),因为许多基于 GTK 的应用程序都需要核心 Gnome 库,即使您没有 Gnome 桌面也是如此。
import subprocess
def suspend_screensaver():
'suspend linux screensaver'
proc = subprocess.Popen('gsettings set org.gnome.desktop.screensaver idle-activation-enabled false', shell=True)
proc.wait()
def resume_screensaver():
'resume linux screensaver'
proc = subprocess.Popen('gsettings set org.gnome.desktop.screensaver idle-activation-enabled true', shell=True)
proc.wait()
我知道这个问题很老,但有一个更现代的答案:现在大多数 Linux 上的 DE 都使用 dbus 进行通信,你可以使用这个:
在 shell 中,使用 kde 工具:
qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Inhibit "myapps" "because I want it"
这个 dbus 调用将返回一个 cookie(一个数字),这将需要取消抑制屏幕保护程序:
qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.UnInhibit $COOKIE
在python中,它将类似于
import dbus
bus = dbus.SessionBus()
saver = bus.get_object('org.freedesktop.ScreenSaver', '/ScreenSaver')
saver_interface = dbus.Interface(saver, dbus_interface='org.freedesktop.ScreenSaver')
# now we can inhibit the screensaver
cookie=saver_interface.Inhibit("myapps", "because I want it")
# we can also restore it
saver_interface.UnInhibit(cookie)
讨论
TLDR;没有任何跨 DE 方法可以使用纯 Python 来禁止屏幕保护程序。但是,该问题还询问了有关使用 Linux 执行此操作的问题(可能来自 shell)。需要明确的是,在 Linux 中没有任何特别好的跨 DE 方法可以做到这一点,但至少有潜力。您可能想使用 hackish xdg-screensaver
shell 脚本。
这是我花了一些时间研究的话题。我对那里的任何解决方案都不满意,所以在使用了一些自制工具之后,我最终修改了咖啡因项目以满足我的需求,并且从那以后一直在愉快地使用它。我会总结一下我在这个过程中学到的一些东西。
如果您不熟悉它,我建议您查看咖啡因(Launchpad PPA @ https://launchpad.net/~caffeine-developers/+archive/ubuntu/ppa)。
咖啡因项目主要由以下脚本组成:caffeine-screensaver
caffeine
caffeine-indicator
caffeinate
caffeine
并且caffeine-indicator
是用 Python 3 编写的,而caffeine-screensaver
它是xdg-screensaver
用 shell 脚本编写的。
ccpizza答案的前半部分很棒,因为它是跨 DE 并且与咖啡因的实现非常相似。我对 xdg-screensaver 僵尸进程没有任何问题,但我确信如果我更好地了解用例或它发生的条件,它可以得到补救。仅供参考,运行xdg-screensaver suspend ROOT_WINDOW_ID
将使跟踪进程后台运行并使其无限期运行(直到恢复)。
如果您对实现真正的跨 DE 解决方案感兴趣,那么我强烈建议您检查上述xdg-screensaver
/ caffeine-screensaver
。LightsOn的许多分支也已经成熟。
xdg-screensaver
检测桌面环境(KDE、Gnome、XFCE、LXDE、xscreensaver 或 gnome-screensaver)并采取相应措施。对于该xdg-screensaver suspend
命令,它会运行xset -dpms
以禁用 DPMS、特定于 DE 的命令,然后在其持续时间内监视提供的窗口 ID。如果窗口消失,则运行 resume 命令并退出 xdg-screensaver。该xdg-screensaver resume
命令由xset +dpms
(仅当最初启用 DPMS 时)然后是特定于 DE 的命令组成。
请注意,如果 xprop 可用,xdg-screensaver 只会跟踪提供的窗口 ID(它是 x11-utils 的一部分,因此应该是)。要跟踪窗口,它会在后台xprop -id WINDOW_ID -spy
监视窗口的更改。它将前面提到的进程的 PID 和窗口 ID 一起存储在一个锁定文件中,以便在挂起和恢复时引用。DPMS 的原始状态在单独的锁定文件中引用。锁定文件应确保没有重复的进程。
该脚本完全是一团糟,所以我很同情任何不幸使用它的人,但我没有遇到任何问题。你可能不想重新发明轮子,所以如果你正在为公众消费创造一些东西,那么我建议你选择它。如果您正在创建供个人使用的东西,那么只需挖掘它并使用特定于您的 DE 的命令。
ccpizza建议使用subprocess.Popen('xwininfo -root | grep xwininfo | cut -d" " -f4', stdout=subprocess.PIPE, shell=True).stdout.read().strip()
获取桌面的根窗口 ID。使用桌面的根窗口 IDxdg-screensaver suspend
将无限期禁用桌面的屏幕保护程序。使用特定窗口的 ID 将在窗口期间禁用桌面的屏幕保护程序。
外壳脚本
要确定活动窗口 ID,您可以运行以下命令:
xprop -root _NET_ACTIVE_WINDOW | awk -F '[ ,]' '{print $5}'
要确定根窗口 ID,您可以运行以下命令:
xwininfo -root | awk '/^xwininfo: Window id: / {print $4}'
要确定屏幕保护程序超时,您可以运行以下命令:
xset q | awk '/^ timeout: / {print $2}'
注意:如果屏幕保护程序被禁用,结果将为 0
要确定DPMS 是启用还是禁用,您可以运行以下命令:
xset q | awk '/^ DPMS is / {print tolower($3)}'
Python 脚本
也有纯 Python 选项。该Xlib
模块非常适合这一点,原样ewmh
(它是 Xlib 的包装器)。
要使用 ewmh确定活动窗口 ID :
active_id = hex(ewmh.EWMH().getActiveWindow().id)
要使用 ewmh确定根窗口 ID :
root_id = hex(ewmh.EWMH().root.id)
要使用 Xlib确定活动窗口 ID :
from Xlib.display import Display
from Xlib.X import AnyPropertyType
active_id = hex(Display().screen().root.get_full_property(Display().get_atom('_NET_ACTIVE_WINDOW'), AnyPropertyType).value[0])
要使用 Xlib 确定根窗口 ID:
from Xlib.display import Display
root_id = hex(Display().screen().root.id)
要使用 Xlib确定屏幕保护程序超时:
from Xlib.display import Display
timeout = Display().get_screen_saver().timeout