366N/A/* $TOG: XPanoramiX.c /main/2 1997/11/16 08:45:41 kaleb $ */
366N/A/*****************************************************************
366N/A
366N/ACopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
366N/A
366N/APermission is hereby granted, free of charge, to any person obtaining a copy
366N/Aof this software and associated documentation files (the "Software"), to deal
366N/Ain the Software without restriction, including without limitation the rights
366N/Ato use, copy, modify, merge, publish, distribute, sublicense, and/or sell
366N/Acopies of the Software.
366N/A
366N/AThe above copyright notice and this permission notice shall be included in
366N/Aall copies or substantial portions of the Software.
366N/A
366N/ATHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
366N/AIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
366N/AFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
366N/ADIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
366N/ABUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
366N/AWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
366N/AIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
366N/A
366N/AExcept as contained in this notice, the name of Digital Equipment Corporation
366N/Ashall not be used in advertising or otherwise to promote the sale, use or other
366N/Adealings in this Software without prior written authorization from Digital
366N/AEquipment Corporation.
366N/A
366N/A******************************************************************/
1345N/A/* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
366N/A *
366N/A * Permission is hereby granted, free of charge, to any person obtaining a
919N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
366N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
366N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
366N/A */
366N/A
366N/A#define NEED_EVENTS
366N/A#define NEED_REPLIES
366N/A#include <X11/Xlibint.h>
366N/A#include <X11/Xutil.h>
366N/A#include <X11/Xresource.h>
366N/A#include <X11/extensions/Xext.h>
366N/A#include <X11/extensions/extutil.h>
366N/A#include <X11/extensions/panoramiXext.h>
366N/A#include <X11/extensions/panoramiXproto.h>
366N/A#include <X11/extensions/xinerama.h>
366N/A
366N/ABool XGetXineramaInfo(Display *dpy, int screen_number, XID VirtualWID, XineramaInfo *info);
366N/A
366N/Astatic XExtensionInfo _panoramiX_ext_info_data;
366N/Astatic XExtensionInfo *panoramiX_ext_info = &_panoramiX_ext_info_data;
366N/Astatic /* const */ char *panoramiX_extension_name = PANORAMIX_PROTOCOL_NAME;
366N/A
366N/A#define PanoramiXCheckExtension(dpy,i,val) \
366N/A XextCheckExtension (dpy, i, panoramiX_extension_name, val)
366N/A#define PanoramiXSimpleCheckExtension(dpy,i) \
366N/A XextSimpleCheckExtension (dpy, i, panoramiX_extension_name)
366N/A
366N/Astatic int close_display();
366N/Astatic Bool wire_to_event();
366N/Astatic Status event_to_wire();
366N/Astatic /* const */ XExtensionHooks panoramiX_extension_hooks = {
366N/A NULL, /* create_gc */
366N/A NULL, /* copy_gc */
366N/A NULL, /* flush_gc */
366N/A NULL, /* free_gc */
366N/A NULL, /* create_font */
366N/A NULL, /* free_font */
366N/A close_display, /* close_display */
366N/A NULL, /* wire_to_event */
366N/A NULL, /* event_to_wire */
366N/A NULL, /* error */
366N/A NULL, /* error_string */
366N/A};
366N/A
366N/Astatic XEXT_GENERATE_FIND_DISPLAY (find_display, panoramiX_ext_info,
366N/A panoramiX_extension_name,
366N/A &panoramiX_extension_hooks,
366N/A 0, NULL)
366N/A
366N/Astatic XEXT_GENERATE_CLOSE_DISPLAY (close_display, panoramiX_ext_info)
366N/A
366N/A
366N/A
366N/A#ifdef SUNSOFT
366N/Astruct XineramaExtVersionInfo
366N/A{
366N/A int major_vers, minor_vers;
366N/A};
366N/A
366N/A/**** Code taken from xc/include/extensions/Xinerama.h in Xorg for
366N/A compatibility with XFree86 & Xorg protocols ****/
366N/A
366N/Astatic Bool XineramaIsActive(Display *dpy);
366N/A
366N/A/*
366N/A Returns the number of heads and a pointer to an array of
366N/A structures describing the position and size of the individual
366N/A heads. Returns NULL and number = 0 if Xinerama is not active.
366N/A
366N/A Returned array should be freed with XFree().
366N/A*/
366N/Atypedef struct {
366N/A int screen_number;
366N/A short x_org;
366N/A short y_org;
366N/A short width;
366N/A short height;
366N/A} XineramaScreenInfo;
366N/A
366N/Astatic XineramaScreenInfo *
366N/AXineramaQueryScreens(
366N/A Display *dpy,
366N/A int *number
366N/A);
366N/A
366N/A#endif
366N/A
366N/A/****************************************************************************
366N/A * *
366N/A * PanoramiX public interfaces *
366N/A * *
366N/A ****************************************************************************/
366N/A
366N/ABool XPanoramiXQueryExtension (dpy, event_basep, error_basep)
366N/A Display *dpy;
366N/A int *event_basep, *error_basep;
366N/A{
366N/A XExtDisplayInfo *info = find_display (dpy);
366N/A
366N/A if (XextHasExtension(info)) {
366N/A *event_basep = info->codes->first_event;
366N/A *error_basep = info->codes->first_error;
366N/A return True;
366N/A } else {
366N/A return False;
366N/A }
366N/A}
366N/A
366N/A
366N/AStatus XPanoramiXQueryVersion(dpy, major_versionp, minor_versionp)
366N/A Display *dpy;
366N/A int *major_versionp, *minor_versionp;
366N/A{
366N/A XExtDisplayInfo *info = find_display (dpy);
366N/A xPanoramiXQueryVersionReply rep;
366N/A register xPanoramiXQueryVersionReq *req;
366N/A
366N/A#ifdef SUNSOFT
366N/A struct XineramaExtVersionInfo *vinfo;
366N/A
366N/A if (info->data != NULL) {
366N/A vinfo = (struct XineramaExtVersionInfo *) info->data;
366N/A
366N/A *major_versionp = vinfo->major_vers;
366N/A *minor_versionp = vinfo->minor_vers;
366N/A return 1;
366N/A }
366N/A#endif
366N/A
366N/A PanoramiXCheckExtension (dpy, info, 0);
366N/A
366N/A LockDisplay (dpy);
366N/A GetReq (PanoramiXQueryVersion, req);
366N/A req->reqType = info->codes->major_opcode;
366N/A req->panoramiXReqType = X_PanoramiXQueryVersion;
366N/A req->clientMajor = PANORAMIX_MAJOR_VERSION;
366N/A req->clientMinor = PANORAMIX_MINOR_VERSION;
366N/A if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return 0;
366N/A }
366N/A *major_versionp = rep.majorVersion;
366N/A *minor_versionp = rep.minorVersion;
366N/A#ifdef SUNSOFT /* Cache version info */
366N/A vinfo = Xmalloc(sizeof(struct XineramaExtVersionInfo));
366N/A
366N/A if (vinfo != NULL) {
366N/A vinfo->major_vers = rep.majorVersion;
366N/A vinfo->minor_vers = rep.minorVersion;
366N/A info->data = (XPointer) vinfo;
366N/A }
366N/A#endif
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return 1;
366N/A}
366N/A
366N/AXPanoramiXInfo *XPanoramiXAllocInfo()
366N/A{
366N/A return (XPanoramiXInfo *) Xmalloc (sizeof (XPanoramiXInfo));
366N/A}
366N/A
366N/AStatus XPanoramiXGetState (dpy, drawable, panoramiX_info)
366N/A Display *dpy;
366N/A Drawable drawable;
366N/A XPanoramiXInfo *panoramiX_info ;
366N/A{
366N/A XExtDisplayInfo *info = find_display (dpy);
366N/A xPanoramiXGetStateReply rep;
366N/A register xPanoramiXGetStateReq *req;
366N/A
366N/A PanoramiXCheckExtension (dpy, info, 0);
366N/A
366N/A LockDisplay (dpy);
366N/A GetReq (PanoramiXGetState, req);
366N/A req->reqType = info->codes->major_opcode;
366N/A req->panoramiXReqType = X_PanoramiXGetState;
366N/A req->window = drawable;
366N/A if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return 0;
366N/A }
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A panoramiX_info->window = rep.window;
366N/A panoramiX_info->State = rep.state;
366N/A return 1;
366N/A}
366N/A
366N/AStatus XPanoramiXGetScreenCount (dpy, drawable, panoramiX_info)
366N/A Display *dpy;
366N/A Drawable drawable;
366N/A XPanoramiXInfo *panoramiX_info ;
366N/A{
366N/A XExtDisplayInfo *info = find_display (dpy);
366N/A xPanoramiXGetScreenCountReply rep;
366N/A register xPanoramiXGetScreenCountReq *req;
366N/A
366N/A PanoramiXCheckExtension (dpy, info, 0);
366N/A
366N/A LockDisplay (dpy);
366N/A GetReq (PanoramiXGetScreenCount, req);
366N/A req->reqType = info->codes->major_opcode;
366N/A req->panoramiXReqType = X_PanoramiXGetScreenCount;
366N/A req->window = drawable;
366N/A if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return 0;
366N/A }
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A panoramiX_info->window = rep.window;
366N/A panoramiX_info->ScreenCount = rep.ScreenCount;
366N/A return 1;
366N/A}
366N/A
366N/AStatus XPanoramiXGetScreenSize (dpy, drawable, screen_num, panoramiX_info)
366N/A Display *dpy;
366N/A Drawable drawable;
366N/A int screen_num;
366N/A XPanoramiXInfo *panoramiX_info ;
366N/A{
366N/A XExtDisplayInfo *info = find_display (dpy);
366N/A xPanoramiXGetScreenSizeReply rep;
366N/A register xPanoramiXGetScreenSizeReq *req;
366N/A
366N/A PanoramiXCheckExtension (dpy, info, 0);
366N/A
366N/A LockDisplay (dpy);
366N/A GetReq (PanoramiXGetScreenSize, req);
366N/A req->reqType = info->codes->major_opcode;
366N/A req->panoramiXReqType = X_PanoramiXGetScreenSize;
366N/A req->window = drawable;
366N/A req->screen = screen_num; /* need to define */
366N/A if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return 0;
366N/A }
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A panoramiX_info->window = rep.window;
366N/A panoramiX_info->screen = rep.screen;
366N/A panoramiX_info->width = rep.width;
366N/A panoramiX_info->height = rep.height;
366N/A return 1;
366N/A}
366N/A
366N/A
366N/A/* new api for xinerama */
366N/A
366N/ABool XineramaGetState(Display * display, int screen_number)
366N/A{
366N/A XExtDisplayInfo *info = find_display (display);
366N/A
366N/A /* screen_number may seem like hyper-bogus stuff, but:
366N/A it may be possible to have 2 xinerama screen sets on
366N/A one server */
366N/A
366N/A if(screen_number)
366N/A return False; /* no no, must say zero */
366N/A
366N/A if(!XextHasExtension(info))
366N/A return False;
366N/A else
366N/A {
366N/A int maj, min;
366N/A
366N/A if (XPanoramiXQueryVersion(display, &maj, &min) == 0) {
366N/A return False;
366N/A }
366N/A if ((maj == 1) && (min >= 0)) {
366N/A return XineramaIsActive(display);
366N/A } else {
366N/A return True; /* can't check in 1.0 protocol */
366N/A }
366N/A }
366N/A}
366N/A
366N/AStatus XineramaGetInfo(Display * display, int screen_number, XRectangle *
366N/A framebuffer_rects, unsigned char * framebuffer_hints, int *
366N/A num_framebuffers )
366N/A
366N/A{
366N/A int framebuffercount; /* number of fb's we know about */
366N/A int i; /* fortran */
366N/A Window win;
366N/A int x = 0, y = 0;
366N/A int maj, min;
366N/A
366N/A if(!XineramaGetState(display, screen_number))
366N/A return 0;
366N/A
366N/A if (XPanoramiXQueryVersion(display, &maj, &min) == 0) {
366N/A return 0;
366N/A }
366N/A if ((maj == 1) && (min >= 0)) {
366N/A /* Use XFree86/Xorg extended protocol */
366N/A XineramaScreenInfo *xsi;
366N/A
366N/A xsi = XineramaQueryScreens(display, &framebuffercount);
366N/A if (xsi == NULL || framebuffercount == 0) {
366N/A return 0;
366N/A }
366N/A for (i = 0; i < framebuffercount ; i++) {
366N/A framebuffer_rects[i].x = xsi[i].x_org;
366N/A framebuffer_rects[i].y = xsi[i].y_org;
366N/A framebuffer_rects[i].width = xsi[i].width;
366N/A framebuffer_rects[i].height = xsi[i].height;
366N/A }
366N/A XFree(xsi);
366N/A } else {
366N/A /* Use Sun extended protocol */
366N/A XPanoramiXInfo panoramiX_info;
366N/A XineramaInfo *info; /* list of screen x,y etc */
366N/A
366N/A /* get the count of screens that we need to know about
366N/A NOTE: screen_number implies a set of fb's for this
366N/A working surface */
366N/A
366N/A win = 0;
366N/A
366N/A XPanoramiXGetScreenCount(display, win, &panoramiX_info);
366N/A
366N/A if(!panoramiX_info.ScreenCount) {
366N/A return 0;
366N/A }
366N/A framebuffercount = panoramiX_info.ScreenCount;
366N/A
366N/A /* Make sure not to overflow buffers if X server has more screens
366N/A than we expect */
366N/A if (framebuffercount > MAXSCREEN)
366N/A framebuffercount = MAXSCREEN;
366N/A
366N/A info = malloc(sizeof(XineramaInfo));
366N/A
366N/A if(!info)
366N/A return 0;
366N/A
366N/A /* now read the servers list of frame buffers */
366N/A
366N/A if(!XGetXineramaInfo(display,screen_number,
366N/A (XID) RootWindow(display,screen_number),info))
366N/A {
366N/A free(info);
366N/A return 0;
366N/A }
366N/A
366N/A
366N/A for(i = 0; i < framebuffercount; i++)
366N/A {
366N/A framebuffer_rects[i].x = info->subs[i].dx;
366N/A framebuffer_rects[i].y = info->subs[i].dy;
366N/A framebuffer_rects[i].width = info->subs[i].wdx;
366N/A framebuffer_rects[i].height = info->subs[i].wdy;
366N/A }
366N/A
366N/A free(info);
366N/A }
366N/A
366N/A *num_framebuffers = framebuffercount;
366N/A
366N/A /* assume the start up and list are in the same order */
366N/A
366N/A for(i = 0; i < framebuffercount; i++)
366N/A {
366N/A framebuffer_hints[i] = 0;
366N/A if (i > 0) /* fb0 never gets a hint */
366N/A {
366N/A if (framebuffer_rects[i].x > x) { /* right */
366N/A if (framebuffer_rects[i].y == y)
366N/A framebuffer_hints[i] = XINERAMA_PLACE_RIGHT;
366N/A }
366N/A else if (framebuffer_rects[i].x == x) { /* up/down */
366N/A if (framebuffer_rects[i].y > y)
366N/A framebuffer_hints[i] = XINERAMA_PLACE_TOP;
366N/A else if (framebuffer_rects[i].y < y)
366N/A framebuffer_hints[i] = XINERAMA_PLACE_BOTTOM;
366N/A } else if (framebuffer_rects[i].x < x) { /* left */
366N/A if (framebuffer_rects[i].y == y)
366N/A framebuffer_hints[i] = XINERAMA_PLACE_LEFT;
366N/A }
366N/A }
366N/A x = framebuffer_rects[i].x;
366N/A y = framebuffer_rects[i].y;
366N/A
366N/A }
366N/A return framebuffercount;
366N/A}
366N/A
366N/ABool
366N/AXGetXineramaInfo(Display *dpy ,int screen_number,XID VirtualWID,XineramaInfo *info )
366N/A{
366N/A xXineramaInfoReq *req;
366N/A xXineramaInfoReply *rep;
366N/A XExtDisplayInfo *Extinfo = find_display (dpy);
366N/A
366N/A if(!XineramaGetState(dpy, screen_number))
366N/A return False;
366N/A
366N/A rep = malloc(sizeof(xXineramaInfoReply));
366N/A
366N/A LockDisplay(dpy);
366N/A GetReq(XineramaInfo, req);
366N/A req->reqType = Extinfo->codes->major_opcode;
366N/A req->xXineramaReqType = X_XineramaInfo;
366N/A req->visual = VirtualWID;
366N/A
366N/A if (!_XReply(dpy, (xReply *)rep, (sizeof(xXineramaInfoReply)-32) >> 2
366N/A,
366N/A xFalse))
366N/A {
366N/A UnlockDisplay(dpy);
366N/A SyncHandle();
366N/A Xfree(rep);
366N/A return NULL;
366N/A }
366N/A info->wid = VirtualWID;
366N/A memcpy(&info->subs[0],&rep->subs[0],(MAXSCREEN-1) * sizeof(SubWID));
366N/A UnlockDisplay(dpy);
366N/A SyncHandle();
366N/A free(rep);
366N/A return 1;
366N/A}
366N/A
366N/AStatus XineramaGetCenterHint(Display* display, int screen_number,
366N/A int* xret, int* yret)
366N/A{
366N/A int x = -1;
366N/A int y = -1;
366N/A int fb = -1;
366N/A int fbs;
366N/A XrmDatabase xrdb;
366N/A XrmValue value;
366N/A char* vtype;
366N/A char buffer[20];
366N/A XRectangle rects[MAXSCREEN];
366N/A unsigned char hints[MAXSCREEN];
366N/A Bool xiGetState, xiGetInfo;
366N/A long n;
366N/A
366N/A
366N/A if (screen_number)
366N/A return 0; /* don't yet support multiple Xinerama screens */
366N/A
366N/A xiGetState = XineramaGetState(display, screen_number);
366N/A xiGetInfo = XineramaGetInfo(display, screen_number, rects, hints, &fbs);
366N/A
366N/A if (xrdb = XrmGetDatabase(display))
366N/A {
366N/A if (XrmGetResource(xrdb, "xineramaDefaultFramebuffer",
366N/A "XineramaDefaultFramebuffer", &vtype, &value))
366N/A {
366N/A if (value.size < sizeof(buffer)) {
366N/A strncpy(buffer, value.addr, value.size);
366N/A buffer[value.size] = 0;
366N/A errno = 0;
366N/A n = strtol(buffer, (char **)NULL, 10);
366N/A if ( ! ((n == 0) && (errno == EINVAL)) )
366N/A fb = n;
366N/A }
366N/A }
366N/A
366N/A if (!xiGetState || !xiGetInfo)
366N/A fbs = 1;
366N/A if ((fb < 0) || (fb >= fbs)) /* fb value not valid */
366N/A {
366N/A if (XrmGetResource(xrdb, "xineramaCenterHintX", "XineramaCenterHintX",
366N/A &vtype, &value))
366N/A {
366N/A if (value.size < sizeof(buffer)) {
366N/A strncpy(buffer, value.addr, value.size);
366N/A buffer[value.size] = 0;
366N/A errno = 0;
366N/A n = strtol(buffer, (char **)NULL, 10);
366N/A if ( ! ((n == 0) && (errno == EINVAL)) )
366N/A x = n;
366N/A }
366N/A }
366N/A if (XrmGetResource(xrdb, "xineramaCenterHintY", "XineramaCenterHintY",
366N/A &vtype, &value))
366N/A {
366N/A if (value.size < sizeof(buffer)) {
366N/A strncpy(buffer, value.addr, value.size);
366N/A buffer[value.size] = 0;
366N/A errno = 0;
366N/A n = strtol(buffer, (char **)NULL, 10);
366N/A if ( ! ((n == 0) && (errno == EINVAL)) )
366N/A y = n;
366N/A }
366N/A }
366N/A }
366N/A }
366N/A
366N/A if (!xiGetState)
366N/A {
366N/A /* Xinerama is not active, so there's only one framebuffer */
366N/A /* (for screen 0). Return appropriate values anyway. */
366N/A
366N/A if (fb == 0) /* assume screen == fb == 0. Code only supports one screen.*/
366N/A {
366N/A *xret = (WidthOfScreen(ScreenOfDisplay(display, 0))) / 2;
366N/A *yret = (HeightOfScreen(ScreenOfDisplay(display, 0))) / 2;
366N/A }
366N/A else
366N/A {
366N/A if ((x >= 0) && (x < WidthOfScreen(ScreenOfDisplay(display, 0))))
366N/A *xret = x;
366N/A else
366N/A *xret = (WidthOfScreen(ScreenOfDisplay(display, 0))) / 2;
366N/A
366N/A if ((y >= 0) && (y < HeightOfScreen(ScreenOfDisplay(display, 0))))
366N/A *yret = y;
366N/A else
366N/A *yret = (HeightOfScreen(ScreenOfDisplay(display, 0))) / 2;
366N/A }
366N/A }
366N/A else
366N/A {
366N/A /* Xinerama is active, so do the right thing. */
366N/A
366N/A if (!xiGetInfo)
366N/A return 0;
366N/A
366N/A if ((fb > -1) && (fb < fbs)) /* if fb has a legal value */
366N/A {
366N/A *xret = rects[fb].x + (rects[fb].width / 2);
366N/A *yret = rects[fb].y + (rects[fb].height / 2);
366N/A }
366N/A else
366N/A {
366N/A if ((x >= 0) && (x < WidthOfScreen(ScreenOfDisplay(display, 0))))
366N/A *xret = x;
366N/A else
366N/A *xret = (WidthOfScreen(ScreenOfDisplay(display, 0))) / 2;
366N/A
366N/A if ((y >= 0) && (y < HeightOfScreen(ScreenOfDisplay(display, 0))))
366N/A *yret = y;
366N/A else
366N/A *yret = (HeightOfScreen(ScreenOfDisplay(display, 0))) / 2;
366N/A }
366N/A }
366N/A return 1;
366N/A}
366N/A
366N/A/**** Code taken from xc/lib/Xinerama/Xinerama.c in Xorg for compatibility with
366N/A XFree86 & Xorg Xinerama 1.1 protocol ****/
366N/A
366N/A/*******************************************************************\
366N/A Alternate interface to make up for shortcomings in the original,
366N/A namely, the omission of the screen origin. The new interface is
366N/A in the "Xinerama" namespace instead of "PanoramiX".
366N/A\*******************************************************************/
366N/A
366N/Astatic
366N/ABool XineramaIsActive(Display *dpy)
366N/A{
366N/A xXineramaIsActiveReply rep;
366N/A xXineramaIsActiveReq *req;
366N/A XExtDisplayInfo *info = find_display (dpy);
366N/A
366N/A if(!XextHasExtension(info))
366N/A return False; /* server doesn't even have the extension */
366N/A
366N/A LockDisplay (dpy);
366N/A GetReq (XineramaIsActive, req);
366N/A req->reqType = info->codes->major_opcode;
366N/A req->panoramiXReqType = X_XineramaIsActive;
366N/A if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return False;
366N/A }
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return rep.state;
366N/A}
366N/A
366N/Astatic
366N/AXineramaScreenInfo *
366N/AXineramaQueryScreens(
366N/A Display *dpy,
366N/A int *number
366N/A)
366N/A{
366N/A XExtDisplayInfo *info = find_display (dpy);
366N/A xXineramaQueryScreensReply rep;
366N/A xXineramaQueryScreensReq *req;
366N/A XineramaScreenInfo *scrnInfo = NULL;
366N/A
366N/A PanoramiXCheckExtension (dpy, info, 0);
366N/A
366N/A LockDisplay (dpy);
366N/A GetReq (XineramaQueryScreens, req);
366N/A req->reqType = info->codes->major_opcode;
366N/A req->panoramiXReqType = X_XineramaQueryScreens;
366N/A if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return NULL;
366N/A }
366N/A
1345N/A /*
1345N/A * rep.number is a CARD32 so could be as large as 2^32
1345N/A * The X11 protocol limits the total screen size to 64k x 64k,
1345N/A * and no screen can be smaller than a pixel. While technically
1345N/A * that means we could theoretically reach 2^32 screens, and that's
1345N/A * not even taking overlap into account, Xorg is currently limited
1345N/A * to 16 screens, and few known servers have a much higher limit,
1345N/A * so 1024 seems more than enough to prevent both integer overflow
1345N/A * and insane X server responses causing massive memory allocation.
1345N/A */
1345N/A if ((rep.number > 0) && (rep.number <= 1024))
1345N/A scrnInfo = Xmalloc(sizeof(XineramaScreenInfo) * rep.number);
1345N/A if (scrnInfo != NULL) {
1345N/A int i;
366N/A
1345N/A for (i = 0; i < rep.number; i++) {
1345N/A xXineramaScreenInfo scratch;
1345N/A
1345N/A _XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo);
366N/A
1345N/A scrnInfo[i].screen_number = i;
1345N/A scrnInfo[i].x_org = scratch.x_org;
1345N/A scrnInfo[i].y_org = scratch.y_org;
1345N/A scrnInfo[i].width = scratch.width;
1345N/A scrnInfo[i].height = scratch.height;
1345N/A }
1345N/A
1345N/A *number = rep.number;
1345N/A } else {
1345N/A _XEatDataWords(dpy, rep.length);
1345N/A *number = 0;
366N/A }
366N/A
366N/A UnlockDisplay (dpy);
366N/A SyncHandle ();
366N/A return scrnInfo;
366N/A}
366N/A
366N/A
366N/A