|
@@ -0,0 +1,164 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+# PYTHON_ARGCOMPLETE_OK
|
|
|
+
|
|
|
+"""
|
|
|
+sudo apt-get install libx11-dev libxrandr-dev
|
|
|
+https://cgit.freedesktop.org/xorg/app/xrandr/tree/xrandr.c
|
|
|
+"""
|
|
|
+
|
|
|
+import ctypes
|
|
|
+import sys
|
|
|
+
|
|
|
+Time = ctypes.c_ulong
|
|
|
+"""
|
|
|
+#ifndef _XTYPEDEF_XID
|
|
|
+# define _XTYPEDEF_XID
|
|
|
+# ifndef _XSERVER64
|
|
|
+typedef unsigned long XID;
|
|
|
+# else
|
|
|
+typedef CARD32 XID;
|
|
|
+# endif
|
|
|
+#endif
|
|
|
+"""
|
|
|
+XID = ctypes.c_ulong
|
|
|
+"""
|
|
|
+typedef XID RROutput;
|
|
|
+"""
|
|
|
+RROutput = XID
|
|
|
+"""
|
|
|
+typedef XID RRCrtc;
|
|
|
+"""
|
|
|
+RRCrtc = XID
|
|
|
+""" /usr/include/X11/extensions/Xrandr.h
|
|
|
+typedef XID RRMode;
|
|
|
+"""
|
|
|
+RRMode = XID
|
|
|
+""" /usr/include/X11/extensions/randr.h
|
|
|
+#define RR_Connected 0
|
|
|
+"""
|
|
|
+RR_Connected = 0
|
|
|
+""" /usr/include/X11/extensions/randr.h
|
|
|
+typedef unsigned short Connection;
|
|
|
+"""
|
|
|
+Connection = ctypes.c_ushort
|
|
|
+""" /usr/include/X11/extensions/randr.h
|
|
|
+typedef unsigned short SubpixelOrder;
|
|
|
+"""
|
|
|
+SubpixelOrder = ctypes.c_ushort
|
|
|
+
|
|
|
+""" /usr/include/X11/extensions/Xrandr.h
|
|
|
+typedef struct _XRRScreenResources {
|
|
|
+ Time timestamp;
|
|
|
+ Time configTimestamp;
|
|
|
+ int ncrtc;
|
|
|
+ RRCrtc *crtcs;
|
|
|
+ int noutput;
|
|
|
+ RROutput *outputs;
|
|
|
+ int nmode;
|
|
|
+ XRRModeInfo *modes;
|
|
|
+} XRRScreenResources;
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
+class XRRScreenResources(ctypes.Structure):
|
|
|
+ _fields_ = [
|
|
|
+ ('timestamp', Time),
|
|
|
+ ('configTimestamp', Time),
|
|
|
+ ('ncrtc', ctypes.c_int),
|
|
|
+ ('crtcs', ctypes.POINTER(RRCrtc)),
|
|
|
+ ('noutput', ctypes.c_int),
|
|
|
+ ('outputs', ctypes.POINTER(RROutput)),
|
|
|
+ ('nmode', ctypes.c_int),
|
|
|
+ ('modes', ctypes.c_void_p), # ctypes.POINTER(XRRModeInfo)
|
|
|
+ ]
|
|
|
+
|
|
|
+"""
|
|
|
+typedef struct _XRROutputInfo {
|
|
|
+ Time timestamp;
|
|
|
+ RRCrtc crtc;
|
|
|
+ char *name;
|
|
|
+ int nameLen;
|
|
|
+ unsigned long mm_width;
|
|
|
+ unsigned long mm_height;
|
|
|
+ Connection connection;
|
|
|
+ SubpixelOrder subpixel_order;
|
|
|
+ int ncrtc;
|
|
|
+ RRCrtc *crtcs;
|
|
|
+ int nclone;
|
|
|
+ RROutput *clones;
|
|
|
+ int nmode;
|
|
|
+ int npreferred;
|
|
|
+ RRMode *modes;
|
|
|
+} XRROutputInfo;
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
+class XRROutputInfo(ctypes.Structure):
|
|
|
+ _fields_ = [
|
|
|
+ ('timestamp', Time),
|
|
|
+ ('crtc', RRCrtc),
|
|
|
+ ('name', ctypes.c_char_p),
|
|
|
+ ('nameLen', ctypes.c_int),
|
|
|
+ ('mm_width', ctypes.c_ulong),
|
|
|
+ ('mm_height', ctypes.c_ulong),
|
|
|
+ ('connection', Connection),
|
|
|
+ ('subpixel_order', SubpixelOrder),
|
|
|
+ ('ncrtc', ctypes.c_int),
|
|
|
+ ('crtcs', ctypes.POINTER(RRCrtc)),
|
|
|
+ ('nclone', ctypes.c_int),
|
|
|
+ ('clones', ctypes.POINTER(RROutput)),
|
|
|
+ ('nmode', ctypes.c_int),
|
|
|
+ ('npreferred', ctypes.c_int),
|
|
|
+ ('modes', ctypes.POINTER(RRMode)),
|
|
|
+ ]
|
|
|
+
|
|
|
+X11 = ctypes.cdll.LoadLibrary("libX11.so")
|
|
|
+Xrandr = ctypes.cdll.LoadLibrary("libXrandr.so")
|
|
|
+Xrandr.XRRGetScreenResourcesCurrent.restype = ctypes.POINTER(
|
|
|
+ XRRScreenResources)
|
|
|
+"""
|
|
|
+XRROutputInfo *
|
|
|
+XRRGetOutputInfo (Display *dpy, XRRScreenResources *resources, RROutput output);
|
|
|
+"""
|
|
|
+Xrandr.XRRGetOutputInfo.restype = ctypes.POINTER(XRROutputInfo)
|
|
|
+
|
|
|
+
|
|
|
+def get_xrandr_output_infos(xdisplay):
|
|
|
+ screen_resrcs = Xrandr.XRRGetScreenResourcesCurrent(
|
|
|
+ xdisplay,
|
|
|
+ X11.XDefaultRootWindow(xdisplay),
|
|
|
+ )
|
|
|
+ assert isinstance(screen_resrcs.contents, XRRScreenResources)
|
|
|
+ return [Xrandr.XRRGetOutputInfo(xdisplay, screen_resrcs, screen_resrcs.contents.outputs[o])
|
|
|
+ for o in range(screen_resrcs.contents.noutput)]
|
|
|
+
|
|
|
+
|
|
|
+def process():
|
|
|
+ xdisplay = X11.XOpenDisplay(None)
|
|
|
+ for output_info in get_xrandr_output_infos(xdisplay):
|
|
|
+ output_name = output_info.contents.name \
|
|
|
+ .decode(sys.getfilesystemencoding())
|
|
|
+ print(output_name)
|
|
|
+ # if output_info.contents.connection == RR_Connected:
|
|
|
+ # print(output_name)
|
|
|
+ X11.XCloseDisplay(xdisplay)
|
|
|
+
|
|
|
+
|
|
|
+def _init_argparser():
|
|
|
+ import argparse
|
|
|
+ argparser = argparse.ArgumentParser(description=None)
|
|
|
+ return argparser
|
|
|
+
|
|
|
+
|
|
|
+def main(argv):
|
|
|
+ argparser = _init_argparser()
|
|
|
+ try:
|
|
|
+ import argcomplete
|
|
|
+ except ImportError:
|
|
|
+ pass
|
|
|
+ args = argparser.parse_args(argv)
|
|
|
+ process(**vars(args))
|
|
|
+ return 0
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ sys.exit(main(sys.argv[1:]))
|