1 /***************************************************************** 2 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 3 Permission is hereby granted, free of charge, to any person obtaining a copy 4 of this software and associated documentation files (the "Software"), to deal 5 in the Software without restriction, including without limitation the rights 6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 copies of the Software. 8 9 The above copyright notice and this permission notice shall be included in 10 all copies or substantial portions of the Software. 11 12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 16 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 17 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 18 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 20 Except as contained in this notice, the name of Digital Equipment Corporation 21 shall not be used in advertising or otherwise to promote the sale, use or other 22 dealings in this Software without prior written authorization from Digital 23 Equipment 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 38 static XExtensionInfo _panoramiX_ext_info_data; 39 static XExtensionInfo *panoramiX_ext_info = &_panoramiX_ext_info_data; 40 static 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 47 static int close_display(Display *dpy, XExtCodes *codes); 48 49 static /* 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 63 static XEXT_GENERATE_FIND_DISPLAY (find_display, panoramiX_ext_info, 64 panoramiX_extension_name, 65 &panoramiX_extension_hooks, 66 0, NULL) 67 68 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, panoramiX_ext_info) 69 70 71 72 /**************************************************************************** 73 * * 74 * PanoramiX public interfaces * 75 * * 76 ****************************************************************************/ 77 78 Bool 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 96 Status 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 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 126 XPanoramiXInfo *XPanoramiXAllocInfo(void) 127 { 128 return (XPanoramiXInfo *) Xmalloc (sizeof (XPanoramiXInfo)); 129 } 130 131 Status XPanoramiXGetState ( 132 Display *dpy, 133 Drawable drawable, 134 XPanoramiXInfo *panoramiX_info 135 ) 136 { 137 XExtDisplayInfo *info = find_display (dpy); 138 xPanoramiXGetStateReply rep; 139 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 160 Status XPanoramiXGetScreenCount ( 161 Display *dpy, 162 Drawable drawable, 163 XPanoramiXInfo *panoramiX_info 164 ) 165 { 166 XExtDisplayInfo *info = find_display (dpy); 167 xPanoramiXGetScreenCountReply rep; 168 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 189 Status 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 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 228 Bool 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 237 Status XineramaQueryVersion( 238 Display *dpy, 239 int *major, 240 int *minor 241 ) 242 { 243 return XPanoramiXQueryVersion(dpy, major, minor); 244 } 245 246 Bool 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 269 XineramaScreenInfo * 270 XineramaQueryScreens( 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 CARD32 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