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