当有两个或多个显示器一起工作时,是否有任何方法可以通过发出如下命令将其中一个显示器置于待机/暂停状态:xset dpms force suspend
?或为此目的设置一个时间,例如:xset dpms 100 0 0
分别在这些显示器上工作?
我有两个互相工作的显示器,eDP1(我的笔记本电脑)和 VGA1(外部显示器)。
如果我没有直接与它们交互,我希望它们每个都分别进入挂起/待机模式,假设我在 VGA1 上看电影,并且一个半小时内 eDP1 什么也没做。
我对使用它不感兴趣,xrandor --off --output eDP1
因为它的速度不够快。
我希望我的显示器能够正常工作,只需简单移动鼠标,我就能快速地在它们之间切换。
- 运行:Ubuntu 18.04
- 窗口管理器:OpenBox
答案1
无法使用 xset(实际上也是 X11)控制单个监视器
正如标题所示,这是不可能的,原因如下:如何 xset
构建并由于其使用的 X11 函数。如果我们查看源代码,xset
会发现调用DPMSForceLevel(dpy,DPMSModeSuspend)
(557 行),而显示变量dpy
来自XOpenDisplay()
函数(203 行),即定义:
服务器与其屏幕和输入设备一起称为显示器。
换句话说,xset
将设置全局应用于整个显示屏,而不是单个屏幕。要实现这一点,必须更改xset
源代码。DPMS 扩展本身似乎大多只调用整个显示屏,而不是单个屏幕,因此甚至无法使用 X11 库编写自定义代码。
通过子系统手动控制该设置/sys
似乎也不起作用
$ sudo bash -c 'echo Off > /sys/class/drm/card0-VGA-1/dpms'
[sudo] password for admin:
bash: /sys/class/drm/card0-VGA-1/dpms: Permission denied
当发生键或鼠标事件时,屏幕也会退出 DPMS 模式,因此考虑到您可能想要移动鼠标或使用键盘,这两种操作都会导致显示器退出 DPMS 模式。
其他解决方法
最好的替代方案(也是实际可行的解决方案)是xrandr
- 它可以用来控制单个“输出”。特别是,
xrandr --output VGA-1 -off
会关闭该输出。是的,您提到过您不想使用此解决方案,因为它不够快,但到目前为止,它是最好的解决方案。它有几个优点:
- 不受键盘和鼠标事件的影响
- 独立控制输出不同
xset
xrandr --output VGA-1 --brightness 0.1
虽然这是一个软件解决方案,但屏幕会以某种方式变色,使其看起来不亮,因此--brightness
显示屏实际上并没有在硬件层面变暗,也没有在硬件层面关闭。但是,它可以使屏幕变暗,并且还可以抵抗按键/鼠标事件。
我查看了 Mate 和 Budgie 屏幕保护程序的源代码,它们都是 GNOME 屏幕保护程序的分支,但无论如何,它们似乎是一种软件解决方案,因为源代码中没有提及 DPMS。
答案2
临时评论
- 应楼主的要求,我制作了下面的脚本关闭屏幕通过
xrandr
。在更长时间的测试中,结果非常糟糕。并不是关闭失败,而是在重新激活屏幕时,屏幕布局完全混乱了。我很乐意发布它以查看它是否适用于您的情况,但我的建议是不要使用它。
在脚本中,我回到将亮度设置为零。 - 关于我们是否应该定义主动监控器,有一些讨论通过鼠标位置, 或者按活动窗口的位置。如果不存在窗口,后者将不起作用。我们可能根本没有窗口(除了桌面本身),在这种情况下,选择变黑的窗口将是随机的(或者如果我们不包括例外,则会中断)。在我看来,唯一有意义的选择 - 并且在所有情况下都能以可预测的方式工作 - 是通过鼠标位置定义活动屏幕。此外,这也是窗口管理器决定新窗口应出现在哪里的方式。
那么我在这个版本中做了哪些改变呢?
默认情况下,空闲时间现在由键盘和鼠标活动定义。唤醒也由其中之一完成。
自动调暗非活动屏幕
正如我的同事们所说,从 CLI 单独关闭屏幕充其量是一个挑战,而且我也没有找到选择。
我确实找到了一种方法来自动暗淡所有屏幕,除了x 时间之后,鼠标所在的位置。
开始了
#!/usr/bin/env python3
import subprocess
import gi
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk
import time
import sys
def get_idle():
try:
return int(subprocess.check_output("xprintidle")) / 1000
except subprocess.CalledProcessError:
return 0
def get_monitors():
screen = Gdk.Screen.get_default()
n_mons = display.get_n_monitors()
mons = [screen.get_monitor_plug_name(i) for i in range(n_mons)]
return mons
def set_mon_dimmed(mon, dim):
print(mon, dim)
val = "0.0" if dim else "1"
try:
subprocess.Popen(["xrandr", "--output", mon, "--brightness", val])
except subprocess.CalledProcessError:
print("oops")
def mousepos():
# find out mouse location
return Gdk.get_default_root_window().get_pointer()[1:3]
def get_currmonitor_atpos(x, y, display=None):
"""
fetch the current monitor (obj) at position. display is optional to save
fuel if it is already fetched elsewhere
"""
if not display:
display = Gdk.Display.get_default()
return display.get_monitor_at_point(x, y)
display = Gdk.Display.get_default()
wait = int(sys.argv[1])
elapsed = 0
# set intervals to check
res = 2
monitors = [m for m in get_monitors()]
for m in monitors:
set_mon_dimmed(m, False)
monrecord = {}
for m in monitors:
monrecord[m] = {"idle": 0, "dimmed": False}
display = Gdk.Display.get_default()
idle1 = 0
while True:
time.sleep(res)
curr_mousepos = mousepos()
activemon = get_currmonitor_atpos(
curr_mousepos[0], curr_mousepos[1]
).get_model()
idle2 = get_idle()
if idle2 < idle1:
monrecord[activemon]["idle"] = 0
if monrecord[activemon]["dimmed"]:
set_mon_dimmed(activemon, False)
monrecord[activemon]["dimmed"] = False
for m in monrecord.keys():
curr_idle = monrecord[m]["idle"]
print(m, curr_idle)
if all([
curr_idle > wait,
monrecord[m]["dimmed"] is not True,
m != activemon
]):
set_mon_dimmed(m, True)
monrecord[m]["dimmed"] = True
else:
if m != activemon:
monrecord[m]["idle"] = curr_idle + res
idle1 = idle2
如何设置
设置很简单:
确保已
python3-gi
安装xprintidle
sudo apt install python3-gi xprintidle
将上述脚本复制到一个空文件中,另存为
dim_inactive
,然后使其可执行通过命令运行:
/path/to/dim_inactive <idle_time_in_seconds>
一个例子:
/path/to/dim_inactive 120
会使所有屏幕变暗鼠标不在的地方两分钟后
附加信息/说明
- 该脚本在启动时列出所有屏幕
- 记录空闲时间每台监视器(可能超过 2)。如果监视器在 x 秒内未被访问,则监视器将变黑,除了鼠标所在的显示器。
- 根据一个好的(但坏的)传统,Gnome 不断破坏一些东西并不断更改 API。因此,在 19.04 及更高版本上运行此脚本时,您会收到一些已弃用的警告。同时,它不会在 PEP8 上中断。无论如何都会更新到最新的 API。
答案3
多年来,我一直将笔记本电脑设置为当盖子关闭时,笔记本电脑将处于挂起状态,并且外接显示器将变为空白。
由于您想在外接显示器上观看 90 分钟的视频,并且笔记本电脑屏幕变黑,我将盖子关闭选项更改为“不执行任何操作”:
- 优点:当我关闭笔记本电脑盖时,所有笔记本电脑窗口都会进入全屏视频。
- 优点:当我打开笔记本电脑盖时,窗口会恢复,并且不再位于全屏视频下方。
- 缺点:我必须使视频非全屏才能访问顶部栏菜单,从齿轮菜单中选择暂停。
- 优点:当系统通过外接显示器上的菜单暂停时,打开笔记本电脑盖仍可恢复系统。
我没有使用 DPMS 作为外接显示器,但您可以使用xset q
命令检查您的设置:
$ xset q
Keyboard Control:
auto repeat: on key click percent: 0 LED mask: 00000002
XKB indicators:
00: Caps Lock: off 01: Num Lock: on 02: Scroll Lock: off
03: Compose: off 04: Kana: off 05: Sleep: off
06: Suspend: off 07: Mute: off 08: Misc: off
09: Mail: off 10: Charging: off 11: Shift Lock: off
12: Group 2: off 13: Mouse Keys: off
auto repeat delay: 500 repeat rate: 33
auto repeating keys: 00ffffffdffffbbf
fadfffefffedffff
9fffffffffffffff
fff7ffffffffffff
bell percent: 50 bell pitch: 400 bell duration: 100
Pointer Control:
acceleration: 5/1 threshold: 5
Screen Saver:
prefer blanking: yes allow exposures: yes
timeout: 0 cycle: 0
Colors:
default colormap: 0xb3 BlackPixel: 0x0 WhitePixel: 0xffffff
Font Path:
/usr/share/fonts/X11/misc,/usr/share/fonts/X11/Type1,built-ins
DPMS (Energy Star):
Standby: 0 Suspend: 0 Off: 0
DPMS is Disabled
请注意以下几行:
Screen Saver:
prefer blanking: yes
- 你可能想要
prefer blanking: no
还请注意以下几行:
DPMS (Energy Star):
Standby: 0 Suspend: 0 Off: 0
DPMS is Disabled
- 您可能希望在需要时
DPMS is enabled
设置监视器Standby
。
希望其他用户已经使用过这些选项并为您发布详细的答案。
答案4
如果显示器有 ddc 可以工作 - 它也相对较慢,但几乎是减少没有 xrandr 的 ccfl 背光显示器功耗的唯一方法。不幸的是,只有一半的显示器实现了它。
$ ddccontrol dev:/dev/i2c-4
...
> Power control
> id=dpms, name=DPMS Control, address=0xd6, delay=-1ms, type=2
Possible values:
> id=on - name=On, value=1
> id=standby - name=Standby, value=4
...
您可以通过查看 Sergiy 上面提到的 /sys/class/drm/card* 目录(即它们的 i2c* 子目录)轻松地将 i2c 总线连接到输出。
因此,“ddccontrol dev:/dev/i2c-4 -r 0xd6 -w 4”将其设置为待机,“ddccontrol dev:/dev/i2c-4 -r 0xd6 -w 1”将其再次设置为开启。
我设置了 cronjobs,包括 getIdlehttps://github.com/IonicaBizau/screensaver/blob/master/getIdle.c给出 X 空闲时间(以毫秒为单位)。
您可能应该将您的用户添加到 i2c 组或以其他方式启用对 ddc 总线的访问。
另一个怪癖:虽然 ddc 控制标记为“电源”,但至少在我的显示器上我不能用它来确定实际的电源状态 - 如果我手动关闭显示器,它仍然显示“开”并且我无法通过 i2c 打开它。