summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@linux.intel.com>2017-01-20 18:08:18 +0200
committerMartin Peres <martin.peres@linux.intel.com>2017-01-20 18:08:18 +0200
commit1443224f9d2de179514a0bf14194ac3fe3a01499 (patch)
tree3600ee64d2bd38ad49f263d6dc15548b9d908d89
initial commit
-rw-r--r--Makefile27
-rw-r--r--auto-randr.c382
2 files changed, 409 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0c97d49
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
+CC = gcc
+CFLAGS = -c -Wall
+LDFLAGS =
+
+# List of sources:
+SOURCES = auto-randr.c
+OBJECTS = $(SOURCES:.cpp=.o)
+
+# Name of executable target:
+EXECUTABLE = auto-randr
+
+CFLAGS += `pkg-config --cflags x11`
+LDFLAGS += `pkg-config --libs x11`
+
+CFLAGS += `pkg-config --cflags xrandr`
+LDFLAGS += `pkg-config --libs xrandr`
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CC) $(OBJECTS) -o $@ $(LDFLAGS)
+
+.cpp.o:
+ $(CC) $(CFLAGS) $< -o $@
+
+clean:
+ rm $(OBJECTS) $(EXECUTABLE)
diff --git a/auto-randr.c b/auto-randr.c
new file mode 100644
index 0000000..ac3a9c1
--- /dev/null
+++ b/auto-randr.c
@@ -0,0 +1,382 @@
+/*
+Copyright (c) 1988 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+/*
+ * Author: Jim Fulton, MIT X Consortium (For the XEV part)
+ * Martin Peres (Automatic setting of the highest-available resolution)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <X11/Xlocale.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/Xrandr.h>
+
+const char *Yes = "YES";
+const char *No = "NO";
+const char *Unknown = "unknown";
+
+const char *ProgramName;
+Display *dpy;
+int screen;
+
+Bool have_rr;
+int rr_event_base, rr_error_base;
+
+static void
+prologue (XEvent *eventp, const char *event_name)
+{
+ XAnyEvent *e = (XAnyEvent *) eventp;
+
+ printf ("\n%s event, serial %ld, synthetic %s, window 0x%lx,\n",
+ event_name, e->serial, e->send_event ? Yes : No, e->window);
+}
+
+static void
+print_SubPixelOrder (SubpixelOrder subpixel_order)
+{
+ switch (subpixel_order) {
+ case SubPixelUnknown: printf ("SubPixelUnknown"); return;
+ case SubPixelHorizontalRGB: printf ("SubPixelHorizontalRGB"); return;
+ case SubPixelHorizontalBGR: printf ("SubPixelHorizontalBGR"); return;
+ case SubPixelVerticalRGB: printf ("SubPixelVerticalRGB"); return;
+ case SubPixelVerticalBGR: printf ("SubPixelVerticalBGR"); return;
+ case SubPixelNone: printf ("SubPixelNone"); return;
+ default: printf ("%d", subpixel_order);
+ }
+}
+
+static void
+print_Rotation (Rotation rotation)
+{
+ if (rotation & RR_Rotate_0)
+ printf ("RR_Rotate_0");
+ else if (rotation & RR_Rotate_90)
+ printf ("RR_Rotate_90");
+ else if (rotation & RR_Rotate_180)
+ printf ("RR_Rotate_180");
+ else if (rotation & RR_Rotate_270)
+ printf ("RR_Rotate_270");
+ else {
+ printf ("%d", rotation);
+ return;
+ }
+ if (rotation & RR_Reflect_X)
+ printf (", RR_Reflect_X");
+ if (rotation & RR_Reflect_Y)
+ printf (", RR_Reflect_Y");
+}
+
+static void
+print_Connection (Connection connection)
+{
+ switch (connection) {
+ case RR_Connected: printf ("RR_Connected"); return;
+ case RR_Disconnected: printf ("RR_Disconnected"); return;
+ case RR_UnknownConnection: printf ("RR_UnknownConnection"); return;
+ default: printf ("%d", connection);
+ }
+}
+
+static void
+do_RRScreenChangeNotify (XEvent *eventp)
+{
+ XRRScreenChangeNotifyEvent *e = (XRRScreenChangeNotifyEvent *) eventp;
+
+ XRRUpdateConfiguration (eventp);
+ printf (" root 0x%lx, timestamp %lu, config_timestamp %lu\n",
+ e->root, e->timestamp, e->config_timestamp);
+ printf (" size_index %hu", e->size_index);
+ printf (", subpixel_order ");
+ print_SubPixelOrder (e->subpixel_order);
+ printf ("\n rotation ");
+ print_Rotation (e->rotation);
+ printf("\n width %d, height %d, mwidth %d, mheight %d\n",
+ e->width, e->height, e->mwidth, e->mheight);
+}
+
+static Status
+do_XRRSetCrtcConfig (XRRScreenResources *resources, RRCrtc crtc, RRMode mode,
+ RROutput *outputs, int noutputs)
+{
+ XGrabServer(dpy);
+ Status s = XRRSetCrtcConfig(dpy, resources, crtc, CurrentTime, 0, 0,
+ mode, RR_Rotate_0, outputs, noutputs);
+ if (s != RRSetConfigSuccess)
+ printf("XRRSetCrtcConfig failed!");
+ XUngrabServer(dpy);
+
+ return s;
+}
+
+static void
+do_RRNotify_OutputChange (XEvent *eventp, XRRScreenResources *screen_resources)
+{
+ XRROutputChangeNotifyEvent *e = (XRROutputChangeNotifyEvent *) eventp;
+ XRROutputInfo *output_info = NULL;
+ XRRModeInfo *mode_info = NULL, *highest_mode = NULL;
+ XRRCrtcInfo *crtc_info = NULL;
+ int i, j;
+
+ if (screen_resources) {
+ output_info = XRRGetOutputInfo (dpy, screen_resources, e->output);
+ for (i = 0; i < screen_resources->nmode; i++)
+ if (screen_resources->modes[i].id == e->mode) {
+ mode_info = &screen_resources->modes[i]; break;
+ }
+ }
+ printf (" subtype XRROutputChangeNotifyEvent\n");
+ if (output_info)
+ printf (" output %s, ", output_info->name);
+ else
+ printf (" output %lu, ", e->output);
+ if (e->crtc)
+ printf("crtc %lu, ", e->crtc);
+ else
+ printf("crtc None, ");
+ if (mode_info)
+ printf ("mode %s (%dx%d)\n", mode_info->name, mode_info->width,
+ mode_info->height);
+ else if (e->mode)
+ printf ("mode %lu\n", e->mode);
+ else
+ printf("mode None\n");
+ printf (" rotation ");
+ print_Rotation (e->rotation);
+ printf ("\n connection ");
+ print_Connection (e->connection);
+ printf (", subpixel_order ");
+ print_SubPixelOrder (e->subpixel_order);
+ printf ("\n");
+
+ if (e->connection == RR_Connected) {
+ XID crtc_avail = None;
+
+ /* Now list all the available modes */
+ printf (" Found the following modes:\n");
+ for (i = 0; i < output_info->nmode; i++) {
+ /* Find the corresponding mode */
+ for (j = 0; j < screen_resources->nmode; j++)
+ if (output_info->modes[i] == screen_resources->modes[j].id)
+ mode_info = &screen_resources->modes[j];
+
+ printf(" %lu: %s, dotClk=%lu Hz, flags=%lu%s%s\n", mode_info->id,
+ mode_info->name, mode_info->dotClock, mode_info->modeFlags,
+ mode_info->id == e->mode ? "*" : "",
+ i < output_info->npreferred ? "+" : "");
+
+ if (highest_mode == NULL ||
+ mode_info->width * mode_info->height >
+ highest_mode->width * highest_mode->height)
+ highest_mode = mode_info;
+ }
+ if (e->crtc) {
+ crtc_avail = e->crtc;
+ } else {
+ printf (" Search for an available CRTC:\n");
+ for (i = 0; i < screen_resources->ncrtc; i++) {
+ crtc_info = XRRGetCrtcInfo (dpy, screen_resources,
+ screen_resources->crtcs[i]);
+ printf(" %lu: %ix%i (mode %lu)\n", screen_resources->crtcs[i],
+ crtc_info->width, crtc_info->height, crtc_info->mode);
+
+ if (crtc_info->mode == None)
+ crtc_avail = screen_resources->crtcs[i];
+ }
+ }
+
+ if (highest_mode->id == e->mode) {
+ printf (" The highest mode is already selected, nothing to do!\n");
+ } else if (crtc_avail != None) {
+ printf (" Setting the mode %lu (%s, dotClk=%lu Hz) on CRTC %lu\n",
+ highest_mode->id, highest_mode->name, highest_mode->dotClock,
+ crtc_avail);
+
+ do_XRRSetCrtcConfig (screen_resources, crtc_avail, highest_mode->id,
+ &e->output, 1);
+ } else
+ printf (" Found no available CRTC, do not set a new mode!\n");
+ } else if (e->crtc != None) {
+ printf (" Disable the CRTC %lu\n", e->crtc);
+
+ do_XRRSetCrtcConfig (screen_resources, e->crtc, None, NULL, 0);
+ }
+
+ XRRFreeOutputInfo (output_info);
+}
+
+static void
+do_RRNotify_CrtcChange (XEvent *eventp, XRRScreenResources *screen_resources)
+{
+ XRRCrtcChangeNotifyEvent *e = (XRRCrtcChangeNotifyEvent *) eventp;
+ XRRModeInfo *mode_info = NULL;
+
+ if (screen_resources) {
+ int i;
+
+ for (i = 0; i < screen_resources->nmode; i++)
+ if (screen_resources->modes[i].id == e->mode) {
+ mode_info = &screen_resources->modes[i]; break;
+ }
+ }
+ printf (" subtype XRRCrtcChangeNotifyEvent\n");
+ if (e->crtc)
+ printf(" crtc %lu, ", e->crtc);
+ else
+ printf(" crtc None, ");
+ if (mode_info)
+ printf ("mode %s, ", mode_info->name);
+ else if (e->mode)
+ printf ("mode %lu, ", e->mode);
+ else
+ printf("mode None, ");
+ printf ("rotation ");
+ print_Rotation (e->rotation);
+ printf ("\n x %d, y %d, width %d, height %d\n",
+ e->x, e->y, e->width, e->height);
+}
+
+static void
+do_RRNotify_OutputProperty (XEvent *eventp,
+ XRRScreenResources *screen_resources)
+{
+ XRROutputPropertyNotifyEvent *e = (XRROutputPropertyNotifyEvent *) eventp;
+ XRROutputInfo *output_info = NULL;
+ char *property = XGetAtomName (dpy, e->property);
+
+ if (screen_resources)
+ output_info = XRRGetOutputInfo (dpy, screen_resources, e->output);
+ printf (" subtype XRROutputPropertyChangeNotifyEvent\n");
+ if (output_info)
+ printf (" output %s, ", output_info->name);
+ else
+ printf (" output %lu, ", e->output);
+ printf ("property %s, timestamp %lu, state ",
+ property, e->timestamp);
+ if (e->state == PropertyNewValue)
+ printf ("NewValue\n");
+ else if (e->state == PropertyDelete)
+ printf ("Delete\n");
+ else
+ printf ("%d\n", e->state);
+ XRRFreeOutputInfo (output_info);
+ XFree (property);
+}
+
+static void
+do_RRNotify (XEvent *eventp)
+{
+ XRRNotifyEvent *e = (XRRNotifyEvent *) eventp;
+ XRRScreenResources *screen_resources;
+
+ XRRUpdateConfiguration (eventp);
+ screen_resources = XRRGetScreenResources (dpy, e->window);
+ prologue (eventp, "RRNotify");
+ switch (e->subtype) {
+ case RRNotify_OutputChange:
+ do_RRNotify_OutputChange (eventp, screen_resources); break;
+ case RRNotify_CrtcChange:
+ do_RRNotify_CrtcChange (eventp, screen_resources); break;
+ case RRNotify_OutputProperty:
+ do_RRNotify_OutputProperty (eventp, screen_resources); break;
+ default:
+ printf (" subtype %d\n", e->subtype);
+ }
+ XRRFreeScreenResources (screen_resources);
+}
+
+int
+main (int argc, char **argv)
+{
+ char *displayname = NULL;
+ Window w;
+ int done;
+
+ ProgramName = argv[0];
+
+ dpy = XOpenDisplay (displayname);
+ if (!dpy) {
+ fprintf (stderr, "%s: unable to open display '%s'\n",
+ ProgramName, XDisplayName (displayname));
+ exit (1);
+ }
+
+ screen = DefaultScreen (dpy);
+ w = RootWindow(dpy, screen);
+
+ have_rr = XRRQueryExtension (dpy, &rr_event_base, &rr_error_base);
+ if (have_rr) {
+ int rr_major, rr_minor;
+
+ if (XRRQueryVersion (dpy, &rr_major, &rr_minor)) {
+ int rr_mask = RROutputChangeNotifyMask | RROutputPropertyNotifyMask;
+ /* RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask; */
+
+ if (rr_major == 1 && rr_minor <= 1) {
+ rr_mask &= ~(RRCrtcChangeNotifyMask |
+ RROutputChangeNotifyMask |
+ RROutputPropertyNotifyMask);
+ }
+
+ XRRSelectInput (dpy, w, rr_mask);
+ }
+ }
+
+ for (done = 0; !done; ) {
+ XEvent event;
+
+ XNextEvent (dpy, &event);
+
+ switch (event.type) {
+ default:
+ if (have_rr) {
+ if (event.type == rr_event_base + RRScreenChangeNotify) {
+ prologue (&event, "RRScreenChangeNotify");
+ do_RRScreenChangeNotify (&event);
+ break;
+ }
+ if (event.type == rr_event_base + RRNotify) {
+ do_RRNotify (&event);
+ break;
+ }
+ }
+ printf ("Unknown event type %d, exit!\n", event.type);
+ done = 1;
+ break;
+ }
+ fflush(stdout);
+ }
+
+ XCloseDisplay (dpy);
+ return 0;
+}