123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- #!/usr/bin/env python3
- # PYTHON_ARGCOMPLETE_OK
- """
- https://cgit.freedesktop.org/xorg/app/xrandr/tree/xrandr.c
- """
- import ctypes
- import ctypes.util
- X_Time = ctypes.c_ulong
- """
- #ifndef _XTYPEDEF_XID
- # define _XTYPEDEF_XID
- # ifndef _XSERVER64
- typedef unsigned long XID;
- # else
- typedef CARD32 XID;
- # endif
- #endif
- """
- X_XID = ctypes.c_ulong
- """
- typedef XID RROutput;
- """
- X_RROutput = X_XID
- """
- typedef XID RRCrtc;
- """
- X_RRCrtc = X_XID
- """ /usr/include/X11/extensions/Xrandr.h
- typedef XID RRMode;
- """
- X_RRMode = X_XID
- """ /usr/include/X11/extensions/randr.h
- #define RR_Connected 0
- """
- X_RR_Connected = 0
- """ /usr/include/X11/extensions/randr.h
- typedef unsigned short Connection;
- """
- X_Connection = ctypes.c_ushort
- """ /usr/include/X11/extensions/randr.h
- typedef unsigned short SubpixelOrder;
- """
- X_SubpixelOrder = ctypes.c_ushort
- class X_XRRScreenResources(ctypes.Structure):
- """ /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;
- """
- _fields_ = [
- ('timestamp', X_Time),
- ('configTimestamp', X_Time),
- ('ncrtc', ctypes.c_int),
- ('crtcs', ctypes.POINTER(X_RRCrtc)),
- ('noutput', ctypes.c_int),
- ('outputs', ctypes.POINTER(X_RROutput)),
- ('nmode', ctypes.c_int),
- ('modes', ctypes.c_void_p), # ctypes.POINTER(XRRModeInfo)
- ]
- class X_XRROutputInfo(ctypes.Structure):
- """
- 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;
- """
- _fields_ = [
- ('timestamp', X_Time),
- ('crtc', X_RRCrtc),
- ('name', ctypes.c_char_p),
- ('nameLen', ctypes.c_int),
- ('mm_width', ctypes.c_ulong),
- ('mm_height', ctypes.c_ulong),
- ('connection', X_Connection),
- ('subpixel_order', X_SubpixelOrder),
- ('ncrtc', ctypes.c_int),
- ('crtcs', ctypes.POINTER(X_RRCrtc)),
- ('nclone', ctypes.c_int),
- ('clones', ctypes.POINTER(X_RROutput)),
- ('nmode', ctypes.c_int),
- ('npreferred', ctypes.c_int),
- ('modes', ctypes.POINTER(X_RRMode)),
- ]
- X11 = ctypes.cdll.LoadLibrary("libX11.so")
- Xrandr = ctypes.cdll.LoadLibrary("libXrandr.so")
- Xrandr.XRRGetScreenResourcesCurrent.restype = \
- ctypes.POINTER(X_XRRScreenResources)
- libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
- """
- XRROutputInfo *
- XRRGetOutputInfo (Display *dpy, XRRScreenResources *resources, RROutput output);
- """
- Xrandr.XRRGetOutputInfo.restype = ctypes.POINTER(X_XRROutputInfo)
- class RandrOutputInfo:
- def __init__(self,
- xdisplay,
- screen_resrcs: ctypes.POINTER(X_XRRScreenResources),
- output: X_RROutput):
- self._p = Xrandr.XRRGetOutputInfo(xdisplay, screen_resrcs, output)
- def __del__(self):
- libc.free(self._p)
- @property
- def enabled(self):
- return self._p.contents.crtc != 0
- @property
- def connected(self):
- return self._p.contents.connection == X_RR_Connected
- @property
- def name(self):
- return self._p.contents.name.decode()
- def get_xrandr_output_infos(xdisplay):
- screen_resrcs = Xrandr.XRRGetScreenResourcesCurrent(
- xdisplay,
- X11.XDefaultRootWindow(xdisplay),
- )
- assert isinstance(screen_resrcs.contents, X_XRRScreenResources)
- return [RandrOutputInfo(xdisplay, screen_resrcs, screen_resrcs.contents.outputs[o])
- for o in range(screen_resrcs.contents.noutput)]
- def process(connected, disabled, enabled):
- xdisplay = X11.XOpenDisplay(None)
- for output_info in get_xrandr_output_infos(xdisplay):
- if ((not connected or output_info.connected)
- and (not disabled or not output_info.enabled)
- and (not enabled or output_info.enabled)):
- print(output_info.name)
- X11.XCloseDisplay(xdisplay)
- def _init_argparser():
- import argparse
- argparser = argparse.ArgumentParser(
- description='Show names of outputs available to the X server.',
- )
- argparser.add_argument(
- '-c', '--connected',
- action='store_true',
- help='connected only',
- )
- argparser.add_argument(
- '-d', '--disabled',
- action='store_true',
- help='disabled only (does not imply --connected)',
- )
- argparser.add_argument(
- '-e', '--enabled',
- action='store_true',
- help='enabled only (does not imply --connected)',
- )
- 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__":
- import sys
- sys.exit(main(sys.argv[1:]))
|