2004-08-23 01:37:23 +00:00
//network interface
# include "bothdefs.h"
# ifndef NOMEDIA
# include "qux.h"
# ifdef _WIN32
# define EWOULDBLOCK WSAEWOULDBLOCK
# define EMSGSIZE WSAEMSGSIZE
# define ECONNRESET WSAECONNRESET
# define ECONNABORTED WSAECONNABORTED
# define ECONNREFUSED WSAECONNREFUSED
# define EADDRNOTAVAIL WSAEADDRNOTAVAIL
# define qerrno WSAGetLastError()
# else
# define qerrno errno
# define MSG_PARTIAL 0
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
# include <sys/param.h>
# include <sys/ioctl.h>
# include <sys/uio.h>
# include <arpa/inet.h>
# include <errno.h>
# include <unistd.h>
# define closesocket close
# define ioctlsocket ioctl
# endif
# undef malloc
# undef free
# define free BZ_Free
# define malloc BZ_Malloc
# define realloc BZ_Realloc
static xclient_t * xclients ;
static int xlistensocket = - 1 ;
xwindow_t * xfocusedwindow ;
qboolean xrefreshed ;
xclient_t * xgrabbedclient ; //clients can ask the server to ignore other clients
# define MAXREQUESTSIZE 65535
void X_SendData ( xclient_t * cl , void * data , int datalen )
{
# ifdef MULTITHREADWIN32
if ( cl - > threadhandle )
EnterCriticalSection ( & cl - > delecatesection ) ;
# endif
if ( cl - > outbufferlen + datalen > cl - > outbuffermaxlen )
{ //extend buffer size
cl - > outbuffermaxlen = cl - > outbufferlen + datalen + 1024 ;
cl - > outbuffer = realloc ( cl - > outbuffer , cl - > outbuffermaxlen ) ;
}
memcpy ( cl - > outbuffer + cl - > outbufferlen , data , datalen ) ;
cl - > outbufferlen + = datalen ;
# ifdef MULTITHREADWIN32
if ( cl - > threadhandle )
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
}
void X_SendNotification ( xEvent * data )
{
xclient_t * cl ;
for ( cl = xclients ; cl ; cl = cl - > nextclient )
{
if ( cl - > stillinitialising )
continue ;
if ( cl - > tobedropped )
continue ;
if ( cl - > outbufferlen > MAXREQUESTSIZE * 4 )
continue ;
data - > u . u . sequenceNumber = cl - > requestnum ;
X_SendData ( cl , data , sizeof ( xEvent ) ) ;
}
}
qboolean X_NotifcationMaskPresent ( xwindow_t * window , int mask , xclient_t * notfor )
{
xnotificationmask_t * nm ;
nm = window - > notificationmask ;
if ( mask = = SubstructureNotifyMask | | mask = = SubstructureRedirectMask )
{
window = window - > parent ;
// for(;window;window=window->parent)
{
for ( nm = window - > notificationmask ; nm ; nm = nm - > next )
{
if ( nm - > mask & mask )
if ( nm - > client ! = notfor )
return true ;
}
}
}
else
{
for ( nm = window - > notificationmask ; nm ; nm = nm - > next )
{
if ( nm - > mask & mask )
if ( nm - > client ! = notfor )
return true ;
}
}
return false ;
}
int X_SendNotificationMasked ( xEvent * data , xwindow_t * window , unsigned int mask )
{
int count = 0 ;
xclient_t * cl ;
xnotificationmask_t * nm ;
xwindow_t * child = window ;
if ( mask = = SubstructureNotifyMask | | mask = = SubstructureRedirectMask )
{
for ( cl = xclients ; cl ; cl = cl - > nextclient )
{
//don't send to if...
if ( cl - > stillinitialising )
continue ;
if ( cl - > tobedropped )
continue ;
if ( cl - > outbufferlen > MAXREQUESTSIZE * 4 )
{
cl - > tobedropped = true ;
continue ;
}
window = child - > parent ;
// for (window = child; window; window = window->parent)
{
for ( nm = window - > notificationmask ; nm ; nm = nm - > next )
{
if ( nm - > client ! = cl )
continue ;
if ( ! ( nm - > mask & mask ) )
continue ;
data - > u . reparent . event = window - > res . id ; //so the request/notification/whatever knows who asked for it.
data - > u . u . sequenceNumber = cl - > requestnum ;
X_SendData ( cl , data , sizeof ( xEvent ) ) ;
count + + ;
break ;
}
// if (nm)
// break;
}
}
}
else
{
for ( nm = window - > notificationmask ; nm ; nm = nm - > next )
{
if ( ! ( nm - > mask & mask ) )
continue ;
cl = nm - > client ;
if ( cl - > stillinitialising )
continue ;
if ( cl - > tobedropped )
continue ;
if ( cl - > outbufferlen > MAXREQUESTSIZE * 4 )
{
cl - > tobedropped = true ;
continue ;
}
data - > u . u . sequenceNumber = cl - > requestnum ;
X_SendData ( cl , data , sizeof ( xEvent ) ) ;
count + + ;
}
}
return count ;
}
int X_SendInputNotification ( xEvent * data , xwindow_t * window , unsigned int mask )
{
int count = 0 ;
xclient_t * cl ;
xnotificationmask_t * nm ;
xwindow_t * child = window ;
xwindow_t * focus ;
//we go all the way to the root if needed.
for ( cl = xclients ; cl ; cl = cl - > nextclient )
{
//don't send to if...
if ( cl - > stillinitialising )
continue ;
if ( cl - > tobedropped )
continue ;
if ( cl - > outbufferlen > MAXREQUESTSIZE * 4 )
{
cl - > tobedropped = true ;
continue ;
}
window = child - > parent ;
for ( window = child ; window ; window = window - > parent )
{
for ( nm = window - > notificationmask ; nm ; nm = nm - > next )
{
if ( nm - > client ! = cl )
continue ;
if ( ! ( nm - > mask & mask ) )
continue ;
Con_Printf ( " Sending input %i \n " , data - > u . u . type ) ;
if ( data - > u . u . type = = FocusIn | | data - > u . u . type = = FocusOut )
{
data - > u . u . sequenceNumber = cl - > requestnum ;
X_SendData ( cl , data , sizeof ( xEvent ) ) ;
count + + ;
break ;
}
data - > u . keyButtonPointer . event = window - > res . id ; //so the request/notification/whatever knows who asked for it.
data - > u . keyButtonPointer . eventX = data - > u . keyButtonPointer . rootX ;
data - > u . keyButtonPointer . eventY = data - > u . keyButtonPointer . rootY ;
for ( window = window ; window ; window = window - > parent ) //adjust event's xpos/ypos
{
data - > u . keyButtonPointer . eventX - = window - > xpos ;
data - > u . keyButtonPointer . eventY - = window - > ypos ;
}
if ( data - > u . u . type = = EnterNotify | | data - > u . u . type = = LeaveNotify )
{
data - > u . enterLeave . flags & = ~ ELFlagFocus ;
focus = xfocusedwindow ;
while ( focus )
{
if ( focus - > res . id = = data - > u . enterLeave . event )
{
data - > u . enterLeave . flags | = ELFlagFocus ;
break ;
}
focus = focus - > parent ;
}
}
data - > u . u . sequenceNumber = cl - > requestnum ;
if ( data - > u . keyButtonPointer . event = = data - > u . keyButtonPointer . child )
{
data - > u . keyButtonPointer . child = None ;
X_SendData ( cl , data , sizeof ( xEvent ) ) ;
data - > u . keyButtonPointer . child = data - > u . keyButtonPointer . event ;
}
else
X_SendData ( cl , data , sizeof ( xEvent ) ) ;
count + + ;
break ;
}
if ( nm | | ( window - > donotpropagate & mask ) )
break ;
}
}
return count ;
}
void X_SendError ( xclient_t * cl , int errorcode , int assocresource , int major , int minor )
{
xError err ;
err . type = X_Error ;
err . errorCode = errorcode ;
err . sequenceNumber = cl - > requestnum ; /* the nth request from this client */
err . resourceID = assocresource ;
err . minorCode = minor ;
err . majorCode = major ;
err . pad1 = 0 ;
err . pad3 = 0 ;
err . pad4 = 0 ;
err . pad5 = 0 ;
err . pad6 = 0 ;
err . pad7 = 0 ;
X_SendData ( cl , & err , sizeof ( err ) ) ;
}
int X_NewRIDBase ( void )
{
xclient_t * cl ;
int ridbase = 0x200000 ;
while ( ridbase ) //it'll wrap at some point...
{
for ( cl = xclients ; cl ; cl = cl - > nextclient )
{
if ( cl - > ridbase = = ridbase ) //someone has this range...
{
ridbase + = 0x200000 ;
break ;
}
}
if ( ! cl )
return ridbase ;
}
//err... bugger... that could be problematic...
//try again, but start allocating half quantities and hope a client drops soon...
ridbase = 0x200000 ;
while ( ridbase )
{
for ( cl = xclients ; cl ; cl = cl - > nextclient )
{
if ( cl - > ridbase = = ridbase ) //someone has this range...
{
ridbase + = 0x100000 ;
break ; ;
}
}
if ( ! cl )
return ridbase ;
}
if ( ridbase )
return ridbase ;
return 0 ;
}
void X_SendIntialResponse ( xclient_t * cl )
{
int rid ;
char buffer [ 8192 ] ;
xConnSetupPrefix * prefix ;
xConnSetup * setup ;
char * vendor ;
xPixmapFormat * pixmapformats ;
xnotificationmask_t * nm ;
xWindowRoot * root ;
xDepth * depth ;
xVisualType * visualtype ;
rid = X_NewRIDBase ( ) ;
cl - > ridbase = rid ;
if ( ! rid )
{
prefix = ( xConnSetupPrefix * ) buffer ;
prefix - > success = 0 ;
prefix - > lengthReason = 22 ;
prefix - > majorVersion = 11 ; //protocol version.
prefix - > minorVersion = 0 ;
prefix - > length = ( prefix - > lengthReason / 4 + 3 ) & ~ 3 ;
strcpy ( ( char * ) ( prefix + 1 ) , " No free resource range " ) ;
X_SendData ( cl , prefix , sizeof ( prefix ) + ( prefix - > length + 1 ) * 4 ) ;
cl - > tobedropped = true ;
}
else
{
prefix = ( xConnSetupPrefix * ) buffer ;
prefix - > success = 1 ;
prefix - > lengthReason = 0 ;
prefix - > majorVersion = 11 ; //protocol version.
prefix - > minorVersion = 0 ;
setup = ( xConnSetup * ) ( prefix + 1 ) ;
setup - > release = build_number ( ) ; //our version number
setup - > ridBase = rid ;
setup - > ridMask = 0x1fffff ;
setup - > motionBufferSize = 1 ;
setup - > maxRequestSize = MAXREQUESTSIZE ;
setup - > numRoots = 1 ; //we only have one display. so only one root window please.
setup - > imageByteOrder = LSBFirst ; /* LSBFirst, MSBFirst */
setup - > bitmapBitOrder = LSBFirst ; /* LeastSignificant, MostSign...*/
setup - > bitmapScanlineUnit = 32 , /* 8, 16, 32 */
setup - > bitmapScanlinePad = 32 ; /* 8, 16, 32 */
setup - > minKeyCode = 1 ;
setup - > maxKeyCode = 255 ;
vendor = ( char * ) ( setup + 1 ) ;
strcpy ( vendor , " FTE QuakeWorld X " ) ;
setup - > nbytesVendor = ( strlen ( vendor ) + 3 ) & ~ 3 ;
pixmapformats = ( xPixmapFormat * ) ( vendor + setup - > nbytesVendor ) ;
setup - > numFormats = 0 ;
/* pixmapformats[setup->numFormats].depth = 16;
pixmapformats [ setup - > numFormats ] . bitsPerPixel = 16 ;
pixmapformats [ setup - > numFormats ] . scanLinePad = 16 ;
pixmapformats [ setup - > numFormats ] . pad1 = 0 ;
pixmapformats [ setup - > numFormats ] . pad2 = 0 ;
setup - > numFormats + + ; */
pixmapformats [ setup - > numFormats ] . depth = 24 ;
pixmapformats [ setup - > numFormats ] . bitsPerPixel = 32 ;
pixmapformats [ setup - > numFormats ] . scanLinePad = 32 ;
pixmapformats [ setup - > numFormats ] . pad1 = 0 ;
pixmapformats [ setup - > numFormats ] . pad2 = 0 ;
setup - > numFormats + + ;
root = ( xWindowRoot * ) ( pixmapformats + setup - > numFormats ) ;
root - > windowId = rootwindow - > res . id ;
root - > defaultColormap = 32 ;
root - > whitePixel = 0xffffff ;
root - > blackPixel = 0 ;
root - > currentInputMask = 0 ;
for ( nm = rootwindow - > notificationmask ; nm ; nm = nm - > next )
root - > currentInputMask | = nm - > mask ;
root - > pixWidth = rootwindow - > width ;
root - > pixHeight = rootwindow - > height ;
root - > mmWidth = rootwindow - > width / 3 ;
root - > mmHeight = rootwindow - > height / 3 ;
root - > minInstalledMaps = 1 ;
root - > maxInstalledMaps = 1 ;
root - > rootVisualID = 0x22 ;
root - > backingStore = 0 ;
root - > saveUnders = false ;
root - > rootDepth = 24 ;
root - > nDepths = 0 ;
depth = ( xDepth * ) ( root + 1 ) ;
depth - > depth = 24 ;
depth - > pad1 = 0 ;
depth - > nVisuals = 1 ;
depth - > pad2 = 0 ;
root - > nDepths + + ;
visualtype = ( xVisualType * ) ( depth + 1 ) ;
visualtype - > visualID = root - > rootVisualID ;
visualtype - > class = TrueColor ;
visualtype - > bitsPerRGB = 24 ;
visualtype - > colormapEntries = 256 ;
visualtype - > redMask = 0x0000ff ;
visualtype - > greenMask = 0x00ff00 ;
visualtype - > blueMask = 0xff0000 ;
visualtype - > pad = 0 ;
visualtype + + ;
prefix - > length = ( ( char * ) visualtype - ( char * ) setup ) / 4 ;
X_SendData ( cl , prefix , ( char * ) visualtype - ( char * ) prefix ) ;
}
}
qboolean XWindows_TendToClient ( xclient_t * cl ) //true says drop
{
int err ;
int len ;
unsigned int inlen ;
char * input ;
if ( ! xgrabbedclient | | xgrabbedclient = = cl ) //someone grabbed the server
if ( cl - > outbufferlen < 256 & & ! cl - > tobedropped ) //don't accept new messages if we still have a lot to write.
{
# ifdef MULTITHREADWIN32
if ( ! cl - > threadhandle )
# endif
{
if ( cl - > inbuffermaxlen - cl - > inbufferlen < 1000 ) //do we need to expand this message?
{
char * newbuffer ;
cl - > inbuffermaxlen + = 1000 ;
newbuffer = malloc ( cl - > inbuffermaxlen ) ;
if ( cl - > inbuffer )
{
memcpy ( newbuffer , cl - > inbuffer , cl - > inbufferlen ) ;
free ( cl - > inbuffer ) ;
}
cl - > inbuffer = newbuffer ;
}
len = cl - > inbuffermaxlen - cl - > inbufferlen ;
Con_Printf ( " recving \n " ) ;
len = recv ( cl - > socket , cl - > inbuffer + cl - > inbufferlen , len , 0 ) ;
Con_Printf ( " recved %i \n " , len ) ;
if ( len = = 0 ) //connection was closed. bummer.
{
Con_Printf ( " Closed \n " ) ;
return true ;
}
if ( len > 0 )
{
cl - > inbufferlen + = len ;
}
else
{
err = qerrno ;
if ( err ! = EWOULDBLOCK )
{
Con_Printf ( " X read error %i \n " , err ) ;
cl - > tobedropped = true ;
}
}
}
# ifdef MULTITHREADWIN32
else
EnterCriticalSection ( & cl - > delecatesection ) ;
# endif
// if (len > 0) //the correct version
if ( cl - > inbufferlen > 0 ) //temp
{
input = cl - > inbuffer ;
nextmessage :
inlen = cl - > inbufferlen - ( input - cl - > inbuffer ) ;
if ( cl - > stillinitialising )
{
if ( inlen > = sizeof ( xConnClientPrefix ) )
{
xConnClientPrefix * prefix = ( xConnClientPrefix * ) input ;
input + = sizeof ( xConnClientPrefix ) ;
cl - > stillinitialising = false ;
if ( prefix - > byteOrder ! = ' l ' ) //egad no. horrible.
{
# ifdef MULTITHREADWIN32
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
return true ;
}
if ( prefix - > majorVersion ! = 11 ) //x11 only. Sorry.
{
# ifdef MULTITHREADWIN32
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
return true ;
}
if ( prefix - > minorVersion ! = 0 ) //we don't know of any variations.
{
# ifdef MULTITHREADWIN32
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
return true ;
}
if ( prefix - > nbytesAuthProto ! = 0 ) //we can't handle this
{
# ifdef MULTITHREADWIN32
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
return true ;
}
if ( prefix - > nbytesAuthString ! = 0 ) //we can't handle this
{
# ifdef MULTITHREADWIN32
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
return true ;
}
X_SendIntialResponse ( cl ) ;
goto nextmessage ;
}
}
else if ( inlen > = sizeof ( xReq ) )
{
int rlen ;
xReq * req ;
req = ( xReq * ) input ;
rlen = req - > length ;
if ( ! rlen & & inlen > = sizeof ( xReq ) + sizeof ( CARD32 ) ) //BIG-REQUESTS says that if the length of a request is 0, then there's an extra 32bit int with the correct length imediatly after the 0.
rlen = * ( CARD32 * ) ( req + 1 ) ;
if ( rlen & & inlen > = rlen * 4 )
{
cl - > requestnum + + ;
2004-09-20 23:25:38 +00:00
/* if (req->reqType < 0 || req->reqType >= 256 || !XRequests[req->reqType])
2004-08-23 01:37:23 +00:00
{
// Con_Printf("X request %i, len %i - NOT SUPPORTED\n", req->reqType, rlen*4);
//this is a minimal implementation...
X_SendError ( cl , BadImplementation , 0 , req - > reqType , 0 ) ;
// cl->tobedropped = true;
}
else
2004-09-20 23:25:38 +00:00
*/
2004-08-23 01:37:23 +00:00
{
// Con_Printf("X request %i, len %i\n", req->reqType, rlen*4);
//Con_Printf("Request %i\n", req->reqType);
// Z_CheckSentinals();
if ( ! req - > length )
{
int rt , data ;
rt = req - > reqType ; //save these off
data = req - > data ;
req = ( xReq * ) ( ( char * ) req + sizeof ( CARD32 ) ) ; //adjust correctly.
req - > reqType = rt ; //and restore them into the space taken by the longer size.
req - > data = data ;
req - > length = 0 ; //Don't rely on this. This isn't really needed.
XRequests [ req - > reqType ] ( cl , req ) ;
}
else
XRequests [ req - > reqType ] ( cl , req ) ;
// Z_CheckSentinals();
//Con_Printf("Done request\n");
}
input + = rlen * 4 ;
goto nextmessage ;
}
}
len = input - cl - > inbuffer ;
memmove ( cl - > inbuffer , input , cl - > inbufferlen - len ) ;
cl - > inbufferlen - = len ;
}
# ifdef MULTITHREADWIN32
if ( cl - > threadhandle )
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
}
if ( cl - > outbufferlen ) //still send if grabbed. don't let things build up this side.
{
# ifdef MULTITHREADWIN32
if ( ! cl - > threadhandle )
# endif
{
len = cl - > outbufferlen ;
if ( len > 8000 )
len = 8000 ;
len = send ( cl - > socket , cl - > outbuffer , len , 0 ) ;
if ( len > 0 )
{
memmove ( cl - > outbuffer , cl - > outbuffer + len , cl - > outbufferlen - len ) ;
cl - > outbufferlen - = len ;
}
if ( len = = 0 )
cl - > tobedropped = true ;
if ( len < 0 )
{
err = qerrno ;
if ( err ! = EWOULDBLOCK )
{
Con_Printf ( " X send error %i \n " , err ) ;
cl - > tobedropped = true ;
}
}
}
}
else if ( ( ! xgrabbedclient | | xgrabbedclient = = cl ) & & cl - > tobedropped )
return true ; //grabbed servers do not allow altering state if a client drops
return false ;
}
# ifdef MULTITHREAD
# ifdef _WIN32
DWORD WINAPI X_RunClient ( void * parm )
# else
void X_RunClient ( void * parm )
# endif
{
char buffer [ 8192 * 64 ] ;
int read , len , err ;
xclient_t * cl = parm ;
while ( cl - > threadhandle )
{
if ( cl - > tobedropped )
{ //don't bother reading more.
read = 0 ;
}
else
{
read = recv ( cl - > socket , buffer , sizeof ( buffer ) , 0 ) ;
if ( read < 0 & & ! cl - > outbufferlen )
{
if ( qerrno ! = EWOULDBLOCK )
cl - > tobedropped = true ;
else
{
Sleep ( 1 ) ;
continue ;
}
}
}
# ifdef MULTITHREADWIN32
EnterCriticalSection ( & cl - > delecatesection ) ;
# endif
if ( read > 0 )
{
if ( cl - > inbuffermaxlen < cl - > inbufferlen + read ) //expand in buffer
{
cl - > inbuffermaxlen = cl - > inbufferlen + read + 1000 ; //add breathing room.
cl - > inbuffer = realloc ( cl - > inbuffer , cl - > inbuffermaxlen ) ;
}
memcpy ( cl - > inbuffer + cl - > inbufferlen , buffer , read ) ;
cl - > inbufferlen + = read ;
}
else if ( ! read ) //no more socket.
cl - > tobedropped = true ;
else
{ //error of some sort
err = qerrno ;
if ( err ! = EWOULDBLOCK )
cl - > tobedropped = true ;
}
if ( cl - > outbufferlen )
{
len = cl - > outbufferlen ;
if ( len > 8000 )
len = 8000 ;
len = send ( cl - > socket , cl - > outbuffer , len , 0 ) ; //move out of critical section?
if ( len > 0 )
{
memmove ( cl - > outbuffer , cl - > outbuffer + len , cl - > outbufferlen - len ) ;
cl - > outbufferlen - = len ;
}
if ( len = = 0 )
{
cl - > tobedropped = true ;
cl - > outbufferlen = 0 ;
}
if ( len < 0 )
{
err = qerrno ;
if ( err ! = EWOULDBLOCK )
{
cl - > tobedropped = true ;
cl - > outbufferlen = 0 ;
}
}
}
# ifdef MULTITHREADWIN32
LeaveCriticalSection ( & cl - > delecatesection ) ;
# endif
}
DeleteCriticalSection ( & cl - > delecatesection ) ;
closesocket ( cl - > socket ) ;
if ( cl - > inbuffer )
free ( cl - > inbuffer ) ;
if ( cl - > outbuffer )
free ( cl - > outbuffer ) ;
free ( cl ) ;
# ifdef MULTITHREADWIN32
return 0 ;
# endif
}
# endif
void XWindows_TendToClients ( void )
{
struct sockaddr_in address ;
int addrlen ;
xclient_t * cl , * prev = NULL ;
int newclient ;
2004-09-20 23:25:38 +00:00
# ifndef MULTITHREADWIN32
2004-08-23 01:37:23 +00:00
unsigned int _true = 1 ;
2004-09-20 23:25:38 +00:00
# endif
2004-08-23 01:37:23 +00:00
if ( xlistensocket ! = - 1 )
{
addrlen = sizeof ( address ) ;
newclient = accept ( xlistensocket , ( struct sockaddr * ) & address , & addrlen ) ;
if ( newclient ! = - 1 )
{
cl = malloc ( sizeof ( xclient_t ) ) ;
memset ( cl , 0 , sizeof ( xclient_t ) ) ;
cl - > socket = newclient ;
cl - > nextclient = xclients ;
cl - > stillinitialising = 1 ;
xclients = cl ;
# ifdef MULTITHREADWIN32
InitializeCriticalSection ( & cl - > delecatesection ) ;
2004-09-20 23:25:38 +00:00
{ DWORD tid ;
2004-08-23 01:37:23 +00:00
cl - > threadhandle = CreateThread ( NULL , 0 , X_RunClient , cl , 0 , & tid ) ;
}
if ( ! cl - > threadhandle )
DeleteCriticalSection ( & cl - > delecatesection ) ;
# else
if ( ioctlsocket ( cl - > socket , FIONBIO , & _true ) = = - 1 )
Sys_Error ( " Nonblocking failed \n " ) ;
# endif
}
}
for ( cl = xclients ; cl ; cl = cl - > nextclient )
{
if ( XWindows_TendToClient ( cl ) )
{
if ( prev )
{
prev - > nextclient = cl - > nextclient ;
}
else
xclients = cl - > nextclient ;
XS_DestroyResourcesOfClient ( cl ) ;
# ifdef MULTITHREADWIN32
if ( cl - > threadhandle )
{
cl - > threadhandle = NULL ;
break ;
}
# endif
closesocket ( cl - > socket ) ;
if ( cl - > inbuffer )
free ( cl - > inbuffer ) ;
if ( cl - > outbuffer )
free ( cl - > outbuffer ) ;
free ( cl ) ;
break ;
}
prev = cl ;
}
}
void XWindows_Startup ( void ) //initialise the server socket and do any initial setup as required.
{
struct sockaddr_in address ;
unsigned long _true = true ;
int port = 6000 ;
port + = atoi ( Cmd_Argv ( 1 ) ) ;
if ( xlistensocket = = - 1 )
{
if ( ( xlistensocket = socket ( AF_INET , SOCK_STREAM , IPPROTO_TCP ) ) = = - 1 )
{
Con_Printf ( " Failed to create socket \n " ) ;
return ;
}
if ( ioctlsocket ( xlistensocket , FIONBIO , & _true ) = = - 1 )
{
closesocket ( xlistensocket ) ;
Con_Printf ( " Failed to create socket \n " ) ;
xlistensocket = - 1 ;
return ;
}
address . sin_family = AF_INET ;
address . sin_addr . s_addr = INADDR_ANY ;
if ( port = = PORT_ANY )
address . sin_port = 0 ;
else
address . sin_port = htons ( ( short ) port ) ;
if ( bind ( xlistensocket , ( void * ) & address , sizeof ( address ) ) = = - 1 )
{
Con_Printf ( " Couldn't bind socket to port %i \n " , port ) ;
closesocket ( xlistensocket ) ;
xlistensocket = - 1 ;
return ;
}
if ( listen ( xlistensocket , 3 ) = = - 1 )
{
Con_Printf ( " Couldn't listen on port %i \n " , port ) ;
closesocket ( xlistensocket ) ;
xlistensocket = - 1 ;
return ;
}
X_InitRequests ( ) ;
XS_CreateInitialResources ( ) ;
}
//quakie stuph
key_dest = key_menu ;
m_state = m_xwindows ;
m_entersound = true ;
}
extern int x_windowwithfocus ;
extern int x_windowwithcursor ;
void XWindows_RefreshWindow ( xwindow_t * wnd )
{
xwindow_t * p ;
short xpos ;
short ypos ;
unsigned int * out , * in ;
int x , y ;
int maxx , maxy ;
if ( wnd - > inputonly ) //no thanks.
return ;
xpos = 0 ;
ypos = 0 ;
for ( p = wnd - > parent ; p ; p = p - > parent )
{
xpos + = p - > xpos ;
ypos + = p - > ypos ;
}
y = ypos + wnd - > ypos ;
maxy = y + wnd - > height ;
if ( y < ypos + wnd - > ypos )
{
y = ypos + wnd - > ypos ;
}
if ( y < 0 )
y = 0 ;
if ( maxy > = xscreenheight )
maxy = xscreenheight - 1 ;
if ( ! wnd - > mapped ) //&&rand()&1)
{ //unmapped windows are invisible.
return ;
}
{
if ( wnd - > buffer ) // && x_windowwithfocus != wnd->res.id)
{
for ( ; y < maxy ; y + + )
{
x = xpos + wnd - > xpos ;
maxx = x + wnd - > width ;
if ( x < xpos + wnd - > xpos )
{
x = xpos + wnd - > xpos ;
}
if ( x < 0 )
x = 0 ;
if ( maxx > xscreenwidth )
maxx = xscreenwidth ;
out = ( unsigned int * ) xscreen + ( x + ( y * xscreenwidth ) ) ;
in = ( unsigned int * ) wnd - > buffer + ( x - xpos - wnd - > xpos ) + ( y - ypos - wnd - > ypos ) * wnd - > width ;
for ( ; x < maxx ; x + + )
{
* out + + = * in + + ;
}
}
}
else
{
for ( ; y < maxy ; y + + )
{
x = xpos + wnd - > xpos ;
maxx = x + wnd - > width ;
if ( x < xpos + wnd - > xpos )
{
x = xpos + wnd - > xpos ;
}
if ( x < 0 )
{
x = 0 ;
}
if ( maxx > xscreenwidth )
maxx = xscreenwidth ;
out = ( unsigned int * ) xscreen + ( x + ( y * xscreenwidth ) ) ;
for ( ; x < maxx ; x + + )
{
* out + + = wnd - > backpixel ;
}
}
}
}
wnd = wnd - > child ;
while ( wnd )
{
XWindows_RefreshWindow ( wnd ) ;
wnd = wnd - > sibling ;
}
}
/*
void XWindows_DrawWindowTree ( xwindow_t * wnd , short xofs , short yofs )
{
int x , y ;
int maxx , maxy ;
unsigned int * out ;
if ( wnd - > res . owner )
{
y = yofs + wnd - > ypos ;
maxy = y + wnd - > width ;
if ( y < 0 )
{
y = 0 ;
}
if ( maxy > = xscreenheight )
maxy = xscreenheight - 1 ;
for ( y = 0 ; y < wnd - > height ; y + + )
{
x = xofs + wnd - > xpos ;
maxx = x + wnd - > height ;
if ( x < 0 )
{
x = 0 ;
}
if ( maxx > = xscreenwidth )
maxx = xscreenwidth - 1 ;
out = ( unsigned int * ) xscreen + ( x + ( y * xscreenwidth ) ) ;
for ( ; x < maxx ; x + + )
{
* out = rand ( ) ;
out + + ;
}
}
}
xofs + = wnd - > xpos ;
yofs + = wnd - > ypos ;
wnd = wnd - > child ;
while ( wnd )
{
XWindows_DrawWindowTree ( wnd , xofs , yofs ) ;
wnd = wnd - > sibling ;
}
}
*/
//quakie functions
void XWindows_Init ( void )
{
2004-10-07 07:06:19 +00:00
Cmd_AddCommand ( " startx " , XWindows_Startup ) ;
2004-08-23 01:37:23 +00:00
}
int x_mousex ;
int x_mousey ;
int x_windowwithcursor ;
int x_windowwithfocus ;
int mousestate ;
void X_EvalutateCursorOwner ( int movemode )
{
xEvent ev ;
xwindow_t * cursorowner , * wnd , * use ;
int mx , my ;
int wcx ;
int wcy ;
2004-09-20 23:25:38 +00:00
extern xwindow_t * xpconfinewindow ;
2004-08-23 01:37:23 +00:00
{
extern int mousecursor_x , mousecursor_y ;
mx = mousecursor_x * ( ( float ) rootwindow - > width / vid . width ) ;
my = mousecursor_y * ( ( float ) rootwindow - > height / vid . height ) ;
}
if ( mx > = xscreenwidth )
mx = xscreenwidth - 1 ;
if ( my > = xscreenheight )
my = xscreenheight - 1 ;
if ( mx < 0 )
mx = 0 ;
if ( my < 0 )
my = 0 ;
if ( xpconfinewindow ) //don't leave me!
{
cursorowner = xpconfinewindow ;
wcx = 0 ; wcy = 0 ;
for ( wnd = cursorowner ; wnd ; wnd = wnd - > parent )
{
wcx + = wnd - > xpos ;
wcy + = wnd - > ypos ;
}
if ( movemode = = NotifyNormal )
movemode = NotifyWhileGrabbed ;
}
else
{
cursorowner = rootwindow ;
wcx = 0 ; wcy = 0 ;
while ( 1 )
{
use = NULL ;
//find the last window that contains the pointer (lower windows come first)
for ( wnd = cursorowner - > child ; wnd ; wnd = wnd - > sibling )
{
if ( /*!wnd->inputonly && */ wnd - > mapped )
if ( wcx + wnd - > xpos < = mx & & wcx + wnd - > xpos + wnd - > width > = mx )
{
if ( wcy + wnd - > ypos < = my & & wcy + wnd - > ypos + wnd - > height > = my )
{
use = wnd ;
}
}
}
wnd = use ;
if ( wnd )
{
cursorowner = wnd ;
wcx + = wnd - > xpos ;
wcy + = wnd - > ypos ;
continue ;
}
break ;
}
}
if ( mx ! = x_mousex | | my ! = x_mousey | | x_windowwithcursor ! = cursorowner - > res . id )
{
2004-09-20 23:25:38 +00:00
// extern qboolean keydown[256];
2004-08-23 01:37:23 +00:00
// Con_Printf("move %i %i\n", mx, my);
ev . u . u . detail = 0 ;
ev . u . u . sequenceNumber = 0 ;
ev . u . keyButtonPointer . time = Sys_DoubleTime ( ) * 1000 ;
ev . u . keyButtonPointer . root = rootwindow - > res . id ;
ev . u . keyButtonPointer . child = None ;
ev . u . keyButtonPointer . rootX = mx ;
ev . u . keyButtonPointer . rootY = my ;
ev . u . keyButtonPointer . state = mousestate ;
if ( cursorowner - > res . id ! = x_windowwithcursor ) //changed window
{
xwindow_t * a , * b ;
int d1 , d2 ;
2004-09-20 23:25:38 +00:00
if ( XS_GetResource ( x_windowwithcursor , ( void * * ) & wnd ) ! = x_window )
2004-08-23 01:37:23 +00:00
wnd = rootwindow ;
x_windowwithcursor = cursorowner - > res . id ;
//count how deep the windows are
for ( a = wnd , d1 = 0 ; a ; a = a - > parent )
d1 + + ;
for ( b = cursorowner , d2 = 0 ; b ; b = b - > parent )
d2 + + ;
a = wnd ;
b = cursorowner ;
if ( d1 > d2 )
{
while ( d1 > d2 ) //a is too deep
{
a = a - > parent ;
d1 - - ;
}
}
else
{
while ( d2 > d1 )
{
b = b - > parent ;
d2 - - ;
}
}
while ( a ! = b ) //find the common ancestor.
{
a = a - > parent ;
b = b - > parent ;
}
ev . u . enterLeave . mode = movemode ;
ev . u . enterLeave . flags = ELFlagSameScreen ; /* sameScreen and focus booleans, packed together */
//the cursor moved from a to b via:
// if (!a) //changed screen...
// {
// } else
if ( a ! = wnd & & b ! = cursorowner )
{ //changed via a common root, indirectly.
//o LeaveNotify with detail Nonlinear is generated on A.
ev . u . u . type = LeaveNotify ;
ev . u . u . detail = NotifyNonlinear ;
ev . u . keyButtonPointer . child = wnd - > res . id ;
X_SendInputNotification ( & ev , wnd , LeaveWindowMask ) ;
//o LeaveNotify with detail NonlinearVirtual is generated
// on each window between A and C exclusive (in that
// order).
for ( a = wnd - > parent ; a ! = b ; a = a - > parent )
{
ev . u . u . type = LeaveNotify ;
ev . u . u . detail = NotifyNonlinearVirtual ;
ev . u . keyButtonPointer . child = a - > res . id ;
X_SendInputNotification ( & ev , a , LeaveWindowMask ) ;
}
//o EnterNotify with detail NonlinearVirtual is generated
// on each window between C and B exclusive (in that
// order).
for ( ; b ! = cursorowner ; )
{
for ( a = cursorowner ; ; a = a - > parent ) //we need to go through the children.
{
if ( a - > parent = = b )
{
b = a ;
break ;
}
}
if ( b = = cursorowner )
break ;
ev . u . u . type = EnterNotify ;
ev . u . u . detail = NotifyNonlinearVirtual ;
ev . u . keyButtonPointer . child = a - > res . id ;
X_SendInputNotification ( & ev , a , EnterWindowMask ) ;
}
//o EnterNotify with detail Nonlinear is generated on B.
ev . u . u . type = EnterNotify ;
ev . u . u . detail = NotifyNonlinear ;
ev . u . keyButtonPointer . child = cursorowner - > res . id ;
X_SendInputNotification ( & ev , cursorowner , EnterWindowMask ) ;
}
else if ( a = = wnd )
{ //b is a child of a
//o LeaveNotify with detail Inferior is generated on A.
ev . u . u . type = LeaveNotify ;
ev . u . u . detail = NotifyInferior ;
ev . u . keyButtonPointer . child = wnd - > res . id ;
X_SendInputNotification ( & ev , wnd , LeaveWindowMask ) ;
//o EnterNotify with detail Virtual is generated on each
// window between A and B exclusive (in that order).
if ( wnd ! = cursorowner )
for ( b = wnd ; ; )
{
for ( a = cursorowner ; ; a = a - > parent ) //we need to go through the children.
{
if ( a - > parent = = b )
{
b = a ;
break ;
}
}
if ( b = = cursorowner )
break ;
ev . u . u . type = EnterNotify ;
ev . u . u . detail = NotifyVirtual ;
ev . u . keyButtonPointer . child = b - > res . id ;
X_SendInputNotification ( & ev , b , EnterWindowMask ) ;
}
//o EnterNotify with detail Ancestor is generated on B.
ev . u . u . type = EnterNotify ;
ev . u . u . detail = NotifyAncestor ;
ev . u . keyButtonPointer . child = cursorowner - > res . id ;
X_SendInputNotification ( & ev , cursorowner , EnterWindowMask ) ;
}
else // if (b == cursorowner)
{ //a is a child of b
//o LeaveNotify with detail Ancestor is generated on A.
ev . u . u . type = LeaveNotify ;
ev . u . u . detail = NotifyAncestor ;
ev . u . keyButtonPointer . child = wnd - > res . id ;
X_SendInputNotification ( & ev , wnd , LeaveWindowMask ) ;
//o LeaveNotify with detail Virtual is generated on each
// window between A and B exclusive (in that order).
for ( b = wnd ; ; )
{
b = b - > parent ;
if ( b = = cursorowner )
break ;
ev . u . u . type = LeaveNotify ;
ev . u . u . detail = NotifyVirtual ;
ev . u . keyButtonPointer . child = b - > res . id ;
X_SendInputNotification ( & ev , b , LeaveWindowMask ) ;
}
//o EnterNotify with detail Inferior is generated on B.
ev . u . u . type = EnterNotify ;
ev . u . u . detail = NotifyInferior ;
ev . u . keyButtonPointer . child = cursorowner - > res . id ;
X_SendInputNotification ( & ev , cursorowner , EnterWindowMask ) ;
}
{
char title [ 1024 ] ;
Atom type ;
int extrabytes ;
int format ;
while ( cursorowner )
{
title [ XS_GetProperty ( cursorowner , 39 , & type , title , sizeof ( title ) , 0 , & extrabytes , & format ) ] = ' \0 ' ;
if ( * title )
break ;
cursorowner = cursorowner - > parent ;
}
Con_Printf ( " Entered \" %s \" \n " , title ) ;
}
}
{ //same window
ev . u . keyButtonPointer . child = x_windowwithcursor ;
2004-09-20 23:25:38 +00:00
if ( XS_GetResource ( x_windowwithcursor , ( void * * ) & wnd ) = = x_window )
2004-08-23 01:37:23 +00:00
{ //cursor still in the same child.
int mask = PointerMotionMask ;
if ( mousestate )
mask | = ButtonMotionMask ;
if ( mousestate & Button1Mask )
mask | = Button1MotionMask ;
if ( mousestate & Button2Mask )
mask | = Button2MotionMask ;
if ( mousestate & Button3Mask )
mask | = Button3MotionMask ;
if ( mousestate & Button4Mask )
mask | = Button4MotionMask ;
if ( mousestate & Button5Mask )
mask | = Button5MotionMask ;
ev . u . u . type = MotionNotify ;
X_SendInputNotification ( & ev , wnd , mask ) ;
}
}
x_mousex = mx ;
x_mousey = my ;
}
}
void X_EvalutateFocus ( int movemode )
{
xEvent ev ;
xwindow_t * fo , * po , * wnd ;
2004-09-20 23:25:38 +00:00
if ( XS_GetResource ( x_windowwithcursor , ( void * * ) & po ) ! = x_window )
2004-08-23 01:37:23 +00:00
po = rootwindow ;
// xfocusedwindow = NULL;
if ( ! xfocusedwindow )
{
2004-09-20 23:25:38 +00:00
if ( XS_GetResource ( x_windowwithcursor , ( void * * ) & fo ) ! = x_window )
2004-08-23 01:37:23 +00:00
fo = rootwindow ;
}
else
{
fo = xfocusedwindow ;
}
if ( x_windowwithfocus ! = fo - > res . id )
{
ev . u . u . detail = 0 ;
ev . u . u . sequenceNumber = 0 ;
ev . u . focus . mode = movemode ;
{
xwindow_t * a , * b ;
int d1 , d2 ;
2004-09-20 23:25:38 +00:00
if ( XS_GetResource ( x_windowwithfocus , ( void * * ) & wnd ) ! = x_window )
2004-08-23 01:37:23 +00:00
wnd = rootwindow ;
x_windowwithfocus = fo - > res . id ;
//count how deep the windows are
for ( a = wnd , d1 = 0 ; a ; a = a - > parent )
d1 + + ;
for ( b = fo , d2 = 0 ; b ; b = b - > parent )
d2 + + ;
a = wnd ;
b = fo ;
if ( d1 > d2 )
{
while ( d1 > d2 ) //a is too deep
{
a = a - > parent ;
d1 - - ;
}
}
else
{
while ( d2 > d1 )
{
b = b - > parent ;
d2 - - ;
}
}
while ( a ! = b ) //find the common ancestor.
{
a = a - > parent ;
b = b - > parent ;
}
ev . u . enterLeave . mode = movemode ;
ev . u . enterLeave . flags = ELFlagSameScreen ; /* sameScreen and focus booleans, packed together */
//the cursor moved from a to b via:
// if (!a) //changed screen...
// {
// } else
if ( a ! = wnd & & b ! = fo )
{ //changed via a common root, indirectly.
//When the focus moves from window A to window B, window C is
//their least common ancestor, and the pointer is in window P:
//o If P is an inferior of A, FocusOut with detail Pointer
// is generated on each window from P up to but not
// including A (in order).
//FIXME
//o FocusOut with detail Nonlinear is generated on A.
ev . u . u . type = FocusOut ;
ev . u . u . detail = NotifyNonlinear ;
ev . u . focus . window = wnd - > res . id ;
X_SendInputNotification ( & ev , wnd , FocusChangeMask ) ;
//o FocusOut with detail NonlinearVirtual is generated on
// each window between A and C exclusive (in order).
for ( a = wnd - > parent ; a ! = b ; a = a - > parent )
{
ev . u . u . type = FocusOut ;
ev . u . u . detail = NotifyNonlinearVirtual ;
ev . u . focus . window = a - > res . id ;
X_SendInputNotification ( & ev , a , FocusChangeMask ) ;
}
//o FocusIn with detail NonlinearVirtual is generated on
// each window between C and B exclusive (in order).
for ( ; b ! = fo ; )
{
ev . u . u . type = FocusIn ;
ev . u . u . detail = NotifyNonlinearVirtual ;
ev . u . focus . window = a - > res . id ;
X_SendInputNotification ( & ev , a , FocusChangeMask ) ;
for ( a = fo ; ; a = a - > parent ) //we need to go through the children.
{
if ( a - > parent = = b )
{
b = a ;
break ;
}
}
}
//o FocusIn with detail Nonlinear is generated on B.
ev . u . u . type = FocusIn ;
ev . u . u . detail = NotifyNonlinear ;
ev . u . focus . window = fo - > res . id ;
X_SendInputNotification ( & ev , fo , FocusChangeMask ) ;
//o If P is an inferior of B, FocusIn with detail Pointer
// is generated on each window below B down to and includ-
// ing P (in order).
//FIXME:
}
else if ( a = = wnd )
{ //b is a child of a
//When the focus moves from window A to window B, B is an
//inferior of A, and the pointer is in window P:
//o If P is an inferior of A but P is not an inferior of B
// or an ancestor of B, FocusOut with detail Pointer is
// generated on each window from P up to but not including
// A (in order).
//FIXME
//o FocusOut with detail Inferior is generated on A.
ev . u . u . type = FocusOut ;
ev . u . u . detail = NotifyInferior ;
ev . u . focus . window = wnd - > res . id ;
X_SendInputNotification ( & ev , wnd , FocusChangeMask ) ;
//o FocusIn with detail Virtual is generated on each window
// between A and B exclusive (in order).
if ( wnd ! = fo )
for ( b = wnd ; ; )
{
for ( a = fo ; ; a = a - > parent ) //we need to go through the children.
{
if ( a - > parent = = b )
{
b = a ;
break ;
}
}
if ( b = = fo )
break ;
ev . u . u . type = FocusIn ;
ev . u . u . detail = NotifyVirtual ;
ev . u . focus . window = b - > res . id ;
X_SendInputNotification ( & ev , b , FocusChangeMask ) ;
}
//o FocusIn with detail Ancestor is generated on B.
ev . u . u . type = FocusIn ;
ev . u . u . detail = NotifyAncestor ;
ev . u . focus . window = fo - > res . id ;
X_SendInputNotification ( & ev , fo , FocusChangeMask ) ;
}
else // if (b == cursorowner)
{ //a is a child of b
//When the focus moves from window A to window B, A is an
//inferior of B, and the pointer is in window P:
//o FocusOut with detail Ancestor is generated on A.
ev . u . u . type = FocusOut ;
ev . u . u . detail = NotifyAncestor ;
ev . u . focus . window = wnd - > res . id ;
X_SendInputNotification ( & ev , wnd , FocusChangeMask ) ;
//o FocusOut with detail Virtual is generated on each win-
// dow between A and B exclusive (in order).
for ( b = wnd ; ; )
{
b = b - > parent ;
if ( b = = fo )
break ;
ev . u . u . type = FocusOut ;
ev . u . u . detail = NotifyVirtual ;
ev . u . focus . window = a - > res . id ;
X_SendInputNotification ( & ev , a , FocusChangeMask ) ;
}
//o FocusIn with detail Inferior is generated on B.
ev . u . u . type = FocusIn ;
ev . u . u . detail = NotifyInferior ;
ev . u . focus . window = fo - > res . id ;
X_SendInputNotification ( & ev , fo , FocusChangeMask ) ;
//o If P is an inferior of B but P is not A or an inferior
// of A or an ancestor of A, FocusIn with detail Pointer
// is generated on each window below B down to and includ-
// ing P (in order).
//FIXME: code missing
}
}
}
}
void XWindows_Draw ( void )
{
{
X_EvalutateCursorOwner ( NotifyNormal ) ;
}
XWindows_TendToClients ( ) ;
/* if (rand()&15 == 15)
xrefreshed = true ; */
// memset(xscreen, 0, xscreenwidth*4*xscreenheight);
XWindows_TendToClients ( ) ;
// XW_ExposeWindow(rootwindow, 0, 0, rootwindow->width, rootwindow->height);
// XWindows_DrawWindowTree(rootwindow, 0, 0);
if ( xrefreshed )
{
XWindows_RefreshWindow ( rootwindow ) ;
xrefreshed = false ;
// Con_Printf("updated screen\n");
}
{
unsigned int * out = ( unsigned int * ) xscreen + ( x_mousex + ( x_mousey * xscreenwidth ) ) ;
* out = rand ( ) ;
// out[64] = rand();
}
XWindows_TendToClients ( ) ;
2004-09-20 23:25:38 +00:00
Media_ShowFrameRGBA_32 ( xscreen , xscreenwidth , xscreenheight ) ;
2004-08-23 01:37:23 +00:00
Con_DrawNotify ( ) ;
XWindows_TendToClients ( ) ;
}
void XWindows_Key ( int key )
{
extern qboolean keydown [ 256 ] ;
if ( key = = ' q ' | | ( key = = K_BACKSPACE & & keydown [ K_CTRL ] & & keydown [ K_ALT ] ) ) //kill off the server
{
m_state = m_none ;
key_dest = key_game ;
closesocket ( xlistensocket ) ;
xlistensocket = - 1 ;
}
{
xEvent ev ;
xwindow_t * wnd ;
X_EvalutateCursorOwner ( NotifyNormal ) ;
X_EvalutateFocus ( NotifyNormal ) ;
if ( key > = K_MOUSE1 & & key < = K_MOUSE5 )
{
ev . u . u . type = ButtonPress ;
switch ( key )
{
case K_MOUSE1 :
ev . u . u . detail = 1 ;
mousestate | = Button1Mask ;
break ;
case K_MOUSE3 :
ev . u . u . detail = 2 ;
mousestate | = Button2Mask ;
break ;
case K_MOUSE2 :
ev . u . u . detail = 3 ;
mousestate | = Button3Mask ;
break ;
case K_MOUSE4 :
ev . u . u . detail = 4 ;
mousestate | = Button4Mask ;
break ;
default :
ev . u . u . detail = 5 ;
mousestate | = Button5Mask ;
break ;
}
ev . u . keyButtonPointer . state = mousestate ;
ev . u . keyButtonPointer . child = x_windowwithcursor ;
}
else
{
ev . u . u . type = KeyPress ;
ev . u . u . detail = key ;
ev . u . keyButtonPointer . state = 0 ;
ev . u . keyButtonPointer . child = x_windowwithfocus ;
}
ev . u . u . sequenceNumber = 0 ;
ev . u . keyButtonPointer . time = Sys_DoubleTime ( ) * 1000 ;
ev . u . keyButtonPointer . rootX = x_mousex ;
ev . u . keyButtonPointer . rootY = x_mousey ;
ev . u . keyButtonPointer . sameScreen = true ;
ev . u . keyButtonPointer . pad1 = 0 ;
// Con_Printf("key %i, %i %i\n", key, x_mousex, x_mousey);
if ( xpointergrabclient )
{
ev . u . keyButtonPointer . event = ev . u . keyButtonPointer . child ;
ev . u . keyButtonPointer . eventX = ev . u . keyButtonPointer . rootX ;
ev . u . keyButtonPointer . eventY = ev . u . keyButtonPointer . rootY ;
2004-09-20 23:25:38 +00:00
if ( XS_GetResource ( x_windowwithcursor , ( void * * ) & wnd ) = = x_window )
2004-08-23 01:37:23 +00:00
{
ev . u . u . sequenceNumber = xpointergrabclient - > requestnum ;
while ( wnd )
{
ev . u . keyButtonPointer . eventX - = wnd - > xpos ;
ev . u . keyButtonPointer . eventY - = wnd - > ypos ;
wnd = wnd - > parent ;
}
X_SendData ( xpointergrabclient , & ev , sizeof ( ev ) ) ;
}
}
2004-09-20 23:25:38 +00:00
else if ( XS_GetResource ( ev . u . keyButtonPointer . child , ( void * * ) & wnd ) = = x_window )
2004-08-23 01:37:23 +00:00
X_SendInputNotification ( & ev , wnd , ( ev . u . u . type = = ButtonPress ) ? ButtonPressMask : KeyPressMask ) ;
}
}
void XWindows_Keyup ( int key )
{
{
xEvent ev ;
xwindow_t * wnd ;
X_EvalutateCursorOwner ( NotifyNormal ) ;
X_EvalutateFocus ( NotifyNormal ) ;
if ( key > = K_MOUSE1 & & key < = K_MOUSE5 )
{
ev . u . u . type = ButtonRelease ;
ev . u . keyButtonPointer . state = mousestate ;
switch ( key )
{
case K_MOUSE1 :
ev . u . u . detail = 1 ;
mousestate & = ~ Button1Mask ;
break ;
case K_MOUSE3 :
ev . u . u . detail = 2 ;
mousestate & = ~ Button2Mask ;
break ;
case K_MOUSE2 :
ev . u . u . detail = 3 ;
mousestate & = ~ Button3Mask ;
break ;
case K_MOUSE4 :
ev . u . u . detail = 4 ;
mousestate & = ~ Button4Mask ;
break ;
default :
ev . u . u . detail = 5 ;
mousestate & = ~ Button5Mask ;
break ;
}
ev . u . keyButtonPointer . state = mousestate ;
ev . u . keyButtonPointer . child = x_windowwithcursor ;
}
else
{
ev . u . u . type = KeyRelease ;
ev . u . u . detail = key ;
ev . u . keyButtonPointer . child = x_windowwithfocus ;
}
ev . u . u . sequenceNumber = 0 ;
ev . u . keyButtonPointer . time = Sys_DoubleTime ( ) * 1000 ;
ev . u . keyButtonPointer . rootX = x_mousex ;
ev . u . keyButtonPointer . rootY = x_mousey ;
ev . u . keyButtonPointer . state = 0 ;
ev . u . keyButtonPointer . sameScreen = true ;
ev . u . keyButtonPointer . pad1 = 0 ;
// Con_Printf("keyup %i, %i %i\n", key, x_mousex, x_mousey);
if ( xpointergrabclient )
{
ev . u . keyButtonPointer . event = ev . u . keyButtonPointer . child ;
ev . u . keyButtonPointer . eventX = ev . u . keyButtonPointer . rootX ;
ev . u . keyButtonPointer . eventY = ev . u . keyButtonPointer . rootY ;
2004-09-20 23:25:38 +00:00
if ( XS_GetResource ( x_windowwithcursor , ( void * * ) & wnd ) = = x_window )
2004-08-23 01:37:23 +00:00
{
ev . u . u . sequenceNumber = xpointergrabclient - > requestnum ;
while ( wnd )
{
ev . u . keyButtonPointer . eventX - = wnd - > xpos ;
ev . u . keyButtonPointer . eventY - = wnd - > ypos ;
wnd = wnd - > parent ;
}
X_SendData ( xpointergrabclient , & ev , sizeof ( ev ) ) ;
}
}
2004-09-20 23:25:38 +00:00
else if ( XS_GetResource ( ev . u . keyButtonPointer . child , ( void * * ) & wnd ) = = x_window )
2004-08-23 01:37:23 +00:00
{
X_SendInputNotification ( & ev , wnd , ( ev . u . u . type = = ButtonRelease ) ? ButtonReleaseMask : KeyReleaseMask ) ;
}
}
}
# else
//quakie functions
void XWindows_Init ( void ) { }
void XWindows_Draw ( void ) { }
void XWindows_Key ( int key ) { }
void XWindows_Keyup ( int key ) { }
# endif