Merge ~pieq/checkbox-support:remove-xrandr-contrib into checkbox-support: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)
Reviewer Review Type Date Requested Status
Sylvain Pineau (community) Approve
Review via email: mp+424147@code.launchpad.net

Description of the change

Following the changes made for lp:1968943, this commit removes an unused package from checkbox_support.contrib.

Please check https://code.launchpad.net/~pieq/plainbox-provider-checkbox/+git/plainbox-provider-checkbox/+merge/424146 for additional information.

To post a comment you must log in.
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/checkbox_support/contrib/__init__.py b/checkbox_support/contrib/__init__.py
2deleted file mode 100644
3index e69de29..0000000
4--- a/checkbox_support/contrib/__init__.py
5+++ /dev/null
6diff --git a/checkbox_support/contrib/xrandr.py b/checkbox_support/contrib/xrandr.py
7deleted file mode 100644
8index 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

Subscribers

People subscribed via source and target branches