Merge ~pieq/checkbox-support:remove-xrandr-contrib into checkbox-support:master
- Git
- lp:~pieq/checkbox-support
- remove-xrandr-contrib
- Merge into master
Proposed by
Pierre Equoy
Status: | Merged |
---|---|
Approved by: | Sylvain Pineau |
Approved revision: | 544e95491f3752cea8fd600d8c28e29427b23dca |
Merged at revision: | 682b5fa8c4ee4c885ecb5585c06d731cd308a472 |
Proposed branch: | ~pieq/checkbox-support:remove-xrandr-contrib |
Merge into: | checkbox-support:master |
Diff against target: |
1075 lines (+0/-1064) 1 file modified
dev/null (+0/-1064) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sylvain Pineau (community) | Approve | ||
Review via email: mp+424147@code.launchpad.net |
Commit message
Description of the change
Following the changes made for lp:1968943, this commit removes an unused package from checkbox_
Please check https:/
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/checkbox_support/contrib/__init__.py b/checkbox_support/contrib/__init__.py |
2 | deleted file mode 100644 |
3 | index e69de29..0000000 |
4 | --- a/checkbox_support/contrib/__init__.py |
5 | +++ /dev/null |
6 | diff --git a/checkbox_support/contrib/xrandr.py b/checkbox_support/contrib/xrandr.py |
7 | deleted file mode 100644 |
8 | index 91fd173..0000000 |
9 | --- a/checkbox_support/contrib/xrandr.py |
10 | +++ /dev/null |
11 | @@ -1,1064 +0,0 @@ |
12 | -# Python-XRandR provides a high level API for the XRandR extension of the |
13 | -# X.org server. XRandR allows to configure resolution, refresh rate, rotation |
14 | -# of the screen and multiple outputs of graphics cards. |
15 | -# |
16 | -# Copyright 2014 © Canonical Ltd. |
17 | -# Copyright 2007 © Sebastian Heinlein <sebastian.heinlein@web.de> |
18 | -# Copyright 2007 © Michael Vogt <mvo@ubuntu.com> |
19 | -# Copyright 2007 © Canonical Ltd. |
20 | -# |
21 | -# In many aspects it follows the design of the xrand tool of the X.org, which |
22 | -# comes with the following copyright: |
23 | -# |
24 | -# Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. |
25 | -# Copyright © 2002 Hewlett Packard Company, Inc. |
26 | -# Copyright © 2006 Intel Corporation |
27 | -# |
28 | -# And can be downloaded here: |
29 | -# |
30 | -# git://anongit.freedesktop.org/git/xorg/app/xrandr |
31 | -# |
32 | -# This library is free software; you can redistribute it and/or |
33 | -# modify it under the terms of the GNU Lesser General Public |
34 | -# License as published by the Free Software Foundation; either |
35 | -# version 2.1 of the License, or any later version. |
36 | -# |
37 | -# This library is distributed in the hope that it will be useful, |
38 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
39 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
40 | -# Lesser General Public License for more details. |
41 | -# |
42 | -# You should have received a copy of the GNU Lesser General Public |
43 | -# License along with this library; if not, write to the Free Software |
44 | -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
45 | -# MA 02110-1301 USA |
46 | - |
47 | -from ctypes import ( |
48 | - POINTER, |
49 | - Structure, |
50 | - byref, |
51 | - c_char_p, |
52 | - c_void_p, |
53 | - c_int, |
54 | - c_long, |
55 | - c_ulong, |
56 | - c_ushort, |
57 | - cdll, |
58 | -) |
59 | -import os |
60 | - |
61 | -RR_ROTATE_0 = 1 |
62 | -RR_ROTATE_90 = 2 |
63 | -RR_ROTATE_180 = 4 |
64 | -RR_ROTATE_270 = 8 |
65 | -RR_REFLECT_X = 16 |
66 | -RR_REFLECT_Y = 32 |
67 | - |
68 | -RR_CONNECTED = 0 |
69 | -RR_DISCONNECTED = 1 |
70 | -RR_UNKOWN_CONNECTION = 2 |
71 | - |
72 | -RR_BAD_OUTPUT = 0 |
73 | -RR_BAD_CRTC = 1 |
74 | -RR_BAD_MODE = 2 |
75 | - |
76 | -RR_SET_CONFIG_SUCCESS = 0 |
77 | -RR_SET_CONFIG_INVALID_CONFIG_TIME = 1 |
78 | -RR_SET_CONFIG_INVALID_TIME = 2 |
79 | -RR_SET_CONFIG_FAILED = 3 |
80 | - |
81 | -# Flags to keep track of changes |
82 | -CHANGES_NONE = 0 |
83 | -CHANGES_CRTC = 1 |
84 | -CHANGES_MODE = 2 |
85 | -CHANGES_RELATION = 4 |
86 | -CHANGES_POSITION = 8 |
87 | -CHANGES_ROTATION = 16 |
88 | -CHANGES_REFLECTION = 32 |
89 | -CHANGES_AUTOMATIC = 64 |
90 | -CHANGES_REFRESH = 128 |
91 | -CHANGES_PROPERTY = 256 |
92 | - |
93 | -# Relation information |
94 | -RELATION_ABOVE = 0 |
95 | -RELATION_BELOW = 1 |
96 | -RELATION_RIGHT_OF = 2 |
97 | -RELATION_LEFT_OF = 3 |
98 | -RELATION_SAME_AS = 4 |
99 | - |
100 | -# some fundamental datatypes |
101 | -RRCrtc = c_long |
102 | -RROutput = c_long |
103 | -RRMode = c_long |
104 | -Connection = c_ushort |
105 | -SubpixelOrder = c_ushort |
106 | -Time = c_ulong |
107 | -Rotation = c_ushort |
108 | -Status = c_int |
109 | - |
110 | -# load the libs |
111 | -xlib = cdll.LoadLibrary('libX11.so.6') |
112 | -rr = cdll.LoadLibrary('libXrandr.so.2') |
113 | - |
114 | - |
115 | -# query resources |
116 | -class _XRRModeInfo(Structure): |
117 | - _fields_ = [ |
118 | - ("id", RRMode), # XID is c_long |
119 | - ("width", c_int), |
120 | - ("height", c_int), |
121 | - ("dotClock", c_long), |
122 | - ("hSyncStart", c_int), |
123 | - ("hSyncEnd", c_int), |
124 | - ("hTotal", c_int), |
125 | - ("hSkew", c_int), |
126 | - ("vSyncStart", c_int), |
127 | - ("vSyncEnd", c_int), |
128 | - ("vTotal", c_int), |
129 | - ("name", c_char_p), |
130 | - ("nameLength", c_int), |
131 | - ("modeFlags", c_long), |
132 | - ] |
133 | - |
134 | - |
135 | -class _XRRScreenSize(Structure): |
136 | - _fields_ = [ |
137 | - ("width", c_int), |
138 | - ("height", c_int), |
139 | - ("mwidth", c_int), |
140 | - ("mheight", c_int) |
141 | - ] |
142 | - |
143 | - |
144 | -class _XRRCrtcInfo(Structure): |
145 | - _fields_ = [ |
146 | - ("timestamp", Time), |
147 | - ("x", c_int), |
148 | - ("y", c_int), |
149 | - ("width", c_int), |
150 | - ("height", c_int), |
151 | - ("mode", RRMode), |
152 | - ("rotation", c_int), |
153 | - ("noutput", c_int), |
154 | - ("outputs", POINTER(RROutput)), |
155 | - ("rotations", Rotation), |
156 | - ("npossible", c_int), |
157 | - ("possible", POINTER(RROutput)), |
158 | - ] |
159 | - |
160 | - |
161 | -class _XRRScreenResources(Structure): |
162 | - _fields_ = [ |
163 | - ("timestamp", Time), |
164 | - ("configTimestamp", Time), |
165 | - ("ncrtc", c_int), |
166 | - ("crtcs", POINTER(RRCrtc)), |
167 | - ("noutput", c_int), |
168 | - ("outputs", POINTER(RROutput)), |
169 | - ("nmode", c_int), |
170 | - ("modes", POINTER(_XRRModeInfo)), |
171 | - ] |
172 | - |
173 | - |
174 | -class RRError(Exception): |
175 | - """Base exception class of the module""" |
176 | - pass |
177 | - |
178 | - |
179 | -class UnsupportedRRError(RRError): |
180 | - """Raised if the required XRandR extension version is not available""" |
181 | - def __init__(self, required, current): |
182 | - self.required = required |
183 | - self.current = current |
184 | - |
185 | - |
186 | -# XRRGetOutputInfo |
187 | -class _XRROutputInfo(Structure): |
188 | - _fields_ = [ |
189 | - ("timestamp", Time), |
190 | - ("crtc", c_int), |
191 | - ("name", c_char_p), |
192 | - ("nameLen", c_int), |
193 | - ("mm_width", c_ulong), |
194 | - ("mm_height", c_ulong), |
195 | - ("connection", Connection), |
196 | - ("subpixel_order", SubpixelOrder), |
197 | - ("ncrtc", c_int), |
198 | - ("crtcs", POINTER(RRCrtc)), |
199 | - ("nclone", c_int), |
200 | - ("clones", POINTER(RROutput)), |
201 | - ("nmode", c_int), |
202 | - ("npreferred", c_int), |
203 | - ("modes", POINTER(RRMode)) |
204 | - ] |
205 | - |
206 | - |
207 | -class _XRRCrtcGamma(Structure): |
208 | - _fields_ = [ |
209 | - ('size', c_int), |
210 | - ('red', POINTER(c_ushort)), |
211 | - ('green', POINTER(c_ushort)), |
212 | - ('blue', POINTER(c_ushort)), |
213 | - ] |
214 | - |
215 | - |
216 | -def _array_conv(array, type, conv=lambda x: x): |
217 | - length = len(array) |
218 | - res = (type * length)() |
219 | - for i in range(length): |
220 | - res[i] = conv(array[i]) |
221 | - return res |
222 | - |
223 | - |
224 | -class Output(object): |
225 | - """The output is a reference to a supported output jacket of the graphics |
226 | - card. Outputs are attached to a hardware pipe to be used. Furthermore |
227 | - they can be a clone of another output or show a subset of the screen""" |
228 | - def __init__(self, info, id, screen): |
229 | - """Initializes an output instance""" |
230 | - self._info = info |
231 | - self.id = id |
232 | - self._screen = screen |
233 | - # Store changes later here |
234 | - self._mode = None |
235 | - self._crtc = None |
236 | - self._rotation = RR_ROTATE_0 |
237 | - self._relation = None |
238 | - self._relation_offset = 0 |
239 | - self._relative_to = None |
240 | - self._position = None |
241 | - self._reflection = None |
242 | - self._automatic = None |
243 | - self._rate = None |
244 | - self._changes = CHANGES_NONE |
245 | - self._x = 0 |
246 | - self._y = 0 |
247 | - |
248 | - self.name = self._info.contents.name |
249 | - |
250 | - def __del__(self): |
251 | - """Frees the internal reference to the output info if the output gets |
252 | - removed""" |
253 | - rr.XRRFreeOutputInfo(self._info) |
254 | - |
255 | - def get_physical_width(self): |
256 | - """Returns the display width reported by the connected output device""" |
257 | - return self._info.contents.mm_width |
258 | - |
259 | - def get_physical_height(self): |
260 | - """ |
261 | - Returns the display height reported by the connected output device |
262 | - """ |
263 | - return self._info.contents.mm_height |
264 | - |
265 | - def get_crtc(self): |
266 | - """Returns the xid of the hardware pipe to which the output is |
267 | - attached. If the output is disabled it will return 0""" |
268 | - return self._info.contents.crtc |
269 | - |
270 | - def get_crtcs(self): |
271 | - """Returns the xids of the hardware pipes to which the output could |
272 | - be attached""" |
273 | - crtcs = [] |
274 | - for i in range(self._info.contents.ncrtc): |
275 | - for crtc in self._screen.crtcs: |
276 | - if crtc.xid == self._info.contents.crtcs[i]: |
277 | - crtcs.append(crtc) |
278 | - return crtcs |
279 | - |
280 | - def get_available_rotations(self): |
281 | - """Returns a binary flag of the supported rotations of the output or |
282 | - 0 if the output is disabled""" |
283 | - rotations = RR_ROTATE_0 |
284 | - found = False |
285 | - if self.is_active(): |
286 | - # Get the rotations supported by all crtcs to make assigning |
287 | - # crtcs easier. Furthermore there don't seem to be so many |
288 | - # cards which show another behavior |
289 | - for crtc in self.get_crtcs(): |
290 | - # Set rotations to the value of the first found crtc and |
291 | - # then create a subset only for all other crtcs |
292 | - if not found: |
293 | - rotations = crtc.get_available_rotations() |
294 | - found = True |
295 | - else: |
296 | - rotations = rotations & crtc.get_available_rotations() |
297 | - return rotations |
298 | - |
299 | - def get_available_modes(self): |
300 | - """Returns the list of supported mode lines (resolution, refresh rate) |
301 | - that are supported by the connected device""" |
302 | - modes = [] |
303 | - for m in range(self._info.contents.nmode): |
304 | - output_modes = self._info.contents.modes |
305 | - for s in range(self._screen._resources.contents.nmode): |
306 | - screen_modes = self._screen._resources.contents.modes |
307 | - if screen_modes[s].id == output_modes[m]: |
308 | - modes.append(screen_modes[s]) |
309 | - return modes |
310 | - |
311 | - def get_preferred_mode(self): |
312 | - """Returns an index that refers to the list of available modes and |
313 | - points to the preferred mode of the connected device""" |
314 | - return self._info.contents.npreferred |
315 | - |
316 | - def is_active(self): |
317 | - """Returns True if the output is attached to a hardware pipe, is |
318 | - enabled""" |
319 | - return self._info.contents.crtc != 0 |
320 | - |
321 | - def is_connected(self): |
322 | - """Return True if a device is detected at the output""" |
323 | - if self._info.contents.connection in (RR_CONNECTED, |
324 | - RR_UNKOWN_CONNECTION): |
325 | - return True |
326 | - return False |
327 | - |
328 | - def disable(self): |
329 | - """Disables the output""" |
330 | - if not self.is_active(): |
331 | - return |
332 | - self._mode = None |
333 | - self._crtc._outputs.remove(self) |
334 | - self._crtc = None |
335 | - self._changes = self._changes | CHANGES_CRTC | CHANGES_MODE |
336 | - |
337 | - def set_to_mode(self, mode): |
338 | - modes = self.get_available_modes() |
339 | - if mode in range(len(modes)): |
340 | - self._mode = modes[mode].id |
341 | - return |
342 | - raise RRError("Mode is not available") |
343 | - |
344 | - def set_to_preferred_mode(self): |
345 | - modes = self.get_available_modes() |
346 | - mode = modes[self.get_preferred_mode()] |
347 | - if mode is not None: |
348 | - self._mode = mode.id |
349 | - return |
350 | - raise RRError("Preferred mode is not available") |
351 | - |
352 | - def get_clones(self): |
353 | - """Returns the xids of the outputs which can be clones of the output""" |
354 | - clones = [] |
355 | - for i in range(self._info.contents.nclone): |
356 | - id = self._info.contents.clones[i] |
357 | - o = self._screen.get_output_by_id(id) |
358 | - clones.append(o) |
359 | - return clones |
360 | - |
361 | - def set_relation(self, relative, relation, offset=0): |
362 | - """Sets the position of the output in relation to the given one""" |
363 | - rel = self._screen.get_output_by_name(relative) |
364 | - if rel and relation in (RELATION_LEFT_OF, RELATION_RIGHT_OF, |
365 | - RELATION_ABOVE, RELATION_BELOW, |
366 | - RELATION_SAME_AS): |
367 | - self._relation = relation |
368 | - self._relative_to = rel |
369 | - self._relation_offset = offset |
370 | - self._changes = self._changes | CHANGES_RELATION |
371 | - else: |
372 | - raise RRError("The given relative output or relation is not " |
373 | - "available") |
374 | - |
375 | - def has_changed(self, changes=None): |
376 | - """Checks if the output has changed: Either for a specific change or |
377 | - generally""" |
378 | - if changes: |
379 | - return self._changes & changes |
380 | - else: |
381 | - return self._changes != CHANGES_NONE |
382 | - |
383 | - |
384 | -class Crtc(object): |
385 | - """The crtc is a reference to a hardware pipe that is provided by the |
386 | - graphics device. Outputs can be attached to crtcs""" |
387 | - |
388 | - def __init__(self, info, xid, screen): |
389 | - """Initializes the hardware pipe object""" |
390 | - self._info = info |
391 | - self.xid = xid |
392 | - self._screen = screen |
393 | - self._outputs = [] |
394 | - |
395 | - def __del__(self): |
396 | - """Frees the reference to the rendering pipe if the instance gets |
397 | - removed""" |
398 | - rr.XRRFreeCrtcInfo(self._info) |
399 | - |
400 | - def get_xid(self): |
401 | - """Returns the internal id of the crtc from the X server""" |
402 | - return self.xid |
403 | - |
404 | - def get_available_rotations(self): |
405 | - """Returns a binary flag that contains the supported rotations of the |
406 | - hardware pipe""" |
407 | - return self._info.contents.rotations |
408 | - |
409 | - def set_config(self, x, y, mode, outputs, rotation=RR_ROTATE_0): |
410 | - """Configures the render pipe with the given mode and outputs. X and y |
411 | - set the position of the crtc output in the screen""" |
412 | - rr.XRRSetCrtcConfig(self._screen._display, |
413 | - self._screen._resources, |
414 | - self.xid, |
415 | - self._screen.get_timestamp(), |
416 | - c_int(x), c_int(y), |
417 | - mode, |
418 | - rotation, |
419 | - _array_conv(outputs, RROutput, lambda x: x.id), |
420 | - len(outputs)) |
421 | - |
422 | - def apply_changes(self): |
423 | - """Applies the stored changes""" |
424 | - if len(self._outputs) > 0: |
425 | - output = self._outputs[0] |
426 | - self.set_config(output._x, output._y, output._mode, |
427 | - self._outputs, output._rotation) |
428 | - else: |
429 | - self.disable() |
430 | - |
431 | - def disable(self): |
432 | - """Turns off all outputs on the crtc""" |
433 | - rr.XRRSetCrtcConfig(self._screen._display, |
434 | - self._screen._resources, |
435 | - self.xid, |
436 | - self._screen.get_timestamp(), |
437 | - 0, 0, |
438 | - None, |
439 | - RR_ROTATE_0, |
440 | - 0, 0) |
441 | - |
442 | - #FIXME: support gamma settings |
443 | - """ |
444 | - def get_gamma_size(self): |
445 | - return rr.XRRGetCrtcGammaSize(self._screen._display, self.id) |
446 | - def get_gamma(self): |
447 | - result = rr.XRRGetCrtcGamma(self._screen._display, self.id) |
448 | - return _from_gamma(result) |
449 | - def set_gamma(self, gamma): |
450 | - g = _to_gamma(gamma) |
451 | - rr.XRRSetCrtcGamma(self._screen._display, self.id, g) |
452 | - rr.XRRFreeGamma(g) |
453 | - gamma = property(get_gamma, set_gamma)""" |
454 | - |
455 | - def load_outputs(self): |
456 | - """Get the currently assigned outputs""" |
457 | - outputs = [] |
458 | - for i in range(self._info.contents.noutput): |
459 | - id = self._info.contents.outputs[i] |
460 | - o = self._screen.get_output_by_id(id) |
461 | - outputs.append(o) |
462 | - self._outputs = outputs |
463 | - |
464 | - def get_outputs(self): |
465 | - """Returns the list of attached outputs""" |
466 | - return self._outputs |
467 | - |
468 | - def add_output(self, output): |
469 | - """Adds the specified output to the crtc""" |
470 | - output._crtc = self |
471 | - self._outputs.append(output) |
472 | - |
473 | - def supports_output(self, output): |
474 | - """Check if the output can be used by the crtc. |
475 | - See check_crtc_for_output in xrandr.c""" |
476 | - if not self.xid in [c.xid for c in output.get_crtcs()]: |
477 | - return False |
478 | - if len(self._outputs): |
479 | - for other in self._outputs: |
480 | - if other == output: |
481 | - continue |
482 | - if other._x != output._x: |
483 | - return False |
484 | - if other._y != output._y: |
485 | - return False |
486 | - if other._mode != output._mode: |
487 | - return False |
488 | - if other._rotation != output._rotation: |
489 | - return False |
490 | - #FIXME: pick_crtc is still missing |
491 | - elif self._info.contents.noutput > 0: |
492 | - if self._info.contents.x != output._x: |
493 | - return False |
494 | - if self._info.contents.y != output._y: |
495 | - return False |
496 | - if self._info.contents.mode_info != output._mode: |
497 | - return False |
498 | - if self._info.rotation != output._rotation: |
499 | - return False |
500 | - return True |
501 | - |
502 | - def supports_rotation(self, rotation): |
503 | - """Check if the given rotation is supported by the crtc""" |
504 | - rotations = self._info.contents.rotations |
505 | - dir = rotation & (RR_ROTATE_0 | RR_ROTATE_90 | RR_ROTATE_180 | |
506 | - RR_ROTATE_270) |
507 | - reflect = rotation & (RR_REFLECT_X | RR_REFLECT_Y) |
508 | - if (((rotations & dir) != 0) and ((rotations & reflect) == reflect)): |
509 | - return True |
510 | - return False |
511 | - |
512 | - def has_changed(self): |
513 | - """Check if there are any new outputs assigned to the crtc or any |
514 | - outputs with a changed mode or position""" |
515 | - if len(self._outputs) != self._info.contents.noutput: |
516 | - return True |
517 | - for i in range(self._info.contents.noutput): |
518 | - id = self._info.contents.outputs[i] |
519 | - output = self._screen.get_output_by_id(id) |
520 | - if not output in self._outputs: |
521 | - return True |
522 | - if output.has_changed(): |
523 | - return True |
524 | - return False |
525 | - |
526 | - |
527 | -class Screen(object): |
528 | - def __init__(self, dpy, screen=-1): |
529 | - """Initializes the screen""" |
530 | - # Some sane default values |
531 | - self.outputs = {} |
532 | - self.crtcs = [] |
533 | - self._width = 0 |
534 | - self._height = 0 |
535 | - self._width_max = 0 |
536 | - self._height_max = 0 |
537 | - self._width_min = 0 |
538 | - self._height_min = 0 |
539 | - self._width_mm = 0 |
540 | - self._height_mm = 0 |
541 | - |
542 | - self._display = dpy |
543 | - if not -1 <= screen < xlib.XScreenCount(dpy): |
544 | - raise RRError("The chosen screen is not available", screen) |
545 | - elif screen == -1: |
546 | - self._screen = xlib.XDefaultScreen(dpy) |
547 | - else: |
548 | - self._screen = screen |
549 | - self._root = xlib.XDefaultRootWindow(self._display, self._screen) |
550 | - self._id = rr.XRRRootToScreen(self._display, self._root) |
551 | - |
552 | - self._load_resources() |
553 | - self._load_config() |
554 | - (self._width, self._height, |
555 | - self._width_mm, self._height_mm) = self.get_size() |
556 | - if XRANDR_VERSION >= (1, 2): |
557 | - self._load_screen_size_range() |
558 | - self._load_crtcs() |
559 | - self._load_outputs() |
560 | - |
561 | - # Store XRandR 1.0 changes here |
562 | - self._rate = self.get_current_rate() |
563 | - self._rotation = self.get_current_rotation() |
564 | - self._size_index = self.get_current_size_index() |
565 | - |
566 | - def __del__(self): |
567 | - """Free the reference to the interal screen config if the screen |
568 | - gets removed""" |
569 | - rr.XRRFreeScreenConfigInfo(self._config) |
570 | - |
571 | - def _load_config(self): |
572 | - """Loads the screen configuration. Only needed privately by the |
573 | - the bindings""" |
574 | - class XRRScreenConfiguration(Structure): |
575 | - " private to Xrandr " |
576 | - pass |
577 | - gsi = rr.XRRGetScreenInfo |
578 | - gsi.restype = POINTER(XRRScreenConfiguration) |
579 | - self._config = gsi(self._display, self._root) |
580 | - |
581 | - def _load_screen_size_range(self): |
582 | - """Detects the dimensionios of the screen""" |
583 | - minWidth = c_int() |
584 | - minHeight = c_int() |
585 | - maxWidth = c_int() |
586 | - maxHeight = c_int() |
587 | - res = rr.XRRGetScreenSizeRange(self._display, self._root, |
588 | - byref(minWidth), byref(minHeight), |
589 | - byref(maxWidth), byref(maxHeight)) |
590 | - if res: |
591 | - self._width_max = maxWidth.value |
592 | - self._width_min = minWidth.value |
593 | - self._height_max = maxHeight.value |
594 | - self._height_min = minHeight.value |
595 | - |
596 | - def _load_resources(self): |
597 | - """Loads the screen resources. Only needed privately for the |
598 | - bindings""" |
599 | - gsr = rr.XRRGetScreenResources |
600 | - gsr.restype = POINTER(_XRRScreenResources) |
601 | - self._resources = gsr(self._display, self._root) |
602 | - |
603 | - def _load_crtcs(self): |
604 | - """Loads the available XRandR 1.2 crtcs (hardware pipes) of |
605 | - the screen""" |
606 | - gci = rr.XRRGetCrtcInfo |
607 | - gci.restype = POINTER(_XRRCrtcInfo) |
608 | - c = self._resources.contents.crtcs |
609 | - for i in range(self._resources.contents.ncrtc): |
610 | - xrrcrtcinfo = gci(self._display, self._resources, c[i]) |
611 | - self.crtcs.append(Crtc(xrrcrtcinfo, c[i], self)) |
612 | - |
613 | - def _load_outputs(self): |
614 | - """Loads the available XRandR 1.2 outputs of the screen""" |
615 | - goi = rr.XRRGetOutputInfo |
616 | - goi.restype = POINTER(_XRROutputInfo) |
617 | - o = self._resources.contents.outputs |
618 | - for i in range(self._resources.contents.noutput): |
619 | - xrroutputinfo = goi(self._display, self._resources, o[i]) |
620 | - output = Output(xrroutputinfo, o[i], self) |
621 | - self.outputs[xrroutputinfo.contents.name] = output |
622 | - # Store the mode of the crtc in the output instance |
623 | - crtc = self.get_crtc_by_xid(output.get_crtc()) |
624 | - if crtc: |
625 | - output._mode = crtc._info.contents.mode |
626 | - crtc.add_output(output) |
627 | - |
628 | - def get_size(self): |
629 | - """Returns the current pixel and physical size of the screen""" |
630 | - width = xlib.XDisplayWidth(self._display, self._screen) |
631 | - width_mm = xlib.XDisplayWidthMM(self._display, self._screen) |
632 | - height = xlib.XDisplayHeight(self._display, self._screen) |
633 | - height_mm = xlib.XDisplayHeightMM(self._display, self._screen) |
634 | - return width, height, width_mm, height_mm |
635 | - |
636 | - def get_timestamp(self): |
637 | - """Creates a X timestamp that must be used when applying changes, since |
638 | - they can be delayed""" |
639 | - config_timestamp = Time() |
640 | - rr.XRRTimes.restpye = c_ulong |
641 | - return rr.XRRTimes(self._display, self._id, byref(config_timestamp)) |
642 | - |
643 | - def get_crtc_by_xid(self, xid): |
644 | - """Returns the crtc with the given xid or None""" |
645 | - for crtc in self.crtcs: |
646 | - if crtc.xid == xid: |
647 | - return crtc |
648 | - return None |
649 | - |
650 | - def get_current_rate(self): |
651 | - """Returns the currently used refresh rate""" |
652 | - _check_required_version((1, 0)) |
653 | - xccr = rr.XRRConfigCurrentRate |
654 | - xccr.restype = c_int |
655 | - return xccr(self._config) |
656 | - |
657 | - def get_available_rates_for_size_index(self, size_index): |
658 | - """Returns the refresh rates that are supported by the screen for |
659 | - the given resolution. See get_available_sizes for the resolution to |
660 | - which size_index points""" |
661 | - _check_required_version((1, 0)) |
662 | - rates = [] |
663 | - nrates = c_int() |
664 | - rr.XRRConfigRates.restype = POINTER(c_ushort) |
665 | - _rates = rr.XRRConfigRates(self._config, size_index, byref(nrates)) |
666 | - for r in range(nrates.value): |
667 | - rates.append(_rates[r]) |
668 | - return rates |
669 | - |
670 | - def get_current_rotation(self): |
671 | - """Returns the currently used rotation. Can be RR_ROTATE_0, |
672 | - RR_ROTATE_90, RR_ROTATE_180 or RR_ROTATE_270""" |
673 | - _check_required_version((1, 0)) |
674 | - current = c_ushort() |
675 | - rr.XRRConfigRotations(self._config, byref(current)) |
676 | - return current.value |
677 | - |
678 | - def get_available_rotations(self): |
679 | - """Returns a binary flag that holds the available resolutions""" |
680 | - _check_required_version((1, 0)) |
681 | - current = c_ushort() |
682 | - rotations = rr.XRRConfigRotations(self._config, byref(current)) |
683 | - return rotations |
684 | - |
685 | - def get_current_size_index(self): |
686 | - """Returns the position of the currently used resolution size in the |
687 | - list of available resolutions. See get_available_sizes""" |
688 | - _check_required_version((1, 0)) |
689 | - rotation = c_ushort() |
690 | - size = rr.XRRConfigCurrentConfiguration(self._config, |
691 | - byref(rotation)) |
692 | - return size |
693 | - |
694 | - def get_available_sizes(self): |
695 | - """Returns the available resolution sizes of the screen. The size |
696 | - index points to the corresponding resolution of this list""" |
697 | - _check_required_version((1, 0)) |
698 | - sizes = [] |
699 | - nsizes = c_int() |
700 | - xcs = rr.XRRConfigSizes |
701 | - xcs.restype = POINTER(_XRRScreenSize) |
702 | - _sizes = xcs(self._config, byref(nsizes)) |
703 | - for r in range(nsizes.value): |
704 | - sizes.append(_sizes[r]) |
705 | - return sizes |
706 | - |
707 | - def set_config(self, size_index, rate, rotation): |
708 | - """Configures the screen with the given resolution at the given size |
709 | - index, rotation and refresh rate. To get in effect call |
710 | - Screen.apply_config()""" |
711 | - _check_required_version((1, 0)) |
712 | - self.set_size_index(size_index) |
713 | - self.set_refresh_rate(rate) |
714 | - self.set_rotation(rotation) |
715 | - |
716 | - def set_size_index(self, index): |
717 | - """Sets the reoslution of the screen. To get in effect call |
718 | - Screen.apply_config()""" |
719 | - if index in range(len(self.get_available_sizes())): |
720 | - self._size_index = index |
721 | - else: |
722 | - raise RRError("There isn't any size associated " |
723 | - "to the index {}".format(index)) |
724 | - |
725 | - def set_rotation(self, rotation): |
726 | - """Sets the rotation of the screen. To get in effect call |
727 | - Screen.apply_config()""" |
728 | - if self.get_available_rotations() & rotation: |
729 | - self._rotation = rotation |
730 | - else: |
731 | - raise RRError("The chosen rotation is not supported") |
732 | - |
733 | - def set_refresh_rate(self, rate): |
734 | - """Sets the refresh rate of the screen. To get in effect call |
735 | - Screen.apply_config()""" |
736 | - if rate in self.get_available_rates_for_size_index(self._size_index): |
737 | - self._rate = rate |
738 | - else: |
739 | - raise RRError( |
740 | - "The chosen refresh rate {0} is not supported".format(rate)) |
741 | - |
742 | - def get_mode_by_xid(self, xid): |
743 | - """Returns the mode of the given xid""" |
744 | - screen_modes = self._resources.contents.modes |
745 | - for s in range(self._resources.contents.nmode): |
746 | - if screen_modes[s].id == xid: |
747 | - return screen_modes[s] |
748 | - return None |
749 | - |
750 | - def get_output_by_name(self, name): |
751 | - """Returns the output of the screen with the given name or None""" |
752 | - if name in self.outputs: |
753 | - return self.outputs[name] |
754 | - else: |
755 | - return None |
756 | - |
757 | - def get_output_by_id(self, id): |
758 | - """Returns the output of the screen with the given xid or None""" |
759 | - for o in list(self.outputs.values()): |
760 | - if o.id == id: |
761 | - return o |
762 | - return None |
763 | - |
764 | - def print_info(self, verbose=False): |
765 | - """Prints some information about the detected screen and its outputs""" |
766 | - _check_required_version((1, 0)) |
767 | - print(( |
768 | - "Screen {0}: minimum {1} x {2}, current {3} x {4}," |
769 | - " maximum {5} x {6}" |
770 | - ).format(self._screen, self._width_min, self._height_min, self._width, |
771 | - self._height, self._width_max, self._height_max)) |
772 | - print(" {0}mm x {0}mm".format(self._width_mm, |
773 | - self._height_mm)) |
774 | - print("Crtcs: {0}".format(len(self.crtcs))) |
775 | - if verbose: |
776 | - print("Modes ({0}):".format(self._resources.contents.nmode)) |
777 | - modes = self._resources.contents.modes |
778 | - for i in range(self._resources.contents.nmode): |
779 | - print(" {0} - {1}x{2}".format( |
780 | - modes[i].name, modes[i].width, modes[i].height)) |
781 | - i = 0 |
782 | - print("Sizes @ Refresh Rates:") |
783 | - for s in self.get_available_sizes(): |
784 | - print(" [{0}] {1} x {2} @ {3}".format( |
785 | - i, s.width, s.height, |
786 | - self.get_available_rates_for_size_index(i))) |
787 | - i += 1 |
788 | - print("Rotations:") |
789 | - rots = self.get_available_rotations() |
790 | - if rots & RR_ROTATE_0: |
791 | - print("normal") |
792 | - if rots & RR_ROTATE_90: |
793 | - print("right") |
794 | - if rots & RR_ROTATE_180: |
795 | - print("inverted") |
796 | - if rots & RR_ROTATE_270: |
797 | - print("left") |
798 | - print("") |
799 | - print("Outputs:") |
800 | - for o in list(self.outputs.keys()): |
801 | - output = self.outputs[o] |
802 | - print(" %s" % o) |
803 | - if output.is_connected(): |
804 | - print("(%smm x %smm)" % (output.get_physical_width(), |
805 | - output.get_physical_height())) |
806 | - modes = output.get_available_modes() |
807 | - print(" Modes:") |
808 | - for m in range(len(modes)): |
809 | - mode = modes[m] |
810 | - refresh = mode.dotClock / (mode.hTotal * mode.vTotal) |
811 | - print(" [%s] %s x %s @ %s" % (m, |
812 | - mode.width, |
813 | - mode.height, |
814 | - refresh)) |
815 | - if mode.id == output._mode: |
816 | - print("*") |
817 | - if m == output.get_preferred_mode(): |
818 | - print("(preferred)") |
819 | - print("") |
820 | - print(" Rotations:") |
821 | - rots = output.get_available_rotations() |
822 | - if rots & RR_ROTATE_0: |
823 | - print("normal") |
824 | - if rots & RR_ROTATE_90: |
825 | - print("right") |
826 | - if rots & RR_ROTATE_180: |
827 | - print("inverted") |
828 | - if rots & RR_ROTATE_270: |
829 | - print("left") |
830 | - print("") |
831 | - else: |
832 | - print("(not connected)") |
833 | - if verbose: |
834 | - print(" Core properties:") |
835 | - for (f, t) in output._info.contents._fields_: |
836 | - print(" %s: %s" % ( |
837 | - f, getattr(output._info.contents, f))) |
838 | - |
839 | - def get_outputs(self): |
840 | - """Returns the outputs of the screen""" |
841 | - _check_required_version((1, 2)) |
842 | - return list(self.outputs.values()) |
843 | - |
844 | - def get_output_names(self): |
845 | - _check_required_version((1, 2)) |
846 | - return list(self.outputs.keys()) |
847 | - |
848 | - def set_size(self, width, height, width_mm, height_mm): |
849 | - """Apply the given pixel and physical size to the screen""" |
850 | - _check_required_version((1, 2)) |
851 | - # Check if we really need to apply the changes |
852 | - if (width, height, width_mm, height_mm) == self.get_size(): |
853 | - return |
854 | - rr.XRRSetScreenSize(self._display, self._root, |
855 | - c_int(width), c_int(height), |
856 | - c_int(width_mm), c_int(height_mm)) |
857 | - |
858 | - def apply_output_config(self): |
859 | - """Used for instantly applying RandR 1.2 changes""" |
860 | - _check_required_version((1, 2)) |
861 | - self._arrange_outputs() |
862 | - self._calculate_size() |
863 | - self.set_size(self._width, self._height, |
864 | - self._width_mm, self._height_mm) |
865 | - |
866 | - # Assign all active outputs to crtcs |
867 | - for output in list(self.outputs.values()): |
868 | - if not output._mode or output._crtc: |
869 | - continue |
870 | - for crtc in output.get_crtcs(): |
871 | - if crtc and crtc.supports_output(output): |
872 | - crtc.add_output(output) |
873 | - output._changes = output._changes | CHANGES_CRTC |
874 | - break |
875 | - if not output._crtc: |
876 | - #FIXME: Take a look at the pick_crtc code in xrandr.c |
877 | - raise RRError("There is no matching crtc for the output") |
878 | - |
879 | - # Apply stored changes of crtcs |
880 | - for crtc in self.crtcs: |
881 | - if crtc.has_changed(): |
882 | - crtc.apply_changes() |
883 | - |
884 | - def apply_config(self): |
885 | - """Used for instantly applying RandR 1.0 changes""" |
886 | - _check_required_version((1, 0)) |
887 | - status = rr.XRRSetScreenConfigAndRate(self._display, |
888 | - self._config, |
889 | - self._root, |
890 | - self._size_index, |
891 | - self._rotation, |
892 | - self._rate, |
893 | - self.get_timestamp()) |
894 | - return status |
895 | - |
896 | - def _arrange_outputs(self): |
897 | - """Arrange all output positions according to their relative position""" |
898 | - for output in self.get_outputs(): |
899 | - # Skip not changed and not used outputs |
900 | - if not output.has_changed(CHANGES_RELATION) or \ |
901 | - output._mode is None: |
902 | - continue |
903 | - relative = output._relative_to |
904 | - mode = self.get_mode_by_xid(output._mode) |
905 | - mode_relative = self.get_mode_by_xid(relative._mode) |
906 | - if not relative or not relative._mode: |
907 | - output._x = 0 |
908 | - output._y = 0 |
909 | - output._changes = output._changes | CHANGES_POSITION |
910 | - if output._relation == RELATION_LEFT_OF: |
911 | - output._y = relative._y + output._relation_offset |
912 | - output._x = relative._x - get_mode_width( |
913 | - mode, output._rotation) |
914 | - elif output._relation == RELATION_RIGHT_OF: |
915 | - output._y = relative._y + output._relation_offset |
916 | - output._x = relative._x + get_mode_width(mode_relative, |
917 | - output._rotation) |
918 | - elif output._relation == RELATION_ABOVE: |
919 | - output._y = relative._y - get_mode_height(mode, |
920 | - output._rotation) |
921 | - output._x = relative._x + output._relation_offset |
922 | - elif output._relation == RELATION_BELOW: |
923 | - output._y = relative._y + get_mode_height(mode_relative, |
924 | - output._rotation) |
925 | - output._x = relative._x + output._relation_offset |
926 | - elif output._relation == RELATION_SAME_AS: |
927 | - output._y = relative._y + output._relation_offset |
928 | - output._x = relative._x + output._relation_offset |
929 | - output._changes = output._changes | CHANGES_POSITION |
930 | - # Normalize the postions so to the upper left cornor of all outputs |
931 | - # is at 0,0 |
932 | - min_x = 32768 |
933 | - min_y = 32768 |
934 | - for output in self.get_outputs(): |
935 | - if output._mode is None: |
936 | - continue |
937 | - if output._x < min_x: |
938 | - min_x = output._x |
939 | - if output._y < min_y: |
940 | - min_y = output._y |
941 | - for output in self.get_outputs(): |
942 | - if output._mode is None: |
943 | - continue |
944 | - output._x -= min_x |
945 | - output._y -= min_y |
946 | - output._changes = output._changes | CHANGES_POSITION |
947 | - |
948 | - def _calculate_size(self): |
949 | - """Recalculate the pixel and physical size of the screen so that |
950 | - it covers all outputs""" |
951 | - width = self._width |
952 | - height = self._height |
953 | - for output in self.get_outputs(): |
954 | - if not output._mode: |
955 | - continue |
956 | - mode = self.get_mode_by_xid(output._mode) |
957 | - x = output._x |
958 | - y = output._y |
959 | - w = get_mode_width(mode, output._rotation) |
960 | - h = get_mode_height(mode, output._rotation) |
961 | - if x + w > width: |
962 | - width = x + w |
963 | - if y + h > height: |
964 | - height = y + h |
965 | - if width > self._width_max or height > self._height_max: |
966 | - raise RRError("The required size is not supported", |
967 | - (width, height), (self._width_max, self._width_min)) |
968 | - else: |
969 | - if height < self._height_min: |
970 | - self._fb_height = self._height_min |
971 | - else: |
972 | - self._height = height |
973 | - if width < self._width_min: |
974 | - self._width = self._width_min |
975 | - else: |
976 | - self._width = width |
977 | - #FIXME: Physical size is missing |
978 | - |
979 | - |
980 | -def get_current_display(): |
981 | - """Returns the currently used display""" |
982 | - display_url = os.getenv("DISPLAY") |
983 | - if display_url is None: |
984 | - raise SystemExit("DISPLAY environment variable is not defined!") |
985 | - open_display = xlib.XOpenDisplay |
986 | - # Set .argtypes and .restype, to ensure proper |
987 | - # type check and conversion |
988 | - open_display.restype = c_void_p |
989 | - open_display.argtypes = [c_char_p] |
990 | - # XOpenDisplay accepts a char*, but |
991 | - # display_url is a unicode string therefore |
992 | - # we convert it to a bytes string |
993 | - dpy = open_display(display_url.encode('utf-8')) |
994 | - return dpy |
995 | - |
996 | - |
997 | -def get_current_screen(): |
998 | - """Returns the currently used screen""" |
999 | - screen = Screen(get_current_display()) |
1000 | - return screen |
1001 | - |
1002 | - |
1003 | -def get_screen_of_display(display, count): |
1004 | - """Returns the screen of the given display""" |
1005 | - dpy = xlib.XOpenDisplay(display) |
1006 | - return Screen(dpy, count) |
1007 | - |
1008 | - |
1009 | -def get_version(): |
1010 | - """Returns a tuple containing the major and minor version of the xrandr |
1011 | - extension or None if the extension is not available""" |
1012 | - major = c_int() |
1013 | - minor = c_int() |
1014 | - res = rr.XRRQueryVersion(get_current_display(), |
1015 | - byref(major), byref(minor)) |
1016 | - if res: |
1017 | - return (major.value, minor.value) |
1018 | - return None |
1019 | - |
1020 | - |
1021 | -def has_extension(): |
1022 | - """Returns True if the xrandr extension is available""" |
1023 | - if XRANDR_VERSION: |
1024 | - return True |
1025 | - return False |
1026 | - |
1027 | - |
1028 | -def _to_gamma(gamma): |
1029 | - g = rr.XRRAllocGamma(len(gamma[0])) |
1030 | - for i in range(gamma[0]): |
1031 | - g.red[i] = gamma[0][i] |
1032 | - g.green[i] = gamma[1][i] |
1033 | - g.blue[i] = gamma[2][i] |
1034 | - return g |
1035 | - |
1036 | - |
1037 | -def _from_gamma(g): |
1038 | - gamma = ([], [], []) |
1039 | - for i in range(g.size): |
1040 | - gamma[0].append(g.red[i]) |
1041 | - gamma[1].append(g.green[i]) |
1042 | - gamma[2].append(g.blue[i]) |
1043 | - rr.XRRFreeGamma(g) |
1044 | - |
1045 | - |
1046 | -def _check_required_version(version): |
1047 | - """Raises an exception if the given or a later version of xrandr is not |
1048 | - available""" |
1049 | - if XRANDR_VERSION is None or XRANDR_VERSION < version: |
1050 | - raise UnsupportedRRError(version, XRANDR_VERSION) |
1051 | - |
1052 | - |
1053 | -def get_mode_height(mode, rotation): |
1054 | - """Return the height of the given mode taking the rotation into account""" |
1055 | - if rotation & (RR_ROTATE_0 | RR_ROTATE_180): |
1056 | - return mode.height |
1057 | - elif rotation & (RR_ROTATE_90 | RR_ROTATE_270): |
1058 | - return mode.width |
1059 | - else: |
1060 | - return 0 |
1061 | - |
1062 | - |
1063 | -def get_mode_width(mode, rotation): |
1064 | - """Return the width of the given mode taking the rotation into account""" |
1065 | - if rotation & (RR_ROTATE_0 | RR_ROTATE_180): |
1066 | - return mode.width |
1067 | - elif rotation & (RR_ROTATE_90 | RR_ROTATE_270): |
1068 | - return mode.height |
1069 | - else: |
1070 | - return 0 |
1071 | - |
1072 | - |
1073 | -XRANDR_VERSION = get_version() |
1074 | - |
1075 | -# vim:ts=4:sw=4:et |
+1