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