Use mode ID instead of mode for autoconfig
[x-on-resize.git] / x-on-resize.c
blob55692c152916e24b8e4302e1ed47de1c9d06185c
1 /*
2 * Copyright © 2011 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <getopt.h>
21 #include <unistd.h>
22 #include <X11/Xlib.h>
23 #include <X11/extensions/Xrandr.h>
24 #include "config.h"
26 struct output_info {
27 struct output_info *next;
28 RROutput output;
29 XRROutputInfo *info;
32 static struct output_info *output_info;
34 static struct output_info *
35 find_output_info (RROutput output)
37 struct output_info *oi;
39 for (oi = output_info; oi; oi = oi->next)
40 if (oi->output == output)
41 return oi;
42 return NULL;
45 static void
46 clear_output_info (RROutput output)
48 struct output_info *oi, **prev;
50 for (prev = &output_info; (oi = *prev); prev = &(oi->next))
51 if (oi->output == output) {
52 XRRFreeOutputInfo (oi->info);
53 *prev = oi->next;
54 free (oi);
55 break;
60 * Check to see if the monitor attached to an output
61 * is the same
63 static int
64 same_monitor(XRROutputInfo *a, XRROutputInfo *b)
66 int m;
68 if (a->connection != b->connection)
69 return 0;
70 if (a->nmode != b->nmode)
71 return 0;
72 if (a->npreferred != b->npreferred)
73 return 0;
74 for (m = 0; m < a->nmode; m++)
75 if (a->modes[m] != b->modes[m])
76 return 0;
77 return 1;
80 static int
81 check_output (Display *dpy, XRRScreenResources *resources, RROutput output)
83 XRROutputInfo *info;
84 struct output_info *oi;
86 info = XRRGetOutputInfo (dpy, resources, output);
87 if (!info) {
88 clear_output_info(output);
89 return 0;
91 oi = find_output_info(output);
92 if (oi) {
93 int same = same_monitor(oi->info, info);
94 XRRFreeOutputInfo(oi->info);
95 oi->info = info;
96 return same;
98 oi = calloc(1, sizeof (struct output_info));
99 oi->output = output;
100 oi->info = info;
101 oi->next = output_info;
102 output_info = oi;
103 return 0;
108 main (int argc, char **argv)
110 Display *dpy;
111 int event_base, error_base;
112 int major, minor;
113 XEvent ev;
114 XRRNotifyEvent *nev;
115 const char *config = NULL;
116 const char *resize = NULL;
117 const char *display = NULL;
118 int c, o;
119 int start = 0;
120 XRRScreenResources *resources;
122 static struct option opts[] = {
123 { "config", 1, NULL, 'c' },
124 { "resize", 1, NULL, 'r' },
125 { "start", 0, NULL, 's' },
126 { "auto", 0, NULL, 'a' },
127 { "display", 1, NULL, 'd' },
128 { "help", 0, NULL, 'h' },
129 { "version", 0, NULL, 'v' },
130 { 0, 0, NULL, 0 }
133 while ((c = getopt_long(argc, argv, "c:r:d:hsav", opts, NULL)) != -1) {
134 switch (c) {
135 case 'c':
136 config = optarg;
137 break;
138 case 'r':
139 resize = optarg;
140 break;
141 case 'd':
142 display = optarg;
143 break;
144 case 'a':
145 config = "xrandr --auto";
146 break;
147 case 's':
148 start = 1;
149 break;
150 case 'v':
151 printf("%s\n", PACKAGE_STRING);
152 exit(0);
153 case 'h':
154 default:
155 fprintf(stderr, "Usage: %s --display <display> --config <config> --resize <resize> --auto --start --version\n", argv[0]);
156 exit(1);
157 break;
161 dpy = XOpenDisplay(display);
162 if (!dpy) {
163 fprintf(stderr, "XOpenDisplay %s failed\n", XDisplayName(display));
164 exit(1);
166 if (!XRRQueryExtension (dpy, &event_base, &error_base) ||
167 !XRRQueryVersion (dpy, &major, &minor))
169 fprintf (stderr, "RandR extension missing on %s\n", XDisplayName(display));
170 exit (1);
172 XRRSelectInput(dpy, RootWindow(dpy, 0), RROutputChangeNotifyMask);
173 XSelectInput(dpy, RootWindow(dpy, 0), StructureNotifyMask);
175 /* Get current configuration */
176 resources = XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, 0));
177 for (o = 0; o < resources->noutput; o++)
178 (void) check_output(dpy, resources, resources->outputs[o]);
179 XRRFreeScreenResources (resources);
181 if (start) {
182 if (config)
183 system(config);
184 if (resize)
185 system(resize);
187 for (;;) {
188 int configed = 0;
189 int resized = 0;
191 do {
192 XNextEvent(dpy, &ev);
193 switch (ev.type - event_base) {
194 case RRNotify:
195 nev = (XRRNotifyEvent *) &ev;
196 if (nev->subtype == RRNotify_OutputChange) {
197 XRROutputChangeNotifyEvent *noev = (XRROutputChangeNotifyEvent *) nev;
198 resources = XRRGetScreenResources(dpy, RootWindow(dpy, 0));
199 if (!check_output(dpy, resources, noev->output))
200 configed = 1;
201 XRRFreeScreenResources (resources);
203 break;
205 switch (ev.type) {
206 case ConfigureNotify:
207 resized = 1;
208 break;
210 usleep(100000);
211 } while (XEventsQueued(dpy, QueuedAfterFlush));
212 if (configed) {
213 if (config)
214 system(config);
215 else
216 printf ("config\n");
218 if (resized) {
219 if (resize)
220 system(resize);
221 else
222 printf ("resize\n");