使用Python禁止屏幕保护程序

时间:2012-06-04 17:17:06

标签: python linux screensaver xorg

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

3 个答案:

答案 0 :(得分:4)

我前一段时间一直在研究这个问题,最后最终使用xdg-screensaver,我通过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的内容,如dbusgnome-screensaver-command

我真的不喜欢xwininfo的号召,并希望有一个更清洁的方式,但到目前为止找不到更好的东西。 xwininfo方法的另一个问题是它使用根窗口的id而不是app窗口。使用应用程序窗口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()

答案 1 :(得分:2)

我知道这个问题很老,但有一个更现代的答案:现在大多数关于linux的DE使用dbus进行通信,你可以使用它:

shell中的

,使用kde工具:

qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Inhibit "myapps" "because I want it"

这个dbus调用将返回一个cookie(一个数字),用于取消禁止screesaver:

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)

答案 2 :(得分:0)

讨论

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

caffeinecaffeine-indicator是用Python 3编写的,而caffeine-screensaver是用shell脚本编写的重新命名的xdg-screensaver

ccpizza 的上半部分答案很棒,因为它是跨DE的,与咖啡因的实现非常相似。我对xdg-screensaver zombie进程没有任何问题,但我确信如果我更好地了解用例或它发生的条件,它可以得到纠正。只是运行xdg-screensaver suspend ROOT_WINDOW_ID的一个FYI将为跟踪过程提供背景并使其无限期运行(直到恢复)。

如果您对实施真正的跨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。使用桌面的根窗口ID xdg-screensaver suspend将无限期地禁用桌面的屏幕保护程序。使用特定窗口的ID将在窗口期间禁用桌面的屏幕保护程序。

Shell脚本

要确定有效窗口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