Skip to content

Commit 12101cc

Browse files
committed
Add Xlib.ext.dpms
Based on the documentation found here: https://www.x.org/releases/X11R7.7/doc/xextproto/dpms.html It basically works, however there are some known issues: - Any rq.Request call (dpms_enable(), dpms_set_timeouts(), dpms_force_level()) only works if you call another rq.ReplyRequest function (dpms_get_version(), for example) afterwards. I tried to change them to use rq.ReplyRequest, but since they don't return anything they got stucked waiting for a response from X11. - DPMSInfo doesn't work. I don't have a clue why, I receive the following error when trying to call dpms_info(): ``` $ cat playground.py from Xlib import display d = display.Display() print(d.dpms_info()) $ python3 playground.py Traceback (most recent call last): File "playground.py", line 4, in <module> print(d.dpms_info()) File "Xlib/display.py", line 225, in __getattr__ return types.MethodType(function, self) TypeError: first argument must be callable ``` So I decided to comment this function for now.
1 parent 2dbeb64 commit 12101cc

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed

Xlib/ext/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
('XInputExtension', 'xinput'),
3939
('NV-CONTROL', 'nvcontrol'),
4040
('DAMAGE', 'damage'),
41+
('DPMS', 'dpms'),
4142
]
4243

4344
__all__ = map(lambda x: x[1], __extensions__)

Xlib/ext/dpms.py

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# Xlib.ext.dpms -- X Display Power Management Signaling
2+
#
3+
# Copyright (C) 2020 Thiago Kenji Okada <thiagokada@gmail.com>
4+
#
5+
# This library is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU Lesser General Public License
7+
# as published by the Free Software Foundation; either version 2.1
8+
# of the License, or (at your option) any later version.
9+
#
10+
# This library is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+
# See the GNU Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public
16+
# License along with this library; if not, write to the
17+
# Free Software Foundation, Inc.,
18+
# 59 Temple Place,
19+
# Suite 330,
20+
# Boston, MA 02111-1307 USA
21+
22+
'''
23+
This extension provides X Protocol control over the VESA Display
24+
Power Management Signaling (DPMS) characteristics of video boards
25+
under control of the X Window System.
26+
27+
Documentation: https://www.x.org/releases/X11R7.7/doc/xextproto/dpms.html
28+
'''
29+
30+
from Xlib import X
31+
from Xlib.protocol import rq
32+
33+
extname = 'DPMS'
34+
35+
36+
# DPMS Extension Power Levels
37+
# 0 DPMSModeOn In use
38+
# 1 DPMSModeStandby Blanked, low power
39+
# 2 DPMSModeSuspend Blanked, lower power
40+
# 3 DPMSModeOff Shut off, awaiting activity
41+
DPMSModeOn = 0
42+
DPMSModeStandby = 1
43+
DPMSModeSuspend = 2
44+
DPMSModeOff = 3
45+
46+
DPMSPowerLevel = (
47+
DPMSModeOn,
48+
DPMSModeStandby,
49+
DPMSModeSuspend,
50+
DPMSModeOff,
51+
)
52+
53+
54+
class DPMSGetVersion(rq.ReplyRequest):
55+
_request = rq.Struct(
56+
rq.Card8('opcode'),
57+
rq.Opcode(0),
58+
rq.RequestLength(),
59+
rq.Card16('major_version'),
60+
rq.Card16('minor_version'),
61+
)
62+
63+
_reply = rq.Struct(
64+
rq.ReplyCode(),
65+
rq.Pad(1),
66+
rq.Card16('sequence_number'),
67+
rq.ReplyLength(),
68+
rq.Card16('major_version'),
69+
rq.Card16('minor_version'),
70+
rq.Pad(20),
71+
)
72+
73+
74+
def get_version(self):
75+
return DPMSGetVersion(display=self.display,
76+
opcode=self.display.get_extension_major(extname),
77+
major_version=1,
78+
minor_version=1)
79+
80+
81+
class DPMSCapable(rq.ReplyRequest):
82+
_request = rq.Struct(
83+
rq.Card8('opcode'),
84+
rq.Opcode(1),
85+
rq.RequestLength(),
86+
)
87+
88+
_reply = rq.Struct(
89+
rq.ReplyCode(),
90+
rq.Pad(1),
91+
rq.Card16('sequence_number'),
92+
rq.ReplyLength(),
93+
rq.Bool('capable'),
94+
rq.Pad(23),
95+
)
96+
97+
98+
def capable(self):
99+
return DPMSCapable(display=self.display,
100+
opcode=self.display.get_extension_major(extname),
101+
major_version=1,
102+
minor_version=1)
103+
104+
105+
class DPMSGetTimeouts(rq.ReplyRequest):
106+
_request = rq.Struct(
107+
rq.Card8('opcode'),
108+
rq.Opcode(2),
109+
rq.RequestLength(),
110+
)
111+
112+
_reply = rq.Struct(
113+
rq.ReplyCode(),
114+
rq.Pad(1),
115+
rq.Card16('sequence_number'),
116+
rq.ReplyLength(),
117+
rq.Card16('standby_timeout'),
118+
rq.Card16('suspend_timeout'),
119+
rq.Card16('off_timeout'),
120+
rq.Pad(18),
121+
)
122+
123+
124+
def get_timeouts(self):
125+
return DPMSGetTimeouts(display=self.display,
126+
opcode=self.display.get_extension_major(extname),
127+
major_version=1,
128+
minor_version=1)
129+
130+
131+
class DPMSSetTimeouts(rq.Request):
132+
_request = rq.Struct(
133+
rq.Card8('opcode'),
134+
rq.Opcode(3),
135+
rq.RequestLength(),
136+
rq.Card16('standby_timeout'),
137+
rq.Card16('suspend_timeout'),
138+
rq.Card16('off_timeout'),
139+
rq.Pad(2)
140+
)
141+
142+
143+
def set_timeouts(self, standby_timeout, suspend_timeout, off_timeout):
144+
return DPMSSetTimeouts(display=self.display,
145+
opcode=self.display.get_extension_major(extname),
146+
major_version=1,
147+
minor_version=1,
148+
standby_timeout=standby_timeout,
149+
suspend_timeout=suspend_timeout,
150+
off_timeout=off_timeout)
151+
152+
153+
class DPMSEnable(rq.Request):
154+
_request = rq.Struct(
155+
rq.Card8('opcode'),
156+
rq.Opcode(4),
157+
rq.RequestLength(),
158+
)
159+
160+
161+
def enable(self):
162+
return DPMSEnable(display=self.display,
163+
opcode=self.display.get_extension_major(extname),
164+
major_version=1,
165+
minor_version=1)
166+
167+
168+
class DPMSDisable(rq.Request):
169+
_request = rq.Struct(
170+
rq.Card8('opcode'),
171+
rq.Opcode(5),
172+
rq.RequestLength(),
173+
)
174+
175+
176+
def disable(self):
177+
return DPMSDisable(display=self.display,
178+
opcode=self.display.get_extension_major(extname),
179+
major_version=1,
180+
minor_version=1)
181+
182+
183+
class DPMSForceLevel(rq.Request):
184+
_request = rq.Struct(
185+
rq.Card8('opcode'),
186+
rq.Opcode(6),
187+
rq.RequestLength(),
188+
rq.Resource('power_level', DPMSPowerLevel),
189+
)
190+
191+
192+
def force_level(self, power_level):
193+
return DPMSForceLevel(display=self.display,
194+
opcode=self.display.get_extension_major(extname),
195+
major_version=1,
196+
minor_version=1,
197+
power_level=power_level)
198+
199+
200+
class DPMSInfo(rq.ReplyRequest):
201+
_request = rq.Struct(
202+
rq.Card8('opcode'),
203+
rq.Opcode(7),
204+
rq.RequestLength(),
205+
)
206+
207+
_reply = rq.Struct(
208+
rq.ReplyCode(),
209+
rq.Pad(1),
210+
rq.Card16('sequence_number'),
211+
rq.ReplyLength(),
212+
rq.Resource('power_level', DPMSPowerLevel),
213+
rq.Bool('state'),
214+
rq.Pad(21),
215+
)
216+
217+
218+
def info(self):
219+
return DPMSInfo(display=self.display,
220+
opcode=self.display.get_extension_major(extname),
221+
major_version=1,
222+
minor_version=1)
223+
224+
225+
def init(disp, info):
226+
disp.extension_add_method('display', 'dpms_get_version', get_version)
227+
disp.extension_add_method('display', 'dpms_capable', capable)
228+
disp.extension_add_method('display', 'dpms_get_timeouts', get_timeouts)
229+
disp.extension_add_method('display', 'dpms_set_timeouts', set_timeouts)
230+
disp.extension_add_method('display', 'dpms_enable', enable)
231+
disp.extension_add_method('display', 'dpms_disable', disable)
232+
disp.extension_add_method('display', 'dpms_force_level', force_level)
233+
# TODO: Returns 'TypeError: first argument must be callable' on call
234+
# disp.extension_add_method('display', 'dpms_info', info)

0 commit comments

Comments
 (0)