open-src/lib/libXext/sun-src/src/XPanoramiX.c
changeset 366 7b72d11c8c92
child 919 425233ae7236
equal deleted inserted replaced
365:7b1fa8e8728b 366:7b72d11c8c92
       
     1 /* $TOG: XPanoramiX.c /main/2 1997/11/16 08:45:41 kaleb $ */
       
     2 /*****************************************************************
       
     3 
       
     4 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
       
     5 
       
     6 Permission is hereby granted, free of charge, to any person obtaining a copy
       
     7 of this software and associated documentation files (the "Software"), to deal
       
     8 in the Software without restriction, including without limitation the rights
       
     9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    10 copies of the Software.
       
    11 
       
    12 The above copyright notice and this permission notice shall be included in
       
    13 all copies or substantial portions of the Software.
       
    14 
       
    15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
       
    18 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 
       
    19 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 
       
    20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 
       
    21 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
    22 
       
    23 Except as contained in this notice, the name of Digital Equipment Corporation 
       
    24 shall not be used in advertising or otherwise to promote the sale, use or other
       
    25 dealings in this Software without prior written authorization from Digital 
       
    26 Equipment Corporation.
       
    27 
       
    28 ******************************************************************/
       
    29 /* Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
       
    30  *
       
    31  * Permission is hereby granted, free of charge, to any person obtaining a
       
    32  * copy of this software and associated documentation files (the
       
    33  * "Software"), to deal in the Software without restriction, including
       
    34  * without limitation the rights to use, copy, modify, merge, publish,
       
    35  * distribute, and/or sell copies of the Software, and to permit persons
       
    36  * to whom the Software is furnished to do so, provided that the above
       
    37  * copyright notice(s) and this permission notice appear in all copies of
       
    38  * the Software and that both the above copyright notice(s) and this
       
    39  * permission notice appear in supporting documentation.
       
    40  *
       
    41  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
       
    42  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    43  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
       
    44  * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
       
    45  * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
       
    46  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
       
    47  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
       
    48  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
       
    49  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
       
    50  *
       
    51  * Except as contained in this notice, the name of a copyright holder
       
    52  * shall not be used in advertising or otherwise to promote the sale, use
       
    53  * or other dealings in this Software without prior written authorization
       
    54  * of the copyright holder.
       
    55  */
       
    56 
       
    57 #define NEED_EVENTS
       
    58 #define NEED_REPLIES
       
    59 #include <X11/Xlibint.h>
       
    60 #include <X11/Xutil.h>
       
    61 #include <X11/Xresource.h>
       
    62 #include <X11/extensions/Xext.h>
       
    63 #include <X11/extensions/extutil.h>
       
    64 #include <X11/extensions/panoramiXext.h>
       
    65 #include <X11/extensions/panoramiXproto.h>
       
    66 #include <X11/extensions/xinerama.h>
       
    67 
       
    68 Bool XGetXineramaInfo(Display *dpy, int screen_number, XID VirtualWID, XineramaInfo *info);
       
    69 
       
    70 static XExtensionInfo _panoramiX_ext_info_data;
       
    71 static XExtensionInfo *panoramiX_ext_info = &_panoramiX_ext_info_data;
       
    72 static /* const */ char *panoramiX_extension_name = PANORAMIX_PROTOCOL_NAME;
       
    73 
       
    74 #define PanoramiXCheckExtension(dpy,i,val) \
       
    75   XextCheckExtension (dpy, i, panoramiX_extension_name, val)
       
    76 #define PanoramiXSimpleCheckExtension(dpy,i) \
       
    77   XextSimpleCheckExtension (dpy, i, panoramiX_extension_name)
       
    78 
       
    79 static int close_display();
       
    80 static Bool wire_to_event();
       
    81 static Status event_to_wire();
       
    82 static /* const */ XExtensionHooks panoramiX_extension_hooks = {
       
    83     NULL,				/* create_gc */
       
    84     NULL,				/* copy_gc */
       
    85     NULL,				/* flush_gc */
       
    86     NULL,				/* free_gc */
       
    87     NULL,				/* create_font */
       
    88     NULL,				/* free_font */
       
    89     close_display,			/* close_display */
       
    90     NULL,				/* wire_to_event */
       
    91     NULL,				/* event_to_wire */
       
    92     NULL,				/* error */
       
    93     NULL,				/* error_string */
       
    94 };
       
    95 
       
    96 static XEXT_GENERATE_FIND_DISPLAY (find_display, panoramiX_ext_info,
       
    97 				   panoramiX_extension_name, 
       
    98 				   &panoramiX_extension_hooks,
       
    99 				   0, NULL)
       
   100 
       
   101 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, panoramiX_ext_info)
       
   102 
       
   103 
       
   104 
       
   105 #ifdef SUNSOFT
       
   106 struct XineramaExtVersionInfo
       
   107 {
       
   108     int major_vers, minor_vers;
       
   109 };
       
   110 
       
   111 /**** Code taken from xc/include/extensions/Xinerama.h in Xorg for
       
   112       compatibility with XFree86 & Xorg protocols ****/
       
   113 
       
   114 static Bool XineramaIsActive(Display *dpy);
       
   115 
       
   116 /* 
       
   117    Returns the number of heads and a pointer to an array of
       
   118    structures describing the position and size of the individual
       
   119    heads.  Returns NULL and number = 0 if Xinerama is not active.
       
   120   
       
   121    Returned array should be freed with XFree().
       
   122 */
       
   123 typedef struct {
       
   124    int   screen_number;
       
   125    short x_org;
       
   126    short y_org;
       
   127    short width;
       
   128    short height;
       
   129 } XineramaScreenInfo;
       
   130 
       
   131 static XineramaScreenInfo * 
       
   132 XineramaQueryScreens(
       
   133    Display *dpy,
       
   134    int     *number
       
   135 );
       
   136 
       
   137 #endif
       
   138 
       
   139 /****************************************************************************
       
   140  *                                                                          *
       
   141  *			    PanoramiX public interfaces                         *
       
   142  *                                                                          *
       
   143  ****************************************************************************/
       
   144 
       
   145 Bool XPanoramiXQueryExtension (dpy, event_basep, error_basep)
       
   146     Display *dpy;
       
   147     int *event_basep, *error_basep;
       
   148 {
       
   149     XExtDisplayInfo *info = find_display (dpy);
       
   150 
       
   151     if (XextHasExtension(info)) {
       
   152 	*event_basep = info->codes->first_event;
       
   153 	*error_basep = info->codes->first_error;
       
   154 	return True;
       
   155     } else {
       
   156 	return False;
       
   157     }
       
   158 }
       
   159 
       
   160 
       
   161 Status XPanoramiXQueryVersion(dpy, major_versionp, minor_versionp)
       
   162     Display *dpy;
       
   163     int	    *major_versionp, *minor_versionp;
       
   164 {
       
   165     XExtDisplayInfo *info = find_display (dpy);
       
   166     xPanoramiXQueryVersionReply	    rep;
       
   167     register xPanoramiXQueryVersionReq  *req;
       
   168 
       
   169 #ifdef SUNSOFT
       
   170     struct XineramaExtVersionInfo	*vinfo;
       
   171 
       
   172     if (info->data != NULL) {
       
   173 	vinfo = (struct XineramaExtVersionInfo *) info->data;
       
   174 	
       
   175 	*major_versionp = vinfo->major_vers;	
       
   176 	*minor_versionp = vinfo->minor_vers;
       
   177 	return 1;	
       
   178     }
       
   179 #endif
       
   180     
       
   181     PanoramiXCheckExtension (dpy, info, 0);
       
   182 
       
   183     LockDisplay (dpy);
       
   184     GetReq (PanoramiXQueryVersion, req);
       
   185     req->reqType = info->codes->major_opcode;
       
   186     req->panoramiXReqType = X_PanoramiXQueryVersion;
       
   187     req->clientMajor = PANORAMIX_MAJOR_VERSION;
       
   188     req->clientMinor = PANORAMIX_MINOR_VERSION;
       
   189     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
       
   190 	UnlockDisplay (dpy);
       
   191 	SyncHandle ();
       
   192 	return 0;
       
   193     }
       
   194     *major_versionp = rep.majorVersion;
       
   195     *minor_versionp = rep.minorVersion;
       
   196 #ifdef SUNSOFT /* Cache version info */
       
   197     vinfo = Xmalloc(sizeof(struct XineramaExtVersionInfo));
       
   198 
       
   199     if (vinfo != NULL) {
       
   200 	vinfo->major_vers = rep.majorVersion;
       
   201 	vinfo->minor_vers = rep.minorVersion;
       
   202 	info->data = (XPointer) vinfo;
       
   203     }
       
   204 #endif    
       
   205     UnlockDisplay (dpy);
       
   206     SyncHandle ();
       
   207     return 1;
       
   208 }
       
   209 
       
   210 XPanoramiXInfo *XPanoramiXAllocInfo()
       
   211 {
       
   212 	return (XPanoramiXInfo *) Xmalloc (sizeof (XPanoramiXInfo));
       
   213 }
       
   214 
       
   215 Status XPanoramiXGetState (dpy, drawable, panoramiX_info)
       
   216     Display		*dpy;
       
   217     Drawable		drawable;
       
   218     XPanoramiXInfo	*panoramiX_info	;
       
   219 {
       
   220     XExtDisplayInfo			*info = find_display (dpy);
       
   221     xPanoramiXGetStateReply	rep;
       
   222     register xPanoramiXGetStateReq	*req;
       
   223 
       
   224     PanoramiXCheckExtension (dpy, info, 0);
       
   225 
       
   226     LockDisplay (dpy);
       
   227     GetReq (PanoramiXGetState, req);
       
   228     req->reqType = info->codes->major_opcode;
       
   229     req->panoramiXReqType = X_PanoramiXGetState;
       
   230     req->window = drawable;
       
   231     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
       
   232 	UnlockDisplay (dpy);
       
   233 	SyncHandle ();
       
   234 	return 0;
       
   235     }
       
   236     UnlockDisplay (dpy);
       
   237     SyncHandle ();
       
   238     panoramiX_info->window = rep.window;
       
   239     panoramiX_info->State = rep.state;
       
   240     return 1;
       
   241 }
       
   242 
       
   243 Status XPanoramiXGetScreenCount (dpy, drawable, panoramiX_info)
       
   244     Display		*dpy;
       
   245     Drawable		drawable;
       
   246     XPanoramiXInfo	*panoramiX_info	;
       
   247 {
       
   248     XExtDisplayInfo			*info = find_display (dpy);
       
   249     xPanoramiXGetScreenCountReply	rep;
       
   250     register xPanoramiXGetScreenCountReq	*req;
       
   251 
       
   252     PanoramiXCheckExtension (dpy, info, 0);
       
   253 
       
   254     LockDisplay (dpy);
       
   255     GetReq (PanoramiXGetScreenCount, req);
       
   256     req->reqType = info->codes->major_opcode;
       
   257     req->panoramiXReqType = X_PanoramiXGetScreenCount;
       
   258     req->window = drawable;
       
   259     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
       
   260 	UnlockDisplay (dpy);
       
   261 	SyncHandle ();
       
   262 	return 0;
       
   263     }
       
   264     UnlockDisplay (dpy);
       
   265     SyncHandle ();
       
   266     panoramiX_info->window = rep.window;
       
   267     panoramiX_info->ScreenCount = rep.ScreenCount;
       
   268     return 1;
       
   269 }
       
   270 
       
   271 Status XPanoramiXGetScreenSize (dpy, drawable, screen_num, panoramiX_info)
       
   272     Display		*dpy;
       
   273     Drawable		drawable;
       
   274     int			screen_num;
       
   275     XPanoramiXInfo	*panoramiX_info	;
       
   276 {
       
   277     XExtDisplayInfo			*info = find_display (dpy);
       
   278     xPanoramiXGetScreenSizeReply	rep;
       
   279     register xPanoramiXGetScreenSizeReq	*req;
       
   280 
       
   281     PanoramiXCheckExtension (dpy, info, 0);
       
   282 
       
   283     LockDisplay (dpy);
       
   284     GetReq (PanoramiXGetScreenSize, req);
       
   285     req->reqType = info->codes->major_opcode;
       
   286     req->panoramiXReqType = X_PanoramiXGetScreenSize;
       
   287     req->window = drawable;
       
   288     req->screen = screen_num;			/* need to define */ 
       
   289     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
       
   290 	UnlockDisplay (dpy);
       
   291 	SyncHandle ();
       
   292 	return 0;
       
   293     }
       
   294     UnlockDisplay (dpy);
       
   295     SyncHandle ();
       
   296     panoramiX_info->window = rep.window;
       
   297     panoramiX_info->screen = rep.screen;
       
   298     panoramiX_info->width =  rep.width;
       
   299     panoramiX_info->height = rep.height;
       
   300     return 1;
       
   301 }
       
   302 
       
   303 
       
   304 /* new api for xinerama */
       
   305 
       
   306 Bool XineramaGetState(Display * display, int screen_number)
       
   307 {
       
   308     XExtDisplayInfo	 *info = find_display (display);
       
   309 
       
   310     /* screen_number may seem like hyper-bogus stuff, but:
       
   311        it may be possible to have 2 xinerama screen sets on
       
   312        one server */
       
   313 
       
   314     if(screen_number) 
       
   315 	return False;  /* no no, must say zero */
       
   316 
       
   317     if(!XextHasExtension(info)) 
       
   318 	return False;
       
   319     else
       
   320     {
       
   321 	int maj, min;
       
   322 
       
   323 	if (XPanoramiXQueryVersion(display, &maj, &min) == 0) {
       
   324 	    return False;
       
   325 	}
       
   326 	if ((maj == 1) && (min >= 0)) {
       
   327 	    return XineramaIsActive(display);
       
   328 	} else {
       
   329     	    return True; /* can't check in 1.0 protocol */
       
   330 	}
       
   331     }
       
   332 }
       
   333 
       
   334 Status XineramaGetInfo(Display * display, int screen_number, XRectangle *
       
   335 	framebuffer_rects, unsigned char * framebuffer_hints, int *
       
   336 	num_framebuffers )
       
   337 
       
   338 {
       
   339     int	framebuffercount;	/* number of fb's we know about */
       
   340     int	i;			/* fortran */
       
   341     Window	win;
       
   342     int x = 0, y = 0;
       
   343     int maj, min;
       
   344     
       
   345     if(!XineramaGetState(display, screen_number))
       
   346 	return 0;
       
   347 
       
   348     if (XPanoramiXQueryVersion(display, &maj, &min) == 0) {
       
   349 	return 0;
       
   350     }
       
   351     if ((maj == 1) && (min >= 0)) {
       
   352 	/* Use XFree86/Xorg extended protocol */
       
   353 	XineramaScreenInfo	*xsi;
       
   354 
       
   355 	xsi = XineramaQueryScreens(display, &framebuffercount);
       
   356 	if (xsi == NULL || framebuffercount == 0) {
       
   357 	    return 0;
       
   358 	}
       
   359 	for (i = 0; i < framebuffercount ; i++) {
       
   360 	    framebuffer_rects[i].x 	= xsi[i].x_org;
       
   361 	    framebuffer_rects[i].y 	= xsi[i].y_org;
       
   362 	    framebuffer_rects[i].width 	= xsi[i].width;
       
   363 	    framebuffer_rects[i].height = xsi[i].height;
       
   364 	}
       
   365 	XFree(xsi);
       
   366     } else {
       
   367 	/* Use Sun extended protocol */
       
   368 	XPanoramiXInfo	panoramiX_info;	
       
   369 	XineramaInfo *info;		/* list of screen x,y etc */
       
   370 
       
   371 	/* get the count of screens that we need to know about 
       
   372 	   NOTE:  screen_number implies a set of fb's for this
       
   373 	   working surface */
       
   374 
       
   375 	win = 0;
       
   376 
       
   377 	XPanoramiXGetScreenCount(display, win, &panoramiX_info);
       
   378     
       
   379 	if(!panoramiX_info.ScreenCount) {
       
   380 	    return 0;
       
   381 	}
       
   382 	framebuffercount = panoramiX_info.ScreenCount;
       
   383     
       
   384 	/* Make sure not to overflow buffers if X server has more screens
       
   385 	   than we expect */
       
   386 	if (framebuffercount > MAXSCREEN)
       
   387 	    framebuffercount = MAXSCREEN;
       
   388 
       
   389 	info = malloc(sizeof(XineramaInfo));
       
   390     
       
   391 	if(!info)
       
   392 	    return 0;
       
   393 
       
   394 	/* now read the servers list of frame buffers */
       
   395 
       
   396 	if(!XGetXineramaInfo(display,screen_number, 
       
   397 		(XID)	RootWindow(display,screen_number),info))
       
   398 	{
       
   399 		free(info);
       
   400 		return 0;
       
   401 	}
       
   402 
       
   403 
       
   404 	for(i = 0; i < framebuffercount; i++)
       
   405 	{
       
   406 		framebuffer_rects[i].x = info->subs[i].dx;
       
   407 		framebuffer_rects[i].y = info->subs[i].dy;
       
   408 		framebuffer_rects[i].width = info->subs[i].wdx;
       
   409 		framebuffer_rects[i].height = info->subs[i].wdy;
       
   410 	}
       
   411 
       
   412 	free(info);
       
   413     }
       
   414 
       
   415     *num_framebuffers = framebuffercount;
       
   416     
       
   417     /* assume the start up and list are in the same order */
       
   418 
       
   419     for(i = 0; i < framebuffercount; i++)
       
   420     {
       
   421 	framebuffer_hints[i] = 0;
       
   422 	if (i > 0) 	/* fb0 never gets a hint */
       
   423 	{
       
   424 	    if (framebuffer_rects[i].x > x) { 		/* right */
       
   425 		if (framebuffer_rects[i].y == y)
       
   426 		    framebuffer_hints[i] = XINERAMA_PLACE_RIGHT;
       
   427 	    }
       
   428 	    else if (framebuffer_rects[i].x == x) {	/* up/down */
       
   429 		if (framebuffer_rects[i].y > y)
       
   430 		    framebuffer_hints[i] = XINERAMA_PLACE_TOP;
       
   431 		else if (framebuffer_rects[i].y < y)
       
   432 		    framebuffer_hints[i] = XINERAMA_PLACE_BOTTOM;
       
   433 	    } else if (framebuffer_rects[i].x < x) {	/* left */
       
   434 		if (framebuffer_rects[i].y == y)
       
   435 		    framebuffer_hints[i] = XINERAMA_PLACE_LEFT;
       
   436 	    }
       
   437 	}
       
   438 	x = framebuffer_rects[i].x;
       
   439 	y = framebuffer_rects[i].y;
       
   440 
       
   441     }
       
   442     return framebuffercount;
       
   443 }
       
   444 
       
   445 Bool
       
   446 XGetXineramaInfo(Display *dpy ,int  screen_number,XID VirtualWID,XineramaInfo *info )
       
   447 {
       
   448     xXineramaInfoReq 	*req;
       
   449     xXineramaInfoReply 	*rep;
       
   450     XExtDisplayInfo *Extinfo = find_display (dpy);
       
   451 
       
   452     if(!XineramaGetState(dpy, screen_number))
       
   453 	return False;
       
   454 
       
   455     rep = malloc(sizeof(xXineramaInfoReply));
       
   456 
       
   457     LockDisplay(dpy);
       
   458     GetReq(XineramaInfo, req);
       
   459     req->reqType = Extinfo->codes->major_opcode;
       
   460     req->xXineramaReqType = X_XineramaInfo;
       
   461     req->visual = VirtualWID;
       
   462 
       
   463     if (!_XReply(dpy, (xReply *)rep, (sizeof(xXineramaInfoReply)-32) >> 2
       
   464 ,
       
   465         xFalse))
       
   466     {
       
   467         UnlockDisplay(dpy);
       
   468         SyncHandle();
       
   469         Xfree(rep);
       
   470         return NULL;
       
   471     }
       
   472     info->wid = VirtualWID;
       
   473     memcpy(&info->subs[0],&rep->subs[0],(MAXSCREEN-1) * sizeof(SubWID));
       
   474     UnlockDisplay(dpy);
       
   475     SyncHandle();
       
   476     free(rep);
       
   477     return 1;
       
   478 }
       
   479 
       
   480 Status XineramaGetCenterHint(Display* display, int screen_number,
       
   481 				int* xret, int* yret)
       
   482 {
       
   483    int x = -1;
       
   484    int y = -1;
       
   485    int fb = -1;
       
   486    int fbs;
       
   487    XrmDatabase xrdb;
       
   488    XrmValue value;
       
   489    char* vtype;
       
   490    char buffer[20];
       
   491    XRectangle rects[MAXSCREEN];
       
   492    unsigned char hints[MAXSCREEN];
       
   493    Bool xiGetState, xiGetInfo;
       
   494    long n;
       
   495     
       
   496 
       
   497    if (screen_number)
       
   498       return 0;  /* don't yet support multiple Xinerama screens */
       
   499 
       
   500    xiGetState = XineramaGetState(display, screen_number);
       
   501    xiGetInfo = XineramaGetInfo(display, screen_number, rects, hints, &fbs);
       
   502 
       
   503    if (xrdb = XrmGetDatabase(display))
       
   504    {
       
   505       if (XrmGetResource(xrdb, "xineramaDefaultFramebuffer",
       
   506 		"XineramaDefaultFramebuffer", &vtype, &value))
       
   507       {
       
   508 	  if (value.size < sizeof(buffer)) {
       
   509 	      strncpy(buffer, value.addr, value.size);
       
   510 	      buffer[value.size] = 0;
       
   511 	      errno = 0;
       
   512 	      n = strtol(buffer, (char **)NULL, 10);
       
   513 	      if ( ! ((n == 0) && (errno == EINVAL)) )
       
   514 		  fb = n;
       
   515 	  }
       
   516       }
       
   517 
       
   518       if (!xiGetState || !xiGetInfo)
       
   519 	 fbs = 1;
       
   520       if ((fb < 0) || (fb >= fbs)) /* fb value not valid */
       
   521       {
       
   522          if (XrmGetResource(xrdb, "xineramaCenterHintX", "XineramaCenterHintX",
       
   523 		   &vtype, &value))
       
   524          {
       
   525 	     if (value.size < sizeof(buffer)) {
       
   526 		 strncpy(buffer, value.addr, value.size);
       
   527 		 buffer[value.size] = 0;
       
   528 		 errno = 0;
       
   529 		 n = strtol(buffer, (char **)NULL, 10);
       
   530 		 if ( ! ((n == 0) && (errno == EINVAL)) )
       
   531 		     x = n;
       
   532 	     }
       
   533          }
       
   534          if (XrmGetResource(xrdb, "xineramaCenterHintY", "XineramaCenterHintY",
       
   535 		   &vtype, &value))
       
   536          {
       
   537 	     if (value.size < sizeof(buffer)) {
       
   538 		 strncpy(buffer, value.addr, value.size);
       
   539 		 buffer[value.size] = 0;
       
   540 		 errno = 0;
       
   541 		 n = strtol(buffer, (char **)NULL, 10);
       
   542 		 if ( ! ((n == 0) && (errno == EINVAL)) )
       
   543 		     y = n;
       
   544 	     }
       
   545          }
       
   546       }
       
   547    }
       
   548 
       
   549    if (!xiGetState)
       
   550    {
       
   551       /* Xinerama is not active, so there's only one framebuffer */
       
   552       /* (for screen 0). Return appropriate values anyway.       */
       
   553 
       
   554       if (fb == 0) /* assume screen == fb == 0. Code only supports one screen.*/
       
   555       {
       
   556          *xret = (WidthOfScreen(ScreenOfDisplay(display, 0))) / 2;
       
   557          *yret = (HeightOfScreen(ScreenOfDisplay(display, 0))) / 2;
       
   558       }
       
   559       else
       
   560       {
       
   561          if ((x >= 0) && (x < WidthOfScreen(ScreenOfDisplay(display, 0))))
       
   562             *xret = x;
       
   563          else
       
   564             *xret = (WidthOfScreen(ScreenOfDisplay(display, 0))) / 2;
       
   565 
       
   566          if ((y >= 0) && (y < HeightOfScreen(ScreenOfDisplay(display, 0))))
       
   567             *yret = y;
       
   568          else
       
   569             *yret = (HeightOfScreen(ScreenOfDisplay(display, 0))) / 2;
       
   570       }
       
   571    }
       
   572    else
       
   573    {
       
   574       /* Xinerama is active, so do the right thing. */
       
   575 
       
   576       if (!xiGetInfo)
       
   577          return 0;
       
   578 
       
   579       if ((fb > -1) && (fb < fbs))  /* if fb has a legal value */
       
   580       {
       
   581          *xret = rects[fb].x + (rects[fb].width / 2);
       
   582          *yret = rects[fb].y + (rects[fb].height / 2);
       
   583       }
       
   584       else
       
   585       {
       
   586          if ((x >= 0) && (x < WidthOfScreen(ScreenOfDisplay(display, 0))))
       
   587             *xret = x;
       
   588          else
       
   589             *xret = (WidthOfScreen(ScreenOfDisplay(display, 0))) / 2;
       
   590 
       
   591          if ((y >= 0) && (y < HeightOfScreen(ScreenOfDisplay(display, 0))))
       
   592             *yret = y;
       
   593          else
       
   594             *yret = (HeightOfScreen(ScreenOfDisplay(display, 0))) / 2;
       
   595       }
       
   596    }
       
   597    return 1;
       
   598 }
       
   599 
       
   600 /**** Code taken from xc/lib/Xinerama/Xinerama.c in Xorg for compatibility with
       
   601       XFree86 & Xorg Xinerama 1.1 protocol ****/
       
   602 
       
   603 /*******************************************************************\
       
   604   Alternate interface to make up for shortcomings in the original,
       
   605   namely, the omission of the screen origin.  The new interface is
       
   606   in the "Xinerama" namespace instead of "PanoramiX".
       
   607 \*******************************************************************/
       
   608 
       
   609 static
       
   610 Bool XineramaIsActive(Display *dpy)
       
   611 {
       
   612     xXineramaIsActiveReply	rep;
       
   613     xXineramaIsActiveReq  	*req;
       
   614     XExtDisplayInfo 		*info = find_display (dpy);
       
   615 
       
   616     if(!XextHasExtension(info))
       
   617 	return False;  /* server doesn't even have the extension */
       
   618 
       
   619     LockDisplay (dpy);
       
   620     GetReq (XineramaIsActive, req);
       
   621     req->reqType = info->codes->major_opcode;
       
   622     req->panoramiXReqType = X_XineramaIsActive;
       
   623     if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
       
   624 	UnlockDisplay (dpy);
       
   625 	SyncHandle ();
       
   626 	return False;
       
   627     }
       
   628     UnlockDisplay (dpy);
       
   629     SyncHandle ();
       
   630     return rep.state;
       
   631 }
       
   632 
       
   633 static
       
   634 XineramaScreenInfo * 
       
   635 XineramaQueryScreens(
       
   636    Display *dpy,
       
   637    int     *number
       
   638 )
       
   639 {
       
   640     XExtDisplayInfo		*info = find_display (dpy);
       
   641     xXineramaQueryScreensReply	rep;
       
   642     xXineramaQueryScreensReq	*req;
       
   643     XineramaScreenInfo		*scrnInfo = NULL;
       
   644 
       
   645     PanoramiXCheckExtension (dpy, info, 0);
       
   646 
       
   647     LockDisplay (dpy);
       
   648     GetReq (XineramaQueryScreens, req);
       
   649     req->reqType = info->codes->major_opcode;
       
   650     req->panoramiXReqType = X_XineramaQueryScreens;
       
   651     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
       
   652 	UnlockDisplay (dpy);
       
   653 	SyncHandle ();
       
   654 	return NULL;
       
   655     }
       
   656 
       
   657     if(rep.number) {
       
   658 	if((scrnInfo = Xmalloc(sizeof(XineramaScreenInfo) * rep.number))) {
       
   659 	    xXineramaScreenInfo scratch;
       
   660 	    int i;
       
   661 
       
   662 	    for(i = 0; i < rep.number; i++) {
       
   663 		_XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo);
       
   664 		scrnInfo[i].screen_number = i;
       
   665 		scrnInfo[i].x_org 	  = scratch.x_org;
       
   666 		scrnInfo[i].y_org 	  = scratch.y_org;
       
   667 		scrnInfo[i].width 	  = scratch.width;
       
   668 		scrnInfo[i].height 	  = scratch.height;
       
   669 	    }
       
   670 
       
   671 	    *number = rep.number;
       
   672 	} else
       
   673 	    _XEatData(dpy, rep.length << 2);
       
   674     }
       
   675 
       
   676     UnlockDisplay (dpy);
       
   677     SyncHandle ();
       
   678     return scrnInfo;
       
   679 }
       
   680 
       
   681 
       
   682