Description: Add XRandR support, adapted from commit
 d6e507e72e757a31ccf33a70e19ae4f89bf8c240 on project
 https://github.com/unixdj/xphoon
Author: Vadim Vygonets <vadik@cs.huji.ac.il>
Reviewed-by: Ricardo Mones <mones@debian.org>
Last-Update: 2018-10-23
diff --git a/Imakefile b/Imakefile
index f4d7313..c8a9c19 100644
--- a/Imakefile
+++ b/Imakefile
@@ -12,8 +12,8 @@
 
 DEFINES =		$(CPPFLAGS)
 INCLUDES =		-I. -I$(TOP) -I$(TOP)/X11 -I$(TOP)/X11/bitmaps
-LOCAL_LIBRARIES =	$(XLIB)
-DEPLIBS =		$(DEPXLIB)
+LOCAL_LIBRARIES =	$(XLIB) $(XRANDRLIB)
+DEPLIBS =		$(DEPXLIB) $(DEPXRANDRLIB)
 LDOPTIONS =		$(LDFLAGS)
 LDLIBS =		-lm
 
diff --git a/xphoon.c b/xphoon.c
index 99e7adb..49ac3b0 100644
--- a/xphoon.c
+++ b/xphoon.c
@@ -17,6 +17,7 @@ static char rcsid[] =
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
 #include "vroot.h"
 #include <stdio.h>
 #include <stdlib.h>	/* added by David Frey */
@@ -251,6 +252,10 @@ usage:
 
 /* xinit - initialize X stuff */
 
+struct crtcinfo {
+    int x, y, w, h;
+    };
+
 static Display* display;
 static int screen;
 static Window root;
@@ -259,6 +264,8 @@ static GC onegc;
 static GC zerogc;
 static GC copygc;
 static GC clipgc;
+static int hasrandr, ncrtc;
+struct crtcinfo *crtcs;
 
 static void
 xinit( display_name )
@@ -266,6 +273,7 @@ xinit( display_name )
     {
     Pixmap temp_pixmap;
     XGCValues values;
+    int i, j;
 
     display = XOpenDisplay( display_name );
     if ( display == (Display*) 0 )
@@ -277,8 +285,23 @@ xinit( display_name )
 	}
     screen = DefaultScreen( display );
     root = DefaultRootWindow( display );
-    root_w = DisplayWidth( display, screen );
-    root_h = DisplayHeight( display, screen );
+    hasrandr = XRRQueryExtension( display, &i, &j );
+    if ( ! hasrandr )
+	{
+	root_w = DisplayWidth( display, screen );
+	root_h = DisplayHeight( display, screen );
+	ncrtc = 1;
+	crtcs = malloc( sizeof( struct crtcinfo ) );
+	if ( crtcs == NULL )
+	    {
+	    (void) fprintf( stderr, "%s: couldn't allocate crtc", argv0 );
+	    exit( 1 );
+	    }
+	crtcs[0].x = 0;
+	crtcs[0].y = 0;
+	crtcs[0].w = root_w;
+	crtcs[0].h = root_h;
+	}
     temp_pixmap = XCreatePixmap( display, root, 1, 1, 1 );
     /* Don't want NoExpose events coming back from XCopyArea and XCopyPlane */
     values.graphics_exposures = False;
@@ -297,6 +320,52 @@ xinit( display_name )
     XSetBackground( display, clipgc, WhitePixel( display, screen ) );
     }
 
+static void
+xrrinit( void )
+    {
+    XRRScreenResources *sr;
+    XRRCrtcInfo *ci;
+    int i;
+
+    if ( ! hasrandr )
+	return;
+    root_w = DisplayWidth( display, screen );
+    root_h = DisplayHeight( display, screen );
+    sr = XRRGetScreenResources( display, root );
+    ncrtc = sr->ncrtc;
+    crtcs = malloc( sizeof( struct crtcinfo ) * ncrtc );
+    if ( crtcs == NULL )
+	{
+	(void) fprintf( stderr, "%s: couldn't allocate crtc", argv0 );
+	exit( 1 );
+	}
+    memset( crtcs, 0, sizeof( struct crtcinfo ) * ncrtc);
+    for ( i = 0; i < ncrtc; i++ )
+	{
+	ci = XRRGetCrtcInfo( display, sr, sr->crtcs[i] );
+	if ( ci == NULL )
+	    continue;
+	if ( ci->noutput != 0 )
+	    {
+	    crtcs[i].x = ci->x;
+	    crtcs[i].y = ci->y;
+	    crtcs[i].w = ci->width;
+	    crtcs[i].h = ci->height;
+	    }
+	XRRFreeCrtcInfo( ci );
+	}
+    XRRFreeScreenResources( sr );
+    }
+
+static void
+xrrcleanup( void )
+    {
+    if ( ! hasrandr )
+	return;
+    free( crtcs );
+    crtcs = NULL;
+    }
+
 
 /* make_star_tiles - make random star tiles */
 
@@ -597,6 +666,8 @@ set_root( bits_w, bits_h, bits, cx, cy, r )
 	display, mask_bitmap, onegc, cx - r + 2, cy - r + 2,
 	r * 2 - 3, r * 2 - 3, 0, 360 * 64 );
 
+    xrrinit();
+
     /* Make the root pixmap. */
     root_pixmap = XCreatePixmap(
 	display, root, root_w, root_h, DefaultDepth( display, screen ) );
@@ -624,13 +695,20 @@ set_root( bits_w, bits_h, bits, cx, cy, r )
 	}
 
     /* Put the moon into the stars. */
-    x = ( root_w - bits_w ) / 2;
-    y = ( root_h - bits_h ) / 2;
-    XSetClipMask( display, clipgc, mask_bitmap );
-    XSetClipOrigin( display, clipgc, x, y );
-    XCopyPlane(
-	display, moon_bitmap, root_pixmap, clipgc, 0, 0, bits_w, bits_h, x, y,
-	1 );
+    for ( i = 0; i < ncrtc; i++ )
+	{
+	if ( crtcs[i].w == 0 )
+	    continue;
+	x = crtcs[i].x + ( ( crtcs[i].w - bits_w ) / 2 );
+	y = crtcs[i].y + ( ( crtcs[i].h - bits_h ) / 2 );
+	XSetClipMask( display, clipgc, mask_bitmap );
+	XSetClipOrigin( display, clipgc, x, y );
+	XCopyPlane(
+	    display, moon_bitmap, root_pixmap, clipgc, 0, 0, bits_w, bits_h,
+	    x, y, 1 );
+	}
+
+    xrrcleanup();
 
     /* And set the root. */
     XSetWindowBackgroundPixmap( display, root, root_pixmap );
@@ -666,6 +744,8 @@ cleanup()
     if ( star_tiles_made )
 	for ( i = 0; i < NUM_TILES; ++i )
 	    XFreePixmap( display, star_tile[i] );
+    if ( ! hasrandr )
+	free( crtcs );
     XFreeGC( display, onegc );
     XFreeGC( display, zerogc );
     XFreeGC( display, copygc );
