diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | include/X11/extensions/Xrandr.h | 30 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/XrrMonitor.c | 200 |
4 files changed, 233 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index 15b1e8c..d0baa08 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ AC_PREREQ([2.60]) # digit in the version number to track changes which don't affect the # protocol, so Xrandr version l.n.m corresponds to protocol version l.n # -AC_INIT([libXrandr], [1.4.2], +AC_INIT([libXrandr], [1.5.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXrandr]) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS([config.h]) diff --git a/include/X11/extensions/Xrandr.h b/include/X11/extensions/Xrandr.h index f394864..65940bb 100644 --- a/include/X11/extensions/Xrandr.h +++ b/include/X11/extensions/Xrandr.h @@ -552,6 +552,36 @@ XRRGetProviderProperty (Display *dpy, RRProvider provider, unsigned long *nitems, unsigned long *bytes_after, unsigned char **prop); + +typedef struct _XRRMonitorInfo { + Atom name; + Bool primary; + Bool automatic; + int noutput; + int x; + int y; + int width; + int height; + int mwidth; + int mheight; + RROutput *outputs; +} XRRMonitorInfo; + +XRRMonitorInfo * +XRRAllocateMonitor(Display *dpy, int noutput); + +XRRMonitorInfo * +XRRGetMonitors(Display *dpy, Window window, Bool get_active, int *nmonitors); + +void +XRRSetMonitor(Display *dpy, Window window, XRRMonitorInfo *monitor); + +void +XRRDeleteMonitor(Display *dpy, Window window, Atom name); + +void +XRRFreeMonitors(XRRMonitorInfo *monitors); + _XFUNCPROTOEND #endif /* _XRANDR_H_ */ diff --git a/src/Makefile.am b/src/Makefile.am index 2113846..673fe2c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,8 @@ libXrandr_la_SOURCES = \ XrrProperty.c \ XrrScreen.c \ XrrProvider.c \ - XrrProviderProperty.c + XrrProviderProperty.c \ + XrrMonitor.c libXrandr_la_LIBADD = @RANDR_LIBS@ diff --git a/src/XrrMonitor.c b/src/XrrMonitor.c new file mode 100644 index 0000000..71d3943 --- /dev/null +++ b/src/XrrMonitor.c @@ -0,0 +1,200 @@ +/* + * Copyright © 2014 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <X11/Xlib.h> +/* we need to be able to manipulate the Display structure on events */ +#include <X11/Xlibint.h> +#include <X11/extensions/render.h> +#include <X11/extensions/Xrender.h> +#include "Xrandrint.h" + +XRRMonitorInfo * +XRRGetMonitors(Display *dpy, Window window, Bool get_active, int *nmonitors) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetMonitorsReply rep; + xRRGetMonitorsReq *req; + int nbytes, nbytesRead, rbytes; + int nmon, noutput; + int m, o; + char *buf, *buf_head; + xRRMonitorInfo *xmon; + CARD32 *xoutput; + XRRMonitorInfo *mon = NULL; + RROutput *output; + + RRCheckExtension (dpy, info, NULL); + + *nmonitors = -1; + + LockDisplay (dpy); + GetReq (RRGetMonitors, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetMonitors; + req->window = window; + req->get_active = get_active; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + nbytes = (long) rep.length << 2; + nmon = rep.nmonitors; + noutput = rep.noutputs; + nbytesRead = nmon * SIZEOF(xRRMonitorInfo) + noutput * 4; + + if (nmon > 0) { + + /* + * first we must compute how much space to allocate for + * randr library's use; we'll allocate the structures in a single + * allocation, on cleanlyness grounds. + */ + + rbytes = nmon * sizeof (XRRMonitorInfo) + noutput * sizeof(RROutput); + + buf = buf_head = Xmalloc (nbytesRead); + mon = Xmalloc (rbytes); + + if (buf == NULL || mon == NULL) { + if (buf != NULL) Xfree(buf); + if (mon != NULL) Xfree(mon); + _XEatDataWords (dpy, rep.length); + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + _XReadPad(dpy, buf, nbytesRead); + + output = (RROutput *) (mon + nmon); + + for (m = 0; m < nmon; m++) { + xmon = (xRRMonitorInfo *) buf; + mon[m].name = xmon->name; + mon[m].primary = xmon->primary; + mon[m].automatic = xmon->automatic; + mon[m].noutput = xmon->noutput; + mon[m].x = xmon->x; + mon[m].y = xmon->y; + mon[m].width = xmon->width; + mon[m].height = xmon->height; + mon[m].mwidth = xmon->widthInMillimeters; + mon[m].mheight = xmon->heightInMillimeters; + mon[m].outputs = output; + buf += SIZEOF (xRRMonitorInfo); + xoutput = (CARD32 *) buf; + for (o = 0; o < xmon->noutput; o++) + output[o] = xoutput[o]; + output += xmon->noutput; + buf += xmon->noutput * 4; + } + Xfree(buf_head); + } + + /* + * Skip any extra data + */ + if (nbytes > nbytesRead) + _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); + + UnlockDisplay (dpy); + SyncHandle (); + + *nmonitors = nmon; + return mon; +} + +void +XRRSetMonitor(Display *dpy, Window window, XRRMonitorInfo *monitor) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRSetMonitorReq *req; + + RRSimpleCheckExtension (dpy, info); + + LockDisplay(dpy); + GetReq (RRSetMonitor, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetMonitor; + req->length += monitor->noutput; + req->window = window; + req->monitor.name = monitor->name; + req->monitor.primary = monitor->primary; + req->monitor.automatic = False; + req->monitor.noutput = monitor->noutput; + req->monitor.x = monitor->x; + req->monitor.y = monitor->y; + req->monitor.width = monitor->width; + req->monitor.height = monitor->height; + req->monitor.widthInMillimeters = monitor->mwidth; + req->monitor.heightInMillimeters = monitor->mheight; + Data32 (dpy, monitor->outputs, monitor->noutput * 4); + + UnlockDisplay (dpy); + SyncHandle (); +} + +void +XRRDeleteMonitor(Display *dpy, Window window, Atom name) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRDeleteMonitorReq *req; + + RRSimpleCheckExtension (dpy, info); + + LockDisplay(dpy); + GetReq (RRDeleteMonitor, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRDeleteMonitor; + req->window = window; + req->name = name; + UnlockDisplay (dpy); + SyncHandle (); +} + +XRRMonitorInfo * +XRRAllocateMonitor(Display *dpy, int noutput) +{ + XRRMonitorInfo *monitor = calloc(1, sizeof (XRRMonitorInfo) + noutput * sizeof (RROutput)); + if (!monitor) + return NULL; + monitor->outputs = (RROutput *) (monitor + 1); + monitor->noutput = noutput; + return monitor; +} + +void +XRRFreeMonitors(XRRMonitorInfo *monitors) +{ + if (monitors) + Xfree(monitors); +} + |