Xinerama.c revision ee424013
1/*****************************************************************
2Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software.
8
9The above copyright notice and this permission notice shall be included in
10all copies or substantial portions of the Software.
11
12THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
15DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
16BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
17WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
18IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20Except as contained in this notice, the name of Digital Equipment Corporation
21shall not be used in advertising or otherwise to promote the sale, use or other
22dealings in this Software without prior written authorization from Digital
23Equipment Corporation.
24******************************************************************/
25
26#ifdef HAVE_CONFIG_H
27# include "config.h"
28#endif
29
30#include <X11/Xlibint.h>
31#include <X11/Xutil.h>
32#include <X11/extensions/Xext.h>
33#include <X11/extensions/extutil.h>
34#include <X11/extensions/panoramiXext.h>
35#include <X11/extensions/panoramiXproto.h>
36#include <X11/extensions/Xinerama.h>
37
38static XExtensionInfo _panoramiX_ext_info_data;
39static XExtensionInfo *panoramiX_ext_info = &_panoramiX_ext_info_data;
40static const char *panoramiX_extension_name = PANORAMIX_PROTOCOL_NAME;
41
42#define PanoramiXCheckExtension(dpy,i,val) \
43  XextCheckExtension (dpy, i, panoramiX_extension_name, val)
44#define PanoramiXSimpleCheckExtension(dpy,i) \
45  XextSimpleCheckExtension (dpy, i, panoramiX_extension_name)
46
47static int close_display(Display *dpy, XExtCodes *codes);
48
49static /* const */ XExtensionHooks panoramiX_extension_hooks = {
50    NULL,				/* create_gc */
51    NULL,				/* copy_gc */
52    NULL,				/* flush_gc */
53    NULL,				/* free_gc */
54    NULL,				/* create_font */
55    NULL,				/* free_font */
56    close_display,			/* close_display */
57    NULL,				/* wire_to_event */
58    NULL,				/* event_to_wire */
59    NULL,				/* error */
60    NULL,				/* error_string */
61};
62
63static XEXT_GENERATE_FIND_DISPLAY (find_display, panoramiX_ext_info,
64				   panoramiX_extension_name,
65				   &panoramiX_extension_hooks,
66				   0, NULL)
67
68static XEXT_GENERATE_CLOSE_DISPLAY (close_display, panoramiX_ext_info)
69
70
71
72/****************************************************************************
73 *                                                                          *
74 *			    PanoramiX public interfaces                         *
75 *                                                                          *
76 ****************************************************************************/
77
78Bool XPanoramiXQueryExtension (
79    Display *dpy,
80    int *event_base_return,
81    int *error_base_return
82)
83{
84    XExtDisplayInfo *info = find_display (dpy);
85
86    if (XextHasExtension(info)) {
87	*event_base_return = info->codes->first_event;
88	*error_base_return = info->codes->first_error;
89	return True;
90    } else {
91	return False;
92    }
93}
94
95
96Status XPanoramiXQueryVersion(
97    Display *dpy,
98    int     *major_version_return,
99    int     *minor_version_return
100)
101{
102    XExtDisplayInfo *info = find_display (dpy);
103    xPanoramiXQueryVersionReply	    rep;
104    register xPanoramiXQueryVersionReq  *req;
105
106    PanoramiXCheckExtension (dpy, info, 0);
107
108    LockDisplay (dpy);
109    GetReq (PanoramiXQueryVersion, req);
110    req->reqType = info->codes->major_opcode;
111    req->panoramiXReqType = X_PanoramiXQueryVersion;
112    req->clientMajor = PANORAMIX_MAJOR_VERSION;
113    req->clientMinor = PANORAMIX_MINOR_VERSION;
114    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
115	UnlockDisplay (dpy);
116	SyncHandle ();
117	return 0;
118    }
119    *major_version_return = rep.majorVersion;
120    *minor_version_return = rep.minorVersion;
121    UnlockDisplay (dpy);
122    SyncHandle ();
123    return 1;
124}
125
126XPanoramiXInfo *XPanoramiXAllocInfo(void)
127{
128	return (XPanoramiXInfo *) Xmalloc (sizeof (XPanoramiXInfo));
129}
130
131Status XPanoramiXGetState (
132    Display		*dpy,
133    Drawable		drawable,
134    XPanoramiXInfo	*panoramiX_info
135)
136{
137    XExtDisplayInfo			*info = find_display (dpy);
138    xPanoramiXGetStateReply	rep;
139    register xPanoramiXGetStateReq	*req;
140
141    PanoramiXCheckExtension (dpy, info, 0);
142
143    LockDisplay (dpy);
144    GetReq (PanoramiXGetState, req);
145    req->reqType = info->codes->major_opcode;
146    req->panoramiXReqType = X_PanoramiXGetState;
147    req->window = drawable;
148    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
149	UnlockDisplay (dpy);
150	SyncHandle ();
151	return 0;
152    }
153    UnlockDisplay (dpy);
154    SyncHandle ();
155    panoramiX_info->window = rep.window;
156    panoramiX_info->State = rep.state;
157    return 1;
158}
159
160Status XPanoramiXGetScreenCount (
161    Display		*dpy,
162    Drawable		drawable,
163    XPanoramiXInfo	*panoramiX_info
164)
165{
166    XExtDisplayInfo			*info = find_display (dpy);
167    xPanoramiXGetScreenCountReply	rep;
168    register xPanoramiXGetScreenCountReq	*req;
169
170    PanoramiXCheckExtension (dpy, info, 0);
171
172    LockDisplay (dpy);
173    GetReq (PanoramiXGetScreenCount, req);
174    req->reqType = info->codes->major_opcode;
175    req->panoramiXReqType = X_PanoramiXGetScreenCount;
176    req->window = drawable;
177    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
178	UnlockDisplay (dpy);
179	SyncHandle ();
180	return 0;
181    }
182    UnlockDisplay (dpy);
183    SyncHandle ();
184    panoramiX_info->window = rep.window;
185    panoramiX_info->ScreenCount = rep.ScreenCount;
186    return 1;
187}
188
189Status XPanoramiXGetScreenSize (
190    Display		*dpy,
191    Drawable		drawable,
192    int			screen_num,
193    XPanoramiXInfo	*panoramiX_info
194)
195{
196    XExtDisplayInfo			*info = find_display (dpy);
197    xPanoramiXGetScreenSizeReply	rep;
198    register xPanoramiXGetScreenSizeReq	*req;
199
200    PanoramiXCheckExtension (dpy, info, 0);
201
202    LockDisplay (dpy);
203    GetReq (PanoramiXGetScreenSize, req);
204    req->reqType = info->codes->major_opcode;
205    req->panoramiXReqType = X_PanoramiXGetScreenSize;
206    req->window = drawable;
207    req->screen = screen_num;			/* need to define */
208    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
209	UnlockDisplay (dpy);
210	SyncHandle ();
211	return 0;
212    }
213    UnlockDisplay (dpy);
214    SyncHandle ();
215    panoramiX_info->window = rep.window;
216    panoramiX_info->screen = rep.screen;
217    panoramiX_info->width =  rep.width;
218    panoramiX_info->height = rep.height;
219    return 1;
220}
221
222/*******************************************************************\
223  Alternate interface to make up for shortcomings in the original,
224  namely, the omission of the screen origin.  The new interface is
225  in the "Xinerama" namespace instead of "PanoramiX".
226\*******************************************************************/
227
228Bool XineramaQueryExtension (
229   Display *dpy,
230   int     *event_base_return,
231   int     *error_base_return
232)
233{
234   return XPanoramiXQueryExtension(dpy, event_base_return, error_base_return);
235}
236
237Status XineramaQueryVersion(
238   Display *dpy,
239   int     *major,
240   int     *minor
241)
242{
243   return XPanoramiXQueryVersion(dpy, major, minor);
244}
245
246Bool XineramaIsActive(Display *dpy)
247{
248    xXineramaIsActiveReply	rep;
249    xXineramaIsActiveReq  	*req;
250    XExtDisplayInfo 		*info = find_display (dpy);
251
252    if(!XextHasExtension(info))
253	return False;  /* server doesn't even have the extension */
254
255    LockDisplay (dpy);
256    GetReq (XineramaIsActive, req);
257    req->reqType = info->codes->major_opcode;
258    req->panoramiXReqType = X_XineramaIsActive;
259    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
260	UnlockDisplay (dpy);
261	SyncHandle ();
262	return False;
263    }
264    UnlockDisplay (dpy);
265    SyncHandle ();
266    return rep.state;
267}
268
269XineramaScreenInfo *
270XineramaQueryScreens(
271   Display *dpy,
272   int     *number
273)
274{
275    XExtDisplayInfo		*info = find_display (dpy);
276    xXineramaQueryScreensReply	rep;
277    xXineramaQueryScreensReq	*req;
278    XineramaScreenInfo		*scrnInfo = NULL;
279
280    PanoramiXCheckExtension (dpy, info, NULL);
281
282    LockDisplay (dpy);
283    GetReq (XineramaQueryScreens, req);
284    req->reqType = info->codes->major_opcode;
285    req->panoramiXReqType = X_XineramaQueryScreens;
286    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
287	UnlockDisplay (dpy);
288	SyncHandle ();
289	*number = 0;
290	return NULL;
291    }
292
293    /*
294     * rep.number is a CARD32 so could be as large as 2^32
295     * The X11 protocol limits the total screen size to 64k x 64k,
296     * and no screen can be smaller than a pixel.  While technically
297     * that means we could theoretically reach 2^32 screens, and that's
298     * not even taking overlap into account, Xorg is currently limited
299     * to 16 screens, and few known servers have a much higher limit,
300     * so 1024 seems more than enough to prevent both integer overflow
301     * and insane X server responses causing massive memory allocation.
302     */
303    if ((rep.number > 0) && (rep.number <= 1024))
304	scrnInfo = Xmalloc(sizeof(XineramaScreenInfo) * rep.number);
305    if (scrnInfo != NULL) {
306	int i;
307
308	for (i = 0; i < rep.number; i++) {
309	    xXineramaScreenInfo scratch;
310
311	    _XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo);
312
313	    scrnInfo[i].screen_number = i;
314	    scrnInfo[i].x_org	= scratch.x_org;
315	    scrnInfo[i].y_org	= scratch.y_org;
316	    scrnInfo[i].width	= scratch.width;
317	    scrnInfo[i].height	= scratch.height;
318	}
319
320	*number = rep.number;
321    } else {
322	_XEatDataWords(dpy, rep.length);
323	*number = 0;
324    }
325
326    UnlockDisplay (dpy);
327    SyncHandle ();
328    return scrnInfo;
329}
330