/* Copyright (c) 1993, 2001, Oracle and/or its affiliates. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* dga_Xrequests.c - the client side code for DGA X11 requests
*/
/*
*-----------------------------------------------------------------------
*
* This code uses the standard extension mechanism for sending
* SUN_DGA private extension requests.
*
*-----------------------------------------------------------------------
*/
#define NEED_REPLIES
#define NEED_EVENTS
#ifdef SERVER_DGA
#include <X11/X.h>
#include <X11/Xmd.h>
#include "resource.h"
#include "dixstruct.h"
#include <stdio.h>
#include "pixmapstr.h"
#else
#include <X11/Xlibint.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netdb.h>
#ifdef SVR4
#include <sys/utsname.h>
#endif
#endif /* SERVER_DGA */
#include "dga.h"
#include "dga_Xrequests.h"
#include "dga_incls.h"
#include "XineramaInfo.h"
#ifdef SERVER_DGA
#define NEW 1 /* Flag for SHAPES to use new window grabber */
#define BadCookie 0
#endif
#define X_DGA 0 /* a hack, so GetReq and GetResReq work below */
#ifndef MIN
#define MIN(i,j) ((i)<(j)?(i):(j))
#endif
static struct dga_extinfo **dga_extinfo_table = 0; /* No table to start with */
static int dga_extinfo_table_size = 0;
static int terminate_dga_ext();
static int islocalhost();
static int dga_winlist_add();
static int dga_winlist_free();
void * _dga_is_X_window();
int dga_pixlist_add();
static int dga_pixlist_free();
void *_dga_is_X_pixmap();
extern void dgai_win_ungrab_common();
extern int _thr_main();
#ifdef SVR4
#ifdef MT
mutex_t dgaGlobalMutex;
mutex_t dgaGlobalPixmapMutex;
int dgaThreaded; /* 1 == linked with libthread, else 0 */
int dgaMTOn; /* 1 == MT per-drawable locking is turned on, else 0 */
#endif
int _dga_client_version = -1;
void
dga_init_version(ver)
int ver;
{
if (ver > -1)
_dga_client_version = ver;
#ifdef MT
dgaThreaded = (_thr_main() != -1) ? 1 : 0;
dgaMTOn = 0;
mutex_init(&dgaGlobalMutex, USYNC_THREAD, NULL);
mutex_init(&dgaGlobalPixmapMutex, USYNC_THREAD, NULL);
#endif
}
#endif
#ifndef SERVER_DGA
static struct dga_extinfo *
init_dga_ext(dpy)
Display *dpy;
{
int protmajor, protminor;
XExtCodes *xecp;
struct dga_extinfo *infop;
#ifdef SVR4
if (_dga_client_version < 0)
return 0;
#endif
if (dga_extinfo_table_size < (dpy->fd + 1)) {
/* We've got to allocate or grow the table */
struct rlimit rl;
int size;
struct dga_extinfo **tblptr;
size = (getrlimit(RLIMIT_NOFILE, &rl) < 0) ?
dga_extinfo_table_size : rl.rlim_cur;
if (size < (dpy->fd + 1))
return 0;
tblptr = (struct dga_extinfo **) ((dga_extinfo_table_size) ?
realloc(dga_extinfo_table, sizeof(struct dga_extinfo *) *
size) :
malloc(sizeof(struct dga_extinfo *) * size));
if (tblptr == NULL)
return 0;
dga_extinfo_table = tblptr;
memset((char *) &dga_extinfo_table[dga_extinfo_table_size],
(int)'\0',
sizeof(struct dga_extinfo *) *
(size - dga_extinfo_table_size));
dga_extinfo_table_size = size;
}
if (dga_extinfo_table[dpy->fd] != NULL)
return dga_extinfo_table[dpy->fd];
if (!islocalhost(dpy))
return 0;
if ((xecp = XInitExtension(dpy, "SUN_DGA")) != NULL) {
if (XDgaQueryVersion(dpy, &protmajor, &protminor) == 0) {
protmajor = 3;
/* protminor = 0; let minor number pass through */
}
}
else if ((xecp = XInitExtension(dpy, "SunWindowGrabber")) != NULL) {
if (strcmp(ServerVendor(dpy),
"X11/NeWS - Sun Microsystems Inc.") == 0) {
if (VendorRelease(dpy) >= 3000) {
protmajor = 2;
protminor = 0;
}
else if (VendorRelease(dpy) >= 2000) {
protmajor = 1;
protminor = 0;
}
}
else
return 0;
}
else
return 0;
if ((infop = (struct dga_extinfo *)
malloc(sizeof(struct dga_extinfo))) == NULL)
return 0;
infop->protocol_major_version = protmajor;
infop->protocol_minor_version = protminor;
infop->extension = xecp->extension;
infop->major_opcode = xecp->major_opcode;
dga_extinfo_table[dpy->fd] = infop;
XESetCloseDisplay(dpy, infop->extension, terminate_dga_ext);
return infop;
}
static int
islocalhost(dpy)
Display *dpy;
{
char hostname[256];
char *colon;
unsigned int namelen;
size_t hostlen, phostlen;
#ifdef IPv6
struct addrinfo *localhostaddr;
struct addrinfo *otherhostaddr;
struct addrinfo *i, *j;
int equiv = 0;
char host[NI_MAXHOST];
#else
struct hostent *phost;
struct hostent *h;
#endif
union genericaddr {
struct sockaddr generic;
struct sockaddr_in internet;
#ifdef IPv6
struct sockaddr_in6 internetv6;
struct sockaddr_storage maximumsize;
#endif
struct sockaddr_un nuxi;
} addr;
if (dpy->display_name[0] == ':')
return 1;
#ifdef SVR4
colon = strrchr(dpy->display_name, ':');
#else
colon = rindex(dpy->display_name, ':');
#endif
phostlen = strlen(dpy->display_name) - (colon ? strlen(colon) : 0);
if((strncmp("unix", dpy->display_name, MIN(phostlen, 4)) == 0) ||
(strncmp("localhost", dpy->display_name, MIN(phostlen, 9)) == 0))
return 1;
/* We're not a unix domain connection so what are we? */
namelen = sizeof addr;
memset((char *) &addr, (int)'\0', sizeof addr);
if(getpeername(dpy->fd, (struct sockaddr *) &addr,
&namelen) < 0)
return 0;
hostlen = _XGetHostname(hostname, sizeof(hostname));
#ifdef IPv6
if (getaddrinfo(hostname, NULL, NULL, &localhostaddr) != 0)
return 0;
if (getnameinfo(&addr.generic, namelen, host, sizeof(host),
NULL, 0, 0) != 0) {
freeaddrinfo(localhostaddr);
return 0;
}
if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
freeaddrinfo(localhostaddr);
return 0;
}
for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
if (i->ai_family == j->ai_family) {
if (i->ai_family == AF_INET) {
struct sockaddr_in *sinA
= (struct sockaddr_in *) i->ai_addr;
struct sockaddr_in *sinB
= (struct sockaddr_in *) j->ai_addr;
struct in_addr *A = &sinA->sin_addr;
struct in_addr *B = &sinB->sin_addr;
if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
equiv = 1;
}
} else if (i->ai_family == AF_INET6) {
struct sockaddr_in6 *sinA
= (struct sockaddr_in6 *) i->ai_addr;
struct sockaddr_in6 *sinB
= (struct sockaddr_in6 *) j->ai_addr;
struct in6_addr *A = &sinA->sin6_addr;
struct in6_addr *B = &sinB->sin6_addr;
if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
equiv = 1;
}
}
}
}
}
freeaddrinfo(localhostaddr);
freeaddrinfo(otherhostaddr);
return equiv;
#else
if ((addr.generic.sa_family != AF_INET) ||
((h = gethostbyaddr((char *)&addr.internet.sin_addr,
sizeof addr.internet.sin_addr,
addr.internet.sin_family)) == 0))
return 0;
/* Find real host name on TCPIP */
phost = gethostbyname(h->h_name);
phostlen = strlen(phost->h_name);
if (strncmp(hostname, phost->h_name, MIN(phostlen, hostlen)))
return 0;
return 1;
#endif
}
static struct dga_extinfo *
lookup_dga_ext(dpy)
Display *dpy;
{
if (dga_extinfo_table_size < (dpy->fd + 1))
return 0;
return dga_extinfo_table[dpy->fd];
}
static int
terminate_dga_ext(dpy, codes)
Display *dpy;
XExtCodes *codes;
{
free(dga_extinfo_table[dpy->fd]);
dga_extinfo_table[dpy->fd] = NULL;
dga_winlist_free(dpy, NULL);
/* TODO: free pixmaps as well? */
return(1);
}
#endif /* SERVER_DGA */
Dga_token
XDgaGrabWindow(dpy, win)
Display *dpy;
Window win;
{
#ifdef SERVER_DGA
int val;
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
val = DgaWgGrab(pWin, NEW);
if (val) {
if (dga_winlist_add(val, dpy, win) == 0) {
XDgaUnGrabWindow(dpy, win);
return 0;
}
}
return val;
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = init_dga_ext(dpy)) == NULL)
return 0;
LockDisplay(dpy);
GetResReq(DGA, win, req);
req->reqType = extinfop->major_opcode;
req->pad = (extinfop->protocol_major_version >= 2) ?
X_DgaGrabWindow : X_DgaGrabWindow_Old ;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
if (rep.data00) {
if (dga_winlist_add(rep.data00, dpy, win) == 0) {
XDgaUnGrabWindow(dpy, win);
return 0;
}
}
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaUnGrabWindow(dpy, win)
Display *dpy;
Window win;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
int val;
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
val = DgaWgUngrab(pWin, NEW);
if (val) {
if (dga_winlist_free(dpy, win) == 0)
return 0;
}
return val;
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
LockDisplay(dpy);
GetResReq(DGA, win, req);
req->reqType = extinfop->major_opcode;
req->pad = (extinfop->protocol_major_version >= 2) ?
X_DgaUnGrabWindow : X_DgaUnGrabWindow_Old;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
if (rep.data00) {
if (dga_winlist_free(dpy, win) == 0)
return 0;
}
return rep.data00; /* Status */
#endif /* SERVER_DGA */
}
#ifndef SERVER_DGA
Dga_token
XDgaGrabColormap(dpy, cmap)
Display *dpy;
Colormap cmap;
{
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
if ((extinfop = init_dga_ext(dpy)) == NULL) {
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
LockDisplay(dpy);
GetResReq(DGA, cmap, req);
req->reqType = extinfop->major_opcode;
req->pad = (extinfop->protocol_major_version >= 3) ?
X_DgaGrabColormap : X_DgaGrabColormap_Old;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return rep.data00;
}
int
XDgaUnGrabColormap(dpy, cmap)
Display *dpy;
Colormap cmap;
{
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
if ((extinfop = lookup_dga_ext(dpy)) == NULL) {
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
LockDisplay(dpy);
GetResReq(DGA, cmap, req);
req->reqType = extinfop->major_opcode;
req->pad = (extinfop->protocol_major_version >= 3) ?
X_DgaUnGrabColormap : X_DgaUnGrabColormap_Old;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return rep.data00; /* Status */
}
#endif /* SERVER_DGA */
int
XDgaDrawGrabWids(dpy, drawid, nwids)
Display *dpy;
Drawable drawid;
int nwids;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(drawid, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
return(DgaWidGrab(pWin, nwids));
#else
xDGAReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
if (((extinfop = lookup_dga_ext(dpy)) == NULL) ||
(extinfop->protocol_major_version < 2)) {
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
LockDisplay(dpy);
GetReq(DGA, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabWids;
req->id = drawid;
req->number_objects = nwids;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaGrabWids(dpy, win, nwids)
Display *dpy;
Window win;
int nwids;
{
return (XDgaDrawGrabWids(dpy, (Drawable)win, nwids));
}
int
XDgaDrawGrabFCS(dpy, drawid, nfcs)
Display *dpy;
Drawable drawid;
int nfcs;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(drawid, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
/* When OWGX supports PIXMAPS, can be reomoved */
return(DgaFcsGrab(pWin, nfcs));
#else
xDGAReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
if (((extinfop = lookup_dga_ext(dpy)) == NULL) ||
(extinfop->protocol_major_version < 2)) {
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
LockDisplay(dpy);
GetReq(DGA, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabFCS;
req->id = drawid;
req->number_objects = nfcs;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return(rep.data00);
#endif /* SERVER_DGA */
}
int
XDgaGrabFCS(dpy, win, nfcs)
Display *dpy;
Window win;
int nfcs;
{
return (XDgaDrawGrabFCS(dpy, (Drawable)win, nfcs));
}
int
XDgaDrawGrabZbuf(dpy, drawid, nzbuftype)
Display *dpy;
Drawable drawid;
int nzbuftype;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(drawid, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
return(DgaZbufGrab(pWin, nzbuftype));
#else
xDGAReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
if (((extinfop = lookup_dga_ext(dpy)) == NULL) ||
(extinfop->protocol_major_version < 2)) {
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
LockDisplay(dpy);
GetReq(DGA, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabZbuf;
req->id = drawid;
req->number_objects = nzbuftype;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return(rep.data00);
#endif /* SERVER_DGA */
}
int
XDgaGrabZbuf(dpy, win, nzbuftype)
Display *dpy;
Window win;
int nzbuftype;
{
return (XDgaDrawGrabZbuf(dpy, (Drawable)win, nzbuftype));
}
int
XDgaDrawGrabStereo(dpy, drawid, st_mode)
Display *dpy;
Drawable drawid;
int st_mode;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(drawid, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
return(DgaStereoGrab(pWin, st_mode));
#else
xDGAReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
if (((extinfop = lookup_dga_ext(dpy)) == NULL) ||
(extinfop->protocol_major_version < 2)) {
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
LockDisplay(dpy);
GetReq(DGA, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabStereo;
req->id = drawid;
req->number_objects = st_mode;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaGrabStereo(dpy, win, st_mode)
Display *dpy;
Window win;
int st_mode;
{
return (XDgaDrawGrabStereo(dpy, (Drawable)win, st_mode));
}
int
XDgaGrabABuffers(dpy, win, type, buffer_site)
Display *dpy;
Window win;
int type;
int buffer_site;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
/* Some surf prep may be needed for mpg */
return(DgaABuffersGrabInfo((DrawablePtr)pWin, type, buffer_site));
#else
xDgaGrabABuffersReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 2)
return 0;
LockDisplay(dpy);
GetReq(DgaGrabABuffers, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabABuffers;
req->id = win;
req->type = type;
req->buffer_site = buffer_site;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaUnGrabABuffers(dpy, win, type)
Display *dpy;
Window win;
int type;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
return(DgaABuffersUngrabInfo((DrawablePtr)pWin, type));
#else
xDgaGrabABuffersReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 2)
return 0;
LockDisplay(dpy);
GetReq(DgaGrabABuffers, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaUnGrabABuffers;
req->id = win;
req->type = type;
req->buffer_site = 0;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaGrabBuffers(dpy, win, nbuffers)
Display *dpy;
Window win;
int nbuffers;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
/* Some surf prep may be needed for mpg */
return(DgaBufGrab(pWin, nbuffers));
#else
xDGAReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 2)
return 0;
LockDisplay(dpy);
GetReq(DGA, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabBuffers;
req->id = win;
req->number_objects = nbuffers;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaUnGrabBuffers(dpy, win)
Display *dpy;
Window win;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
return(DgaBufUngrab(pWin));
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 2)
return 0;
LockDisplay(dpy);
GetResReq(DGA, win, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaUnGrabBuffers;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaGrabRetainedWindow(dpy, win)
Display *dpy;
Window win;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
return(DgaSharedRetained(pWin, 1, win));
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 3)
return 0;
LockDisplay(dpy);
GetResReq(DGA, win, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabRetained;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaUnGrabRetainedWindow(dpy, win)
Display *dpy;
Window win;
{
#ifdef SERVER_DGA
WindowPtr pWin = (WindowPtr)LookupIDByType(win, RT_WINDOW);
if (!pWin)
return (BadCookie);
if (((DrawablePtr)pWin)->type == DRAWABLE_PIXMAP)
return (BadCookie);
return(DgaSharedRetained(pWin, 0, win));
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 3)
return 0;
LockDisplay(dpy);
GetResReq(DGA, win, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaUnGrabRetained;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00; /* Status */
#endif /* SERVER_DGA */
}
int
XDgaGetRetainedPath(dpy, win, path)
Display *dpy;
Window win;
char *path;
{
#ifdef SERVER_DGA
extern char *DgaSharedRetainedPath;
if (DgaSharedRetainedPath)
strcpy((char *)path, (char *)DgaSharedRetainedPath);
return 1;
#else
xResourceReq *req;
xDGARtndPathReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 3)
return 0;
LockDisplay(dpy);
GetResReq(DGA, win, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGetRetainedPath;
if (!_XReply(dpy, (xReply *) &rep,
(SIZEOF(xDGARtndPathReply) - SIZEOF(xReply)) >> 2, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
strcpy(path, (char *) rep.path);
return 1;
#endif /* SERVER_DGA */
}
int
XDgaQueryVersion(dpy, major_versionp, minor_versionp)
Display *dpy;
int *major_versionp,
*minor_versionp;
{
#ifdef SERVER_DGA
*major_versionp = SUN_DGA_MAJOR_VERSION;
*minor_versionp = SUN_DGA_MINOR_VERSION;
return(1);
#else
xDgaQueryVersionReply rep;
xDgaQueryVersionReq *req;
int opcode, tmp;
if (XQueryExtension(dpy, "SUN_DGA", &opcode, &tmp, &tmp) == 0)
return 0;
LockDisplay(dpy);
GetReq(DgaQueryVersion, req);
req->reqType = opcode;
req->dgaReqType = X_DgaQueryVersion;
if (!_XReply(dpy, (xReply *) & rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
*major_versionp = rep.majorVersion;
*minor_versionp = rep.minorVersion;
UnlockDisplay(dpy);
SyncHandle();
return 1;
#endif /* SERVER_DGA */
}
Dga_token
XDgaGrabPixmap(dpy, d)
Display *dpy;
Pixmap d;
{
#ifdef SERVER_DGA
int val;
PixmapPtr pPix = (PixmapPtr)LookupIDByType(d, RT_PIXMAP);
if (!pPix)
return (BadCookie);
if (((DrawablePtr)pPix)->type == DRAWABLE_WINDOW)
return (BadCookie);
val = DgaInitSharedPixmap(pPix, NEW);
if (val) {
if (dga_pixlist_add(val, dpy, d) == 0) {
XDgaUnGrabPixmap(dpy, d);
return 0;
}
}
return val;
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = init_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 3)
return 0;
LockDisplay(dpy);
GetResReq(DGA, d, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabPixmap;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
if (rep.data00) {
if (dga_pixlist_add(rep.data00, dpy, d) == 0) {
XDgaUnGrabPixmap(dpy, d);
return 0;
}
}
return rep.data00;
#endif /* SERVER_DGA */
}
int
XDgaUnGrabPixmap(dpy, d)
Display *dpy;
Pixmap d;
{
#ifdef SERVER_DGA
PixmapPtr pPix = (PixmapPtr)LookupIDByType(d, RT_PIXMAP);
int val;
if (!pPix)
return (BadCookie);
if (((DrawablePtr)pPix)->type == DRAWABLE_WINDOW)
return (BadCookie);
val = DgaDestroySharedPixmap(pPix);
if (val) {
if (dga_pixlist_free(dpy, d) == 0)
return 0;
}
return val;
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 3)
return 0;
LockDisplay(dpy);
GetResReq(DGA, d, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaUnGrabPixmap;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00; /* Status */
#endif /* SERVER_DGA */
}
static Dga_token
dgai_grabDrawRequest (Display *dpy, Drawable drawid, int *drawType)
{
#ifdef SERVER_DGA
DrawablePtr pDraw = (DrawablePtr)LookupIDByClass(drawid, RC_DRAWABLE);
if (!pDraw)
return(BadCookie);
return(DgaDrawGrab(drawid, pDraw, NEW, drawType));
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = init_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 3)
return 0;
LockDisplay(dpy);
GetResReq(DGA, drawid, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaGrabDrawable;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
/*
** data00 is the opaque token identifying the drawable shared file.
** data01 is the type of the drawable: window (0) or pixmap (1),
** (Note: an attempt to grab a multibuffer drawable XID will fail)
*/
if (rep.data00) {
*drawType = rep.data01;
}
return (rep.data00);
#endif /* SERVER_DGA */
}
static int
dgai_ungrabDrawRequest (Display *dpy, Drawable drawid)
{
#ifdef SERVER_DGA
DrawablePtr pDraw = (DrawablePtr)LookupIDByClass(drawid, RC_DRAWABLE);
if (!pDraw)
return(BadCookie);
return(DgaDrawUngrab(drawid, pDraw, NEW));
#else
xResourceReq *req;
xGenericReply rep;
struct dga_extinfo *extinfop;
if ((extinfop = lookup_dga_ext(dpy)) == NULL)
return 0;
if (extinfop->protocol_major_version < 3)
return 0;
LockDisplay(dpy);
GetResReq(DGA, drawid, req);
req->reqType = extinfop->major_opcode;
req->pad = X_DgaUnGrabDrawable;
if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
UnlockDisplay(dpy);
SyncHandle();
return rep.data00; /* Status */
#endif /* SERVER_DGA */
}
Dga_drawable
XDgaGrabDrawable(Display *dpy, Drawable drawid)
{
Dga_token token;
int drawType;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
if (!(token = dgai_grabDrawRequest(dpy, drawid, &drawType))) {
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return (NULL);
}
switch (drawType) {
case DGA_PROTO_OVERLAY:
case DGA_PROTO_WINDOW: {
_Dga_window dgawin;
if (!dga_winlist_add(token, dpy, (Window)drawid)) {
goto Bad;
}
if (!(dgawin = (_Dga_window) dgai_win_grab_common(dpy, -1, token, 1))) { goto Bad;
}
dgawin->w_dpy = dpy;
dgawin->w_id = (Window) drawid;
if (dgawin->isOverlay = (drawType == DGA_PROTO_OVERLAY)) {
dgawin->s_ovlstate_p = &((WXINFO *)dgawin->w_info)->w_ovlstate;
dgawin->s_ovlshapevalid_p =
&((WXINFO *)dgawin->w_info)->w_ovlshapevalid;
dgawin->ovlStateNotifyFunc = NULL;
}
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return ((Dga_drawable)dgawin);
}
case DGA_PROTO_PIXMAP: {
_Dga_pixmap dgapix;
if (!dga_pixlist_add(token, dpy, (Pixmap)drawid)) {
goto Bad;
}
if (!(dgapix = (_Dga_pixmap) dga_pix_grab(token, (Pixmap)drawid))) {
goto Bad;
}
dgapix->p_dpy = dpy;
dgapix->p_id = (Pixmap) drawid;
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return ((Dga_drawable)dgapix);
}
}
Bad:
(void) dgai_ungrabDrawRequest(dpy, drawid);
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return (NULL);
}
int
XDgaUnGrabDrawable(Dga_drawable dgadraw)
{
Drawable drawid = dga_draw_id(dgadraw);
Display *dpy = dga_draw_display(dgadraw);
int type = dga_draw_type(dgadraw);
int status;
#ifdef MT
mutex_lock(&dgaGlobalMutex);
#endif
switch (type) {
case DGA_DRAW_WINDOW:
case DGA_DRAW_OVERLAY:
dgai_win_ungrab_common((Dga_window)dgadraw, -1,1);
break;
case DGA_DRAW_PIXMAP:
dga_pix_ungrab((Dga_pixmap)dgadraw);
break;
}
status = dgai_ungrabDrawRequest(dpy, drawid);
#ifdef MT
mutex_unlock(&dgaGlobalMutex);
#endif
return (status);
}
static struct dga_xwinrec *dga_xwinlist = NULL;
static int
dga_winlist_add(token, dpy, win)
Dga_token token;
Display *dpy;
Window win;
{
struct dga_xwinrec *recp;
Display *listdpy;
Window listwin;
while (recp =
(struct dga_xwinrec *) _dga_is_X_window(token,&listdpy,&listwin)) {
if ((win == listwin) && (dpy == listdpy)) {
recp->refcnt += 1;
return 1; /* already in list */
}
dga_winlist_free(listdpy, listwin); /* remove bogus entry from list */
}
recp = (struct dga_xwinrec *) malloc(sizeof(struct dga_xwinrec));
if (recp == NULL)
return 0;
recp->next = dga_xwinlist;
dga_xwinlist = recp;
recp->token = token;
recp->dpy = dpy;
recp->win = win;
recp->refcnt = 1;
return 1;
}
/*
* Free dga_xwinrec structure for a particular window and display.
* If win is NULL free all entries on list for this display.
*/
static int
dga_winlist_free(dpy, win)
Display *dpy;
Window win;
{
struct dga_xwinrec *recp, **prevp;
int match = 0;
prevp = &dga_xwinlist;
recp = dga_xwinlist;
while (recp) {
if (recp->dpy == dpy) {
if (win == NULL) {
*prevp = recp->next;
free(recp);
match = 1;
}
else if (recp->win == win) {
if (--recp->refcnt == 0) {
*prevp = recp->next;
free(recp);
}
return 1;
}
else {
prevp = &recp->next;
}
}
else {
prevp = &recp->next;
}
recp = *prevp;
}
return (match);
}
void *
_dga_is_X_window(token, dpyp, winp)
Dga_token token;
Display **dpyp;
Window *winp;
{
struct dga_xwinrec *recp = dga_xwinlist;
while (recp) {
if (recp->token == token) {
*dpyp = recp->dpy;
*winp = recp->win;
return ((void *) recp);
}
recp = recp->next;
}
return 0;
}
static struct dga_xpixrec *dga_xpixlist = NULL;
/* REMIND DARYL: This routine is used to clean up "bogus" entries from
* list. Shouldn't that be done in Ungrab??? */
int
dga_pixlist_add(token, dpy, pix)
Dga_token token;
Display *dpy;
Pixmap pix;
{
struct dga_xpixrec *recp;
Display *listdpy;
if (recp = (struct dga_xpixrec *) _dga_is_X_pixmap(pix, &listdpy)) {
if (dpy == listdpy) {
recp->refcnt += 1;
return 1; /* already in list */
}
dga_pixlist_free(dpy, pix); /* remove bogus entry from list */
}
recp = (struct dga_xpixrec *) malloc(sizeof(struct dga_xpixrec));
if (recp == NULL)
return 0;
recp->next = dga_xpixlist;
dga_xpixlist = recp;
recp->token = token;
recp->dpy = dpy;
recp->pix = pix;
recp->refcnt = 1;
return 1;
}
static int
dga_pixlist_free(dpy, pix)
Display *dpy;
Pixmap pix;
{
struct dga_xpixrec *recp, **prevp;
int match = 0;
prevp = &dga_xpixlist;
recp = dga_xpixlist;
while (recp) {
if (recp->dpy == dpy) {
if (pix == NULL) {
*prevp = recp->next;
free(recp);
match = 1;
}
else if (recp->pix == pix) {
if (--recp->refcnt == 0) {
*prevp = recp->next;
free(recp);
}
return 1;
}
else {
prevp = &recp->next;
}
}
else {
prevp = &recp->next;
}
recp = *prevp;
}
return (match);
}
void *
_dga_is_X_pixmap(pix, dpyp)
Pixmap pix;
Display **dpyp;
{
struct dga_xpixrec *recp = dga_xpixlist;
while (recp) {
if (recp->pix == pix) {
*dpyp = recp->dpy;
return ((void *) recp);
}
recp = recp->next;
}
return 0;
}
#ifndef SERVER_DGA
/************************************
Addition to DGA for Xinerama extension.
This code allows the client to mine out
the window ID's that would normaly be
hidden from the user in Xinerama mode.
Xinerama keeps a list of WIDs that are
connected to a virtual WID that the user
gets to handle.
**************************************/
BOOL
XDgaGetXineramaInfo(dpy , VirtualWID, info )
Display *dpy;
XID VirtualWID;
XineramaInfo *info;
{
register xDgaXineramaInfoReq *req;
xDgaXineramaInfoReply *rep;
struct dga_extinfo *extinfop;
if ((extinfop = init_dga_ext(dpy)) == NULL)
return 0;
rep = malloc(sizeof(xDgaXineramaInfoReply));
LockDisplay(dpy);
GetReq(DgaXineramaInfo, req);
req->reqType = extinfop->major_opcode;
req->xdgaReqType = X_DgaXineramaInfo;
req->visual = VirtualWID;
if (!_XReply(dpy, (xReply *)rep, (sizeof(xDgaXineramaInfoReply)-32) >> 2,
xFalse))
{
UnlockDisplay(dpy);
SyncHandle();
Xfree(rep);
return NULL;
}
info->wid = VirtualWID;
memcpy(&info->subs[0],&rep->subs[0],(MAXSCREEN-1) * sizeof(SubWID));
UnlockDisplay(dpy);
SyncHandle();
free(rep);
return 1;
}
#endif