XrrMonitor.c revision 67594505
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 <stdio.h> 28#include <X11/Xlib.h> 29/* we need to be able to manipulate the Display structure on events */ 30#include <X11/Xlibint.h> 31#include <X11/extensions/render.h> 32#include <X11/extensions/Xrender.h> 33#include "Xrandrint.h" 34 35XRRMonitorInfo * 36XRRGetMonitors(Display *dpy, Window window, Bool get_active, int *nmonitors) 37{ 38 XExtDisplayInfo *info = XRRFindDisplay(dpy); 39 xRRGetMonitorsReply rep; 40 xRRGetMonitorsReq *req; 41 int nbytes, nbytesRead, rbytes; 42 int nmon, noutput; 43 int m, o; 44 char *buf, *buf_head; 45 xRRMonitorInfo *xmon; 46 CARD32 *xoutput; 47 XRRMonitorInfo *mon = NULL; 48 RROutput *output; 49 50 RRCheckExtension (dpy, info, NULL); 51 52 *nmonitors = -1; 53 54 LockDisplay (dpy); 55 GetReq (RRGetMonitors, req); 56 req->reqType = info->codes->major_opcode; 57 req->randrReqType = X_RRGetMonitors; 58 req->window = window; 59 req->get_active = get_active; 60 61 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 62 { 63 UnlockDisplay (dpy); 64 SyncHandle (); 65 return NULL; 66 } 67 68 nbytes = (long) rep.length << 2; 69 nmon = rep.nmonitors; 70 noutput = rep.noutputs; 71 nbytesRead = nmon * SIZEOF(xRRMonitorInfo) + noutput * 4; 72 73 if (nmon > 0) { 74 75 /* 76 * first we must compute how much space to allocate for 77 * randr library's use; we'll allocate the structures in a single 78 * allocation, on cleanlyness grounds. 79 */ 80 81 rbytes = nmon * sizeof (XRRMonitorInfo) + noutput * sizeof(RROutput); 82 83 buf = buf_head = Xmalloc (nbytesRead); 84 mon = Xmalloc (rbytes); 85 86 if (buf == NULL || mon == NULL) { 87 if (buf != NULL) Xfree(buf); 88 if (mon != NULL) Xfree(mon); 89 _XEatDataWords (dpy, rep.length); 90 UnlockDisplay (dpy); 91 SyncHandle (); 92 return NULL; 93 } 94 95 _XReadPad(dpy, buf, nbytesRead); 96 97 output = (RROutput *) (mon + nmon); 98 99 for (m = 0; m < nmon; m++) { 100 xmon = (xRRMonitorInfo *) buf; 101 mon[m].name = xmon->name; 102 mon[m].primary = xmon->primary; 103 mon[m].automatic = xmon->automatic; 104 mon[m].noutput = xmon->noutput; 105 mon[m].x = xmon->x; 106 mon[m].y = xmon->y; 107 mon[m].width = xmon->width; 108 mon[m].height = xmon->height; 109 mon[m].mwidth = xmon->widthInMillimeters; 110 mon[m].mheight = xmon->heightInMillimeters; 111 mon[m].outputs = output; 112 buf += SIZEOF (xRRMonitorInfo); 113 xoutput = (CARD32 *) buf; 114 for (o = 0; o < xmon->noutput; o++) 115 output[o] = xoutput[o]; 116 output += xmon->noutput; 117 buf += xmon->noutput * 4; 118 } 119 Xfree(buf_head); 120 } 121 122 /* 123 * Skip any extra data 124 */ 125 if (nbytes > nbytesRead) 126 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 127 128 UnlockDisplay (dpy); 129 SyncHandle (); 130 131 *nmonitors = nmon; 132 return mon; 133} 134 135void 136XRRSetMonitor(Display *dpy, Window window, XRRMonitorInfo *monitor) 137{ 138 XExtDisplayInfo *info = XRRFindDisplay(dpy); 139 xRRSetMonitorReq *req; 140 141 RRSimpleCheckExtension (dpy, info); 142 143 LockDisplay(dpy); 144 GetReq (RRSetMonitor, req); 145 req->reqType = info->codes->major_opcode; 146 req->randrReqType = X_RRSetMonitor; 147 req->length += monitor->noutput; 148 req->window = window; 149 req->monitor.name = monitor->name; 150 req->monitor.primary = monitor->primary; 151 req->monitor.automatic = False; 152 req->monitor.noutput = monitor->noutput; 153 req->monitor.x = monitor->x; 154 req->monitor.y = monitor->y; 155 req->monitor.width = monitor->width; 156 req->monitor.height = monitor->height; 157 req->monitor.widthInMillimeters = monitor->mwidth; 158 req->monitor.heightInMillimeters = monitor->mheight; 159 Data32 (dpy, monitor->outputs, monitor->noutput * 4); 160 161 UnlockDisplay (dpy); 162 SyncHandle (); 163} 164 165void 166XRRDeleteMonitor(Display *dpy, Window window, Atom name) 167{ 168 XExtDisplayInfo *info = XRRFindDisplay(dpy); 169 xRRDeleteMonitorReq *req; 170 171 RRSimpleCheckExtension (dpy, info); 172 173 LockDisplay(dpy); 174 GetReq (RRDeleteMonitor, req); 175 req->reqType = info->codes->major_opcode; 176 req->randrReqType = X_RRDeleteMonitor; 177 req->window = window; 178 req->name = name; 179 UnlockDisplay (dpy); 180 SyncHandle (); 181} 182 183XRRMonitorInfo * 184XRRAllocateMonitor(Display *dpy, int noutput) 185{ 186 XRRMonitorInfo *monitor = calloc(1, sizeof (XRRMonitorInfo) + noutput * sizeof (RROutput)); 187 if (!monitor) 188 return NULL; 189 monitor->outputs = (RROutput *) (monitor + 1); 190 monitor->noutput = noutput; 191 return monitor; 192} 193 194void 195XRRFreeMonitors(XRRMonitorInfo *monitors) 196{ 197 if (monitors) 198 Xfree(monitors); 199} 200 201