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.
23 #include <X11/extensions/Xrandr.h>
27 struct output_info
*next
;
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
)
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
);
60 * Check to see if the monitor attached to an output
64 same_monitor(XRROutputInfo
*a
, XRROutputInfo
*b
)
68 if (a
->connection
!= b
->connection
)
70 if (a
->nmode
!= b
->nmode
)
72 if (a
->npreferred
!= b
->npreferred
)
74 for (m
= 0; m
< a
->nmode
; m
++)
75 if (a
->modes
[m
] != b
->modes
[m
])
81 check_output (Display
*dpy
, XRRScreenResources
*resources
, RROutput output
)
84 struct output_info
*oi
;
86 info
= XRRGetOutputInfo (dpy
, resources
, output
);
88 clear_output_info(output
);
91 oi
= find_output_info(output
);
93 int same
= same_monitor(oi
->info
, info
);
94 XRRFreeOutputInfo(oi
->info
);
98 oi
= calloc(1, sizeof (struct output_info
));
101 oi
->next
= output_info
;
108 main (int argc
, char **argv
)
111 int event_base
, error_base
;
115 const char *config
= NULL
;
116 const char *resize
= NULL
;
117 const char *display
= NULL
;
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' },
133 while ((c
= getopt_long(argc
, argv
, "c:r:d:hsav", opts
, NULL
)) != -1) {
145 config
= "xrandr --auto";
151 printf("%s\n", PACKAGE_STRING
);
155 fprintf(stderr
, "Usage: %s --display <display> --config <config> --resize <resize> --auto --start --version\n", argv
[0]);
161 dpy
= XOpenDisplay(display
);
163 fprintf(stderr
, "XOpenDisplay %s failed\n", XDisplayName(display
));
166 if (!XRRQueryExtension (dpy
, &event_base
, &error_base
) ||
167 !XRRQueryVersion (dpy
, &major
, &minor
))
169 fprintf (stderr
, "RandR extension missing on %s\n", XDisplayName(display
));
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
);
192 XNextEvent(dpy
, &ev
);
193 switch (ev
.type
- event_base
) {
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
))
201 XRRFreeScreenResources (resources
);
206 case ConfigureNotify
:
211 } while (XEventsQueued(dpy
, QueuedAfterFlush
));