6

在 Linux 中禁用屏幕保护程序的更好的跨 DE 方法是什么?我在这里找到了一些东西,但它仅适用于 gnome-screensaver。我想知道是否有任何方法可以模拟击键或某些 X.Org API 来禁用屏幕保护程序激活。

4

3 回答 3

4

我前段时间一直在研究这个问题,最后最终使用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 的东西(如dbusor )混在一起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()
于 2012-07-21T15:39:29.410 回答
3

我知道这个问题很老,但有一个更现代的答案:现在大多数 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)
于 2017-06-22T06:34:02.470 回答
0

讨论

TLDR;没有任何跨 DE 方法可以使用纯 Python 来禁止屏幕保护程序。但是,该问题还询问了有关使用 Linux 执行此操作的问题(可能来自 shell)。需要明确的是,在 Linux 中没有任何特别好的跨 DE 方法可以做到这一点,但至少有潜力。您可能想使用 hackish xdg-screensavershell 脚本。

这是我花了一些时间研究的话题。我对那里的任何解决方案都不满意,所以在使用了一些自制工具之后,我最终修改了咖啡因项目以满足我的需求,并且从那以后一直在愉快地使用它。我会总结一下我在这个过程中学到的一些东西。

如果您不熟悉它,我建议您查看咖啡因(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-screensaverLightsOn的许多分支也已经成熟。

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
于 2015-04-27T06:48:41.027 回答