Home | History | Annotate | Line # | Download | only in src
      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