有没有一种好的方法可以在Linux中禁止屏幕保护程序?

发布于 2024-07-11 10:27:51 字数 2322 浏览 5 评论 0原文

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

我已阅读 xscreensaver 常见问题解答

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

有人封装了代码来抑制所有这些到快速代码块中吗? 哦,它必须兼容 GPL。

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

只是想知道是否有其他人遇到过这种情况,他们做了什么,他们是否做了什么,是否像我看来的那样丑陋,或者是否有一些优雅的解决方案......似乎可能会以某种方式合成 X 事件来愚弄屏幕保护程序,让其认为某些活动可能以通用的方式实现这一点,但我真的不确定如何做到这一点(并希望您不需要 root 权限才能做到这一点) 。)

有任何想法吗?


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

xdg-screensaver 脚本就在那里,似乎可以工作,但实际上不起作用。

一旦你执行“xdg-screensaver suspend window-id”,其中窗口 id 是通过程序内获取的

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

,或者窗口 id 是通过 xprop 获取的,并且 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-screensaverresumewindow-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 脚本,最终只是“等待”我的进程——很酷),它似乎就是为了做我想做的事情。 我知道我不可能是唯一一个或第一个面临这个问题的人。

I'm looking for a decent, non-lame way to inhibit xscreensaver, kscreensaver, or gnome-screensaver, whichever might be running, preferably in a screensaver-agnostic manner, and it absolutely positively must execute fast.

I've read the xscreensaver FAQ.

I have a gtk based game program that's cranking out 30 frames/second while mixing several channels of audio, and since it's controlled by a joystick, sometimes "the" screensaver will kick in. I put "the" in quotes, because there are at least three different popular screensavers, xscreensaver, gnome-screensaver, and kscreensaver, each with their own unique and clunky methods by which an application might inhibit them.

Has anybody encapsulated the code to inhibit all of these into a fast chunk of code? Oh, and it has to be GPL compatible.

Currently my code simply whines piteously about the uncooperative screensaver developers if any screensaver is detected and the joystick is in use, and doesn't actually try to do anything other than advise the user to manually disable the screensaver, as the only other thing I can think to do is so incredibly ugly that I simply refuse to do it.

Just wondering if anybody else has run into this, and what they've done, and if they did anything, if it was as ugly as it seems to me it would have to be, or if there's some elegant solution out there... Seems like maybe synthesizing X events somehow to fool the screensaver into thinking there's some activity might do the trick in a universal way, but I'm really not sure how to do that (and hoping you wouldn't need to be root to do it.)

Any ideas?


Hmm, unfortunately, at least on Fedora core 8, this does not appear to work.

The xdg-screensaver script is there, and seems to be intended to work, it just doesn't actually work.

Once you do "xdg-screensaver suspend window-id", where window id is gotten from within the program via

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

Or whether the window id is gotten via xprop, and xdg-screensaver run manually, two processes are created:

[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]$ 

And they never die, even after the program they are supposedly waiting for dies, and the screensaver is never re-enabled.

[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]$ 

Running xdg-screensaver resume window-id does not resume the screensaver.

To re-enable the screensaver, I have to manually kill them, and manually remove the files it leaves around in /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]$ 

So, good intentions, but doesn't seem to actually work.


No, of course not expecting to run it every frame, but don't want it causing hiccups when it does run, is all. With my thought of synthesizing X events, I was imagining it would be just often enough to make the screen saver think there was activity.

Looking at xdg-screensaver (which seems to be a shell script that ultimately just does a "wait" for my process -- cool) it seems to be made to do just what I want. I knew I couldn't be the only or first one to face this problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

与风相奔跑 2024-07-18 10:27:51

不,但是是的......

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

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

作为 GTK+ 用户,最棘手的方面可能是创建子进程来运行 shell 脚本(如果您之前没有这样做过,您将需要找到有关使用 fork + exec 的教程)并获取 XWindow要提供给 xdg-screensaver 的应用程序主窗口的 ID。

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

No, but yes...

There's no nice clean way to do this. In my opinion there should be a mechanism administrated by the X server, which both screensavers and interested applications can voluntarily use to negotiate suppression of any screensaver during the runtime of one or more programs. But no such mechanism yet exists to my knowledge. GNOME and KDE look to be implementing a DBUS approach to this problem, but in my opinion even if it becomes widespread (it isn't yet widespread enough to rely on it in 3rd party code) it's not the right approach.

However, xdg-screensaver is a FreeDesktop standardised shell script which you can run as a sub-process to control the screensaver. It controls most popular screensavers, and the OS vendor would be responsible for updating it/ maintaining it to work with newer screensavers or better ways of doing this in the future. Unlike many other kludges it will automatically re-enable the screensaver if your application crashes or exits via some route that forgets to call the re-enable code. See the manual page for details in how to use it.

As a GTK+ user probably the trickiest aspects of this for you would be creating the sub-process to run the shell script (if you haven't done this before you will want to find a tutorial about using fork + exec) and getting the XWindow ID of your application's main window to give to xdg-screensaver.

You ask that the code should be "fast". This makes me wonder if you're expecting to run it every frame - don't. The xdg-screensaver solution allows you to disable or renable the screensaver explicitly, rather than trying to suppress it once per frame or anything like that.

欲拥i 2024-07-18 10:27:51

编辑2019/12/04:

我回到这里,发现dbus-send现在无法正常工作。 D-Bus 连接释放后(dbus-send 退出时发生),Inhibit 方法也会释放。

一个好的方法(使用 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< /code> :

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 方法名称特别有帮助)

Edit 2019/12/04:

I went back to this and found out that dbus-send doesn't work properly now. The Inhibit method is released as soon as the D-Bus connection is released (which happens when dbus-send exits).

A good method (working with Gnome 3.34) is the following python script:

#!/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:])

Old answer that doesn't work anymore:

The current way (under Gnome 3.22 and possibly others such as KDE) seems to be this, which returns an uninhibition cookie as an 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

Then, to disable the inhibition :

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>

Here is a small script that disables the screensaver for a given program, then later restores it on exit.

(D-Feet has been especially helpful for introspecting the ever-changing D-Bus method names)

终止放荡 2024-07-18 10:27:51

试试这个:xdg-screensaver 挂起[窗口 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-screensaver。

还有更复杂的 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]

Try this: xdg-screensaver suspend [window id]

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

a Bash script solution:

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

It works for gnome-screensaver.

And there's the more complicated DBus "inhibit" method: 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]
剩余の解释 2024-07-18 10:27:51

电影播放器​​通常会禁用屏幕保护程序。 您可以浏览 mplayer 代码来看看他们是如何做到这一点的。

对于常规 X,他们使用 XScreenSaverSuspend 支持的地方。

Movie-players typically disable screensavers. You could poke around the mplayer-code to see how they do it.

For regular X, they use XScreenSaverSuspend where supported.

最冷一天 2024-07-18 10:27:51

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

禁用屏幕保护程序:(

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

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

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

It is not an entirely desktop-agnostic solution, but if core Gnome libraries are installed (many GTK-based apps require them) it could work on other desktop environments too:

Disable screensaver:

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

(Re)enable screensaver:

gsettings set org.gnome.desktop.screensaver idle-activation-enabled true
清君侧 2024-07-18 10:27:51

这个“肮脏的解决方案”适用于 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

This 'dirty solution' works for me on 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
人│生佛魔见 2024-07-18 10:27:51

安装 caffe-ng。 托盘应用程序。 完全可定制的激活和忽略列表。 音频检测。 当您不希望时,屏幕保护程序/储物柜永远不会再次关闭。 简单的。

Install caffine-ng. Tray app. Totally customizable activate and ignore lists. Audio detection. Screensaver / Locker never goes off again when you don't want it to. EASY.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文