XrrMonitor.c revision b242714c
1/* 2 * Copyright © 2014 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include <config.h> 25#endif 26 27#include <limits.h> 28#include <stdio.h> 29#include <X11/Xlib.h> 30/* we need to be able to manipulate the Display structure on events */ 31#include <X11/Xlibint.h> 32#include <X11/extensions/render.h> 33#include <X11/extensions/Xrender.h> 34#include "Xrandrint.h" 35 36XRRMonitorInfo * 37XRRGetMonitors(Display *dpy, Window window, Bool get_active, int *nmonitors) 38{ 39 XExtDisplayInfo *info = XRRFindDisplay(dpy); 40 xRRGetMonitorsReply rep; 41 xRRGetMonitorsReq *req; 42 int nbytes, nbytesRead, rbytes; 43 int nmon, noutput; 44 int m, o; 45 char *buf, *buf_head; 46 xRRMonitorInfo *xmon; 47 CARD32 *xoutput; 48 XRRMonitorInfo *mon = NULL; 49 RROutput *output; 50 51 RRCheckExtension (dpy, info, NULL); 52 53 *nmonitors = -1; 54 55 LockDisplay (dpy); 56 GetReq (RRGetMonitors, req); 57 req->reqType = info->codes->major_opcode; 58 req->randrReqType = X_RRGetMonitors; 59 req->window = window; 60 req->get_active = get_active; 61 62 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 63 { 64 UnlockDisplay (dpy); 65 SyncHandle (); 66 return NULL; 67 } 68 69 if (rep.length > INT_MAX >> 2 || 70 rep.nmonitors > INT_MAX / SIZEOF(xRRMonitorInfo) || 71 rep.noutputs > INT_MAX / 4 || 72 rep.nmonitors * SIZEOF(xRRMonitorInfo) > INT_MAX - rep.noutputs * 4) { 73 _XEatData (dpy, rep.length); 74 UnlockDisplay (dpy); 75 SyncHandle (); 76 return NULL; 77 } 78 nbytes = (long) rep.length << 2; 79 nmon = rep.nmonitors; 80 noutput = rep.noutputs; 81 nbytesRead = nmon * SIZEOF(xRRMonitorInfo) + noutput * 4; 82 83 if (nmon > 0) { 84 85 /* 86 * first we must compute how much space to allocate for 87 * randr library's use; we'll allocate the structures in a single 88 * allocation, on cleanlyness grounds. 89 */ 90 91 rbytes = nmon * sizeof (XRRMonitorInfo) + noutput * sizeof(RROutput); 92 93 buf = buf_head = Xmalloc (nbytesRead); 94 mon = Xmalloc (rbytes); 95 96 if (buf == NULL || mon == NULL) { 97 Xfree(buf); 98 Xfree(mon); 99 _XEatDataWords (dpy, rep.length); 100 UnlockDisplay (dpy); 101 SyncHandle (); 102 return NULL; 103 } 104 105 _XReadPad(dpy, buf, nbytesRead); 106 107 output = (RROutput *) (mon + nmon); 108 109 for (m = 0; m < nmon; m++) { 110 xmon = (xRRMonitorInfo *) buf; 111 mon[m].name = xmon->name; 112 mon[m].primary = xmon->primary; 113 mon[m].automatic = xmon->automatic; 114 mon[m].noutput = xmon->noutput; 115 mon[m].x = xmon->x; 116 mon[m].y = xmon->y; 117 mon[m].width = xmon->width; 118 mon[m].height = xmon->height; 119 mon[m].mwidth = xmon->widthInMillimeters; 120 mon[m].mheight = xmon->heightInMillimeters; 121 mon[m].outputs = output; 122 buf += SIZEOF (xRRMonitorInfo); 123 xoutput = (CARD32 *) buf; 124 if (xmon->noutput > rep.noutputs) { 125 Xfree(buf); 126 Xfree(mon); 127 UnlockDisplay (dpy); 128 SyncHandle (); 129 return NULL; 130 } 131 rep.noutputs -= xmon->noutput; 132 for (o = 0; o < xmon->noutput; o++) 133 output[o] = xoutput[o]; 134 output += xmon->noutput; 135 buf += xmon->noutput * 4; 136 } 137 Xfree(buf_head); 138 } 139 140 /* 141 * Skip any extra data 142 */ 143 if (nbytes > nbytesRead) 144 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 145 146 UnlockDisplay (dpy); 147 SyncHandle (); 148 149 *nmonitors = nmon; 150 return mon; 151} 152 153void 154XRRSetMonitor(Display *dpy, Window window, XRRMonitorInfo *monitor) 155{ 156 XExtDisplayInfo *info = XRRFindDisplay(dpy); 157 xRRSetMonitorReq *req; 158 159 RRSimpleCheckExtension (dpy, info); 160 161 LockDisplay(dpy); 162 GetReq (RRSetMonitor, req); 163 req->reqType = info->codes->major_opcode; 164 req->randrReqType = X_RRSetMonitor; 165 req->length += monitor->noutput; 166 req->window = window; 167 req->monitor.name = monitor->name; 168 req->monitor.primary = monitor->primary; 169 req->monitor.automatic = False; 170 req->monitor.noutput = monitor->noutput; 171 req->monitor.x = monitor->x; 172 req->monitor.y = monitor->y; 173 req->monitor.width = monitor->width; 174 req->monitor.height = monitor->height; 175 req->monitor.widthInMillimeters = monitor->mwidth; 176 req->monitor.heightInMillimeters = monitor->mheight; 177 Data32 (dpy, monitor->outputs, monitor->noutput * 4); 178 179 UnlockDisplay (dpy); 180 SyncHandle (); 181} 182 183void 184XRRDeleteMonitor(Display *dpy, Window window, Atom name) 185{ 186 XExtDisplayInfo *info = XRRFindDisplay(dpy); 187 xRRDeleteMonitorReq *req; 188 189 RRSimpleCheckExtension (dpy, info); 190 191 LockDisplay(dpy); 192 GetReq (RRDeleteMonitor, req); 193 req->reqType = info->codes->major_opcode; 194 req->randrReqType = X_RRDeleteMonitor; 195 req->window = window; 196 req->name = name; 197 UnlockDisplay (dpy); 198 SyncHandle (); 199} 200 201XRRMonitorInfo * 202XRRAllocateMonitor(Display *dpy, int noutput) 203{ 204 XRRMonitorInfo *monitor = calloc(1, sizeof (XRRMonitorInfo) + noutput * sizeof (RROutput)); 205 if (!monitor) 206 return NULL; 207 monitor->outputs = (RROutput *) (monitor + 1); 208 monitor->noutput = noutput; 209 return monitor; 210} 211 212void 213XRRFreeMonitors(XRRMonitorInfo *monitors) 214{ 215 Xfree(monitors); 216} 217 218