14

我正在寻找一种体面的、非蹩脚的方式来抑制 xscreensaver、kscreensaver 或 gnome-screensaver,无论哪个可能正在运行,最好以与屏幕保护程序无关的方式,并且它绝对必须快速执行。

我已阅读xscreensaver 常见问题解答

我有一个基于 gtk 的游戏程序,它在混合多个音频通道时以 30 帧/秒的速度运行,并且由于它是由操纵杆控制的,因此有时会启动“the”屏幕保护程序。我将“the”放在引号中,因为有至少三个不同的流行屏幕保护程序,xscreensaver、gnome-screensaver 和 kscreensaver,每个都有自己独特而笨重的方法,应用程序可能会通过这些方法来抑制它们。

有没有人将代码封装成一个快速的代码块来禁止所有这些?哦,它必须与 GPL 兼容。

目前,如果检测到任何屏幕保护程序并且操纵杆正在使用中,我的代码只是对不合作的屏幕保护程序开发人员发出悲哀的抱怨,并且实际上除了建议用户手动禁用屏幕保护程序之外并没有尝试做任何事情,这是我唯一能做的事情想去做是非常丑陋的,我干脆拒绝去做。

只是想知道是否有其他人遇到过这个问题,他们做了什么,如果他们做了什么,它是否像我认为的那样丑陋,或者是否有一些优雅的解决方案......似乎可能以某种方式合成 X 事件以欺骗屏幕保护程序,使其认为有一些活动可能会以一种通用的方式来解决问题,但我真的不知道该怎么做(并且希望你不需要 root 来做到这一点.)

有任何想法吗?


嗯,不幸的是,至少在 Fedora core 8 上,这似乎不起作用。

xdg-screensaver 脚本在那里,并且似乎打算工作,但实际上并没有工作。

一旦你执行“xdg-screensaver 暂停窗口 ID”,窗口 ID 是从程序中通过

xwindow_id = GDK_WINDOW_XWINDOW (GTK_WIDGET (widget)->window);

或者无论是通过xprop获取窗口id,还是手动运行xdg-screensaver,都会创建两个进程:

[scameron@zuul wordwarvi]$ ps -efa | grep xdg
scameron  4218     1  0 20:12 pts/2    00:00:00 /bin/sh /usr/bin/xdg-screensaver suspend 0x3a00004
scameron  4223     1  0 20:12 pts/2    00:00:00 /bin/sh /usr/bin/xdg-screensaver suspend 0x3a00004
scameron  4313  3151  0 20:15 pts/1    00:00:00 grep xdg
[scameron@zuul wordwarvi]$ 

他们永远不会死,即使他们应该等待的程序死了,屏幕保护程序也永远不会重新启用。

[scameron@zuul wordwarvi]$ xdg-screensaver status
disabled
[scameron@zuul wordwarvi]$ ls -ltr /tmp | grep xdg
-rw------- 1 scameron scameron    15 2009-01-20 20:12 xdg-screensaver-scameron--0.0
[scameron@zuul wordwarvi]$ 

运行 xdg-screensaver resume window-id 不会恢复屏幕保护程序。

要重新启用屏幕保护程序,我必须手动杀死它们,并手动删除它留在 /tmp 中的文件:

[scameron@zuul wordwarvi]$ kill 4218 4223
[scameron@zuul wordwarvi]$ rm /tmp/xdg-screensaver-scameron--0.0 
[scameron@zuul wordwarvi]$ xdg-screensaver status
enabled
[scameron@zuul wordwarvi]$ 

所以,好意,但似乎并没有真正奏效。


不,当然不希望每帧都运行它,但不希望它在运行时引起打嗝,仅此而已。考虑到合成 X 事件,我想象它经常足以让屏幕保护程序认为有活动。

看着 xdg-screensaver (这似乎是一个 shell 脚本,最终只是为我的进程做一个“等待”——很酷),它似乎是为了做我想做的事。我知道我不可能是唯一或第一个面临这个问题的人。

4

6 回答 6

6

不,但是是的……

没有很好的干净方法可以做到这一点。在我看来,应该有一种由 X 服务器管理的机制,屏幕保护程序和感兴趣的应用程序都可以自愿使用它来协商在一个或多个程序运行期间抑制任何屏幕保护程序。但据我所知,尚不存在这样的机制。GNOME 和 KDE 看起来正在实现一个 DBUS 方法来解决这个问题,但在我看来,即使它变得普遍(它还不够广泛,无法在 3rd 方代码中依赖它),它也不是正确的方法。

但是,xdg-screensaver 是 FreeDesktop 标准化的 shell 脚本,您可以将其作为子进程运行以控制屏幕保护程序。它控制最流行的屏幕保护程序,操作系统供应商将负责更新/维护它,以便在未来与更新的屏幕保护程序或更好的方法一起使用。与许多其他 kludges 不同,如果您的应用程序通过某些忘记调用重新启用代码的路线崩溃或退出,它将自动重新启用屏幕保护程序。有关如何使用它的详细信息,请参阅手册页。

作为一个 GTK+ 用户,对你来说最棘手的方面可能是创建子进程来运行 shell 脚本(如果你还没有这样做,那么你会想要找到一个关于使用 fork + exec 的教程)并获取 XWindow要提供给 xdg-screensaver 的应用程序主窗口的 ID。

您要求代码应该“快速”。这让我想知道您是否希望每帧都运行它 - 不要。xdg-screensaver 解决方案允许您显式禁用或重新启用屏幕保护程序,而不是尝试每帧抑制一次或类似的事情。

于 2009-01-20T11:44:52.597 回答
4

尝试这个:xdg-screensaver suspend [window id]

(见: http: //portland.freedesktop.org/xdg-utils-1.0/xdg-screensaver.html

一个 Bash 脚本解决方案:

activ_win_id=`DISPLAY=:0.${display} xprop -root _NET_ACTIVE_WINDOW`
activ_win_id=${activ_win_id:40:9}
xdg-screensaver suspend $activ_win_id

它适用于 gnome 屏幕保护程序。

还有更复杂的 DBus“禁止”方法:https ://people.gnome.org/~mccann/gnome-screensaver/docs/gnome-screensaver.html#gs-method-Inhibit

dbus-send --session \
      --dest=org.gnome.ScreenSaver \
      --type=method_call \
      --print-reply \
      --reply-timeout=20000 \
      /org/gnome/ScreenSaver \
      org.gnome.ScreenSaver.Inhibit \
      [application name e.g. ""] \
      [reason e.g."playing a game"] \
      [non-zero-random-integer e.g. 123]
于 2015-01-25T14:28:29.557 回答
3

编辑 2019/12/04:

我回到这个,发现dbus-send现在不能正常工作。Inhibit一旦 D-Bus 连接被释放(dbus-send退出时发生) ,该方法就会被释放。

一个好方法(使用 Gnome 3.34)是以下python 脚本

#!/usr/bin/python
# coding=utf-8
# Usage: gnome-inhibit <command-line>
# Example: gnome-inhibit mpv video.mp4

import subprocess
import dbus
import sys
import os

bus = dbus.SessionBus()
proxy = bus.get_object('org.freedesktop.ScreenSaver','/org/freedesktop/ScreenSaver')
iface = dbus.Interface(proxy, 'org.freedesktop.ScreenSaver')
cookie = iface.Inhibit(sys.argv[1], "gnome-inhibit")
print("Inhibiting screensaver (pid: %d)" % os.getpid())
print("Executing: %s" % subprocess.list2cmdline(sys.argv[1:]))

subprocess.check_call(sys.argv[1:])

不再起作用的旧答案:

当前的方式(在 Gnome 3.22 和可能的其他,如 KDE 下)似乎是这样,它返回一个 uninhibition cookie 作为uint32

dbus-send --session \
      --dest=org.freedesktop.ScreenSaver \
      --type=method_call \
      --print-reply \
      --reply-timeout=20000 \
      /org/freedesktop/ScreenSaver \
      org.freedesktop.ScreenSaver.Inhibit \
      string:program string:reason

然后,禁用抑制:

dbus-send --session \
      --dest=org.freedesktop.ScreenSaver \
      --type=method_call \
      --print-reply \
      --reply-timeout=20000 \
      /org/freedesktop/ScreenSaver \
      org.freedesktop.ScreenSaver.UnInhibit \
      uint32:<inhibit-cookie>

这是一个小脚本,它禁用给定程序的屏幕保护程序,然后在退出时恢复它。

D-Feet对反省不断变化的 D-Bus 方法名称特别有帮助)

于 2017-04-20T22:34:15.553 回答
2

它不是一个完全与桌面无关的解决方案,但如果安装了核心 Gnome 库(许多基于 GTK 的应用程序需要它们),它也可以在其他桌面环境中工作:

禁用屏幕保护程序:

gsettings set org.gnome.desktop.screensaver idle-activation-enabled false

(重新)启用屏幕保护程序:

gsettings set org.gnome.desktop.screensaver idle-activation-enabled true
于 2013-06-30T21:17:41.963 回答
1

电影播放器​​通常禁用屏幕保护程序。您可以查看mplayer -code 以了解他们是如何做到的。

对于常规 X,他们在支持的情况下使用XScreenSaverSuspend 。

于 2009-01-20T11:22:36.840 回答
0

这个“肮脏的解决方案”适用于 Debian 10 + LXDE:

[ "$(cat ~/.xsessionrc | grep 'xset -dpms')" ] || echo 'xset -dpms' >> ~/.xsessionrc  # disables DPMS (Energy Star) features
sed -i '/^timeout:/c timeout:\t3:00:00' ~/.xscreensaver  # 3 hours should be enough to see a film without interruptions
# DOESN'T WORK:  xset s off   # turns the screen saver functions off
于 2021-03-13T14:28:52.253 回答