xrandrl 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #!/usr/bin/env python3
  2. # PYTHON_ARGCOMPLETE_OK
  3. """
  4. https://cgit.freedesktop.org/xorg/app/xrandr/tree/xrandr.c
  5. """
  6. import ctypes
  7. import ctypes.util
  8. X_Time = ctypes.c_ulong
  9. """
  10. #ifndef _XTYPEDEF_XID
  11. # define _XTYPEDEF_XID
  12. # ifndef _XSERVER64
  13. typedef unsigned long XID;
  14. # else
  15. typedef CARD32 XID;
  16. # endif
  17. #endif
  18. """
  19. X_XID = ctypes.c_ulong
  20. """
  21. typedef XID RROutput;
  22. """
  23. X_RROutput = X_XID
  24. """
  25. typedef XID RRCrtc;
  26. """
  27. X_RRCrtc = X_XID
  28. """ /usr/include/X11/extensions/Xrandr.h
  29. typedef XID RRMode;
  30. """
  31. X_RRMode = X_XID
  32. """ /usr/include/X11/extensions/randr.h
  33. #define RR_Connected 0
  34. """
  35. X_RR_Connected = 0
  36. """ /usr/include/X11/extensions/randr.h
  37. typedef unsigned short Connection;
  38. """
  39. X_Connection = ctypes.c_ushort
  40. """ /usr/include/X11/extensions/randr.h
  41. typedef unsigned short SubpixelOrder;
  42. """
  43. X_SubpixelOrder = ctypes.c_ushort
  44. class X_XRRScreenResources(ctypes.Structure):
  45. """ /usr/include/X11/extensions/Xrandr.h
  46. typedef struct _XRRScreenResources {
  47. Time timestamp;
  48. Time configTimestamp;
  49. int ncrtc;
  50. RRCrtc *crtcs;
  51. int noutput;
  52. RROutput *outputs;
  53. int nmode;
  54. XRRModeInfo *modes;
  55. } XRRScreenResources;
  56. """
  57. _fields_ = [
  58. ('timestamp', X_Time),
  59. ('configTimestamp', X_Time),
  60. ('ncrtc', ctypes.c_int),
  61. ('crtcs', ctypes.POINTER(X_RRCrtc)),
  62. ('noutput', ctypes.c_int),
  63. ('outputs', ctypes.POINTER(X_RROutput)),
  64. ('nmode', ctypes.c_int),
  65. ('modes', ctypes.c_void_p), # ctypes.POINTER(XRRModeInfo)
  66. ]
  67. class X_XRROutputInfo(ctypes.Structure):
  68. """
  69. typedef struct _XRROutputInfo {
  70. Time timestamp;
  71. RRCrtc crtc;
  72. char *name;
  73. int nameLen;
  74. unsigned long mm_width;
  75. unsigned long mm_height;
  76. Connection connection;
  77. SubpixelOrder subpixel_order;
  78. int ncrtc;
  79. RRCrtc *crtcs;
  80. int nclone;
  81. RROutput *clones;
  82. int nmode;
  83. int npreferred;
  84. RRMode *modes;
  85. } XRROutputInfo;
  86. """
  87. _fields_ = [
  88. ('timestamp', X_Time),
  89. ('crtc', X_RRCrtc),
  90. ('name', ctypes.c_char_p),
  91. ('nameLen', ctypes.c_int),
  92. ('mm_width', ctypes.c_ulong),
  93. ('mm_height', ctypes.c_ulong),
  94. ('connection', X_Connection),
  95. ('subpixel_order', X_SubpixelOrder),
  96. ('ncrtc', ctypes.c_int),
  97. ('crtcs', ctypes.POINTER(X_RRCrtc)),
  98. ('nclone', ctypes.c_int),
  99. ('clones', ctypes.POINTER(X_RROutput)),
  100. ('nmode', ctypes.c_int),
  101. ('npreferred', ctypes.c_int),
  102. ('modes', ctypes.POINTER(X_RRMode)),
  103. ]
  104. X11 = ctypes.cdll.LoadLibrary("libX11.so")
  105. Xrandr = ctypes.cdll.LoadLibrary("libXrandr.so")
  106. Xrandr.XRRGetScreenResourcesCurrent.restype = \
  107. ctypes.POINTER(X_XRRScreenResources)
  108. libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
  109. """
  110. XRROutputInfo *
  111. XRRGetOutputInfo (Display *dpy, XRRScreenResources *resources, RROutput output);
  112. """
  113. Xrandr.XRRGetOutputInfo.restype = ctypes.POINTER(X_XRROutputInfo)
  114. class RandrOutputInfo:
  115. def __init__(self,
  116. xdisplay,
  117. screen_resrcs: ctypes.POINTER(X_XRRScreenResources),
  118. output: X_RROutput):
  119. self._p = Xrandr.XRRGetOutputInfo(xdisplay, screen_resrcs, output)
  120. def __del__(self):
  121. libc.free(self._p)
  122. @property
  123. def enabled(self):
  124. return self._p.contents.crtc != 0
  125. @property
  126. def connected(self):
  127. return self._p.contents.connection == X_RR_Connected
  128. @property
  129. def name(self):
  130. return self._p.contents.name.decode()
  131. def get_xrandr_output_infos(xdisplay):
  132. screen_resrcs = Xrandr.XRRGetScreenResourcesCurrent(
  133. xdisplay,
  134. X11.XDefaultRootWindow(xdisplay),
  135. )
  136. assert isinstance(screen_resrcs.contents, X_XRRScreenResources)
  137. return [RandrOutputInfo(xdisplay, screen_resrcs, screen_resrcs.contents.outputs[o])
  138. for o in range(screen_resrcs.contents.noutput)]
  139. def process(connected, disabled, enabled):
  140. xdisplay = X11.XOpenDisplay(None)
  141. for output_info in get_xrandr_output_infos(xdisplay):
  142. if ((not connected or output_info.connected)
  143. and (not disabled or not output_info.enabled)
  144. and (not enabled or output_info.enabled)):
  145. print(output_info.name)
  146. X11.XCloseDisplay(xdisplay)
  147. def _init_argparser():
  148. import argparse
  149. argparser = argparse.ArgumentParser(
  150. description='Show names of outputs available to the X server.',
  151. )
  152. argparser.add_argument(
  153. '-c', '--connected',
  154. action='store_true',
  155. help='connected only',
  156. )
  157. argparser.add_argument(
  158. '-d', '--disabled',
  159. action='store_true',
  160. help='disabled only (does not imply --connected)',
  161. )
  162. argparser.add_argument(
  163. '-e', '--enabled',
  164. action='store_true',
  165. help='enabled only (does not imply --connected)',
  166. )
  167. return argparser
  168. def main(argv):
  169. argparser = _init_argparser()
  170. try:
  171. import argcomplete
  172. except ImportError:
  173. pass
  174. args = argparser.parse_args(argv)
  175. process(**vars(args))
  176. return 0
  177. if __name__ == "__main__":
  178. import sys
  179. sys.exit(main(sys.argv[1:]))