1996-09-27 06:29:02 -04:00
|
|
|
|
/*
|
|
|
|
|
* tkUnixEvent.c --
|
|
|
|
|
*
|
|
|
|
|
* This file implements an event source for X displays for the
|
|
|
|
|
* UNIX version of Tk.
|
|
|
|
|
*
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
|
|
|
|
* See the file "license.terms" for information on usage and redistribution
|
|
|
|
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
|
|
|
*
|
1998-09-30 07:11:02 -04:00
|
|
|
|
* SCCS: @(#) tkUnixEvent.c 1.17 97/09/11 12:51:04
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "tkInt.h"
|
|
|
|
|
#include "tkUnixInt.h"
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
/*
|
|
|
|
|
* The following static indicates whether this module has been initialized.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int initialized = 0;
|
|
|
|
|
|
1996-09-27 06:29:02 -04:00
|
|
|
|
/*
|
|
|
|
|
* Prototypes for procedures that are referenced only in this file:
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void DisplayCheckProc _ANSI_ARGS_((ClientData clientData,
|
|
|
|
|
int flags));
|
1998-04-10 06:59:06 -04:00
|
|
|
|
static void DisplayExitHandler _ANSI_ARGS_((
|
|
|
|
|
ClientData clientData));
|
|
|
|
|
static void DisplayFileProc _ANSI_ARGS_((ClientData clientData,
|
|
|
|
|
int flags));
|
1996-09-27 06:29:02 -04:00
|
|
|
|
static void DisplaySetupProc _ANSI_ARGS_((ClientData clientData,
|
|
|
|
|
int flags));
|
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkCreateXEventSource --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is called during Tk initialization to create
|
|
|
|
|
* the event source for X Window events.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* A new event source is created.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkCreateXEventSource()
|
|
|
|
|
{
|
|
|
|
|
if (!initialized) {
|
|
|
|
|
initialized = 1;
|
|
|
|
|
Tcl_CreateEventSource(DisplaySetupProc, DisplayCheckProc, NULL);
|
|
|
|
|
Tcl_CreateExitHandler(DisplayExitHandler, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DisplayExitHandler --
|
|
|
|
|
*
|
|
|
|
|
* This function is called during finalization to clean up the
|
|
|
|
|
* display module.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DisplayExitHandler(clientData)
|
|
|
|
|
ClientData clientData; /* Not used. */
|
|
|
|
|
{
|
|
|
|
|
Tcl_DeleteEventSource(DisplaySetupProc, DisplayCheckProc, NULL);
|
|
|
|
|
initialized = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpOpenDisplay --
|
|
|
|
|
*
|
|
|
|
|
* Allocates a new TkDisplay, opens the X display, and establishes
|
|
|
|
|
* the file handler for the connection.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* A pointer to a Tk display structure.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Opens a display.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
TkDisplay *
|
|
|
|
|
TkpOpenDisplay(display_name)
|
|
|
|
|
char *display_name;
|
|
|
|
|
{
|
|
|
|
|
TkDisplay *dispPtr;
|
|
|
|
|
Display *display = XOpenDisplay(display_name);
|
|
|
|
|
|
|
|
|
|
if (display == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
dispPtr = (TkDisplay *) ckalloc(sizeof(TkDisplay));
|
|
|
|
|
dispPtr->display = display;
|
|
|
|
|
Tcl_CreateFileHandler(ConnectionNumber(display), TCL_READABLE,
|
|
|
|
|
DisplayFileProc, (ClientData) dispPtr);
|
|
|
|
|
return dispPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpCloseDisplay --
|
|
|
|
|
*
|
|
|
|
|
* Cancels notifier callbacks and closes a display.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Deallocates the displayPtr.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpCloseDisplay(displayPtr)
|
|
|
|
|
TkDisplay *displayPtr;
|
|
|
|
|
{
|
|
|
|
|
TkDisplay *dispPtr = (TkDisplay *) displayPtr;
|
|
|
|
|
|
|
|
|
|
if (dispPtr->display != 0) {
|
|
|
|
|
Tcl_DeleteFileHandler(ConnectionNumber(dispPtr->display));
|
|
|
|
|
|
1998-09-30 07:11:02 -04:00
|
|
|
|
(void) XSync(dispPtr->display, False);
|
1998-04-10 06:59:06 -04:00
|
|
|
|
(void) XCloseDisplay(dispPtr->display);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ckfree((char *) dispPtr);
|
|
|
|
|
}
|
|
|
|
|
|
1996-09-27 06:29:02 -04:00
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DisplaySetupProc --
|
|
|
|
|
*
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* This procedure implements the setup part of the UNIX X display
|
|
|
|
|
* event source. It is invoked by Tcl_DoOneEvent before entering
|
|
|
|
|
* the notifier to check for events on all displays.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* If data is queued on a display inside Xlib, then the maximum
|
|
|
|
|
* block time will be set to 0 to ensure that the notifier returns
|
|
|
|
|
* control to Tcl even if there is no more data on the X connection.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DisplaySetupProc(clientData, flags)
|
1998-04-10 06:59:06 -04:00
|
|
|
|
ClientData clientData; /* Not used. */
|
|
|
|
|
int flags;
|
1996-09-27 06:29:02 -04:00
|
|
|
|
{
|
|
|
|
|
TkDisplay *dispPtr;
|
1998-04-10 06:59:06 -04:00
|
|
|
|
static Tcl_Time blockTime = { 0, 0 };
|
1996-09-27 06:29:02 -04:00
|
|
|
|
|
|
|
|
|
if (!(flags & TCL_WINDOW_EVENTS)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
for (dispPtr = tkDisplayList; dispPtr != NULL;
|
|
|
|
|
dispPtr = dispPtr->nextPtr) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Flush the display. If data is pending on the X queue, set
|
|
|
|
|
* the block time to zero. This ensures that we won't block
|
|
|
|
|
* in the notifier if there is data in the X queue, but not on
|
|
|
|
|
* the server socket.
|
|
|
|
|
*/
|
|
|
|
|
|
1996-09-27 06:29:02 -04:00
|
|
|
|
XFlush(dispPtr->display);
|
|
|
|
|
if (XQLength(dispPtr->display) > 0) {
|
1998-04-10 06:59:06 -04:00
|
|
|
|
Tcl_SetMaxBlockTime(&blockTime);
|
1996-09-27 06:29:02 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DisplayCheckProc --
|
|
|
|
|
*
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* This procedure checks for events sitting in the X event
|
|
|
|
|
* queue.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* Moves queued events onto the Tcl event queue.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DisplayCheckProc(clientData, flags)
|
1998-04-10 06:59:06 -04:00
|
|
|
|
ClientData clientData; /* Not used. */
|
|
|
|
|
int flags;
|
1996-09-27 06:29:02 -04:00
|
|
|
|
{
|
|
|
|
|
TkDisplay *dispPtr;
|
|
|
|
|
XEvent event;
|
|
|
|
|
int numFound;
|
|
|
|
|
|
|
|
|
|
if (!(flags & TCL_WINDOW_EVENTS)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
for (dispPtr = tkDisplayList; dispPtr != NULL;
|
|
|
|
|
dispPtr = dispPtr->nextPtr) {
|
|
|
|
|
XFlush(dispPtr->display);
|
|
|
|
|
numFound = XQLength(dispPtr->display);
|
|
|
|
|
|
1996-09-27 06:29:02 -04:00
|
|
|
|
/*
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* Transfer events from the X event queue to the Tk event queue.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*/
|
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
while (numFound > 0) {
|
|
|
|
|
XNextEvent(dispPtr->display, &event);
|
|
|
|
|
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
|
|
|
|
numFound--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* DisplayFileProc --
|
|
|
|
|
*
|
|
|
|
|
* This procedure implements the file handler for the X connection.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Makes entries on the Tcl event queue for all the events available
|
|
|
|
|
* from all the displays.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
DisplayFileProc(clientData, flags)
|
|
|
|
|
ClientData clientData; /* The display pointer. */
|
|
|
|
|
int flags; /* Should be TCL_READABLE. */
|
|
|
|
|
{
|
|
|
|
|
TkDisplay *dispPtr = (TkDisplay *) clientData;
|
|
|
|
|
Display *display = dispPtr->display;
|
|
|
|
|
XEvent event;
|
|
|
|
|
int numFound;
|
|
|
|
|
|
|
|
|
|
XFlush(display);
|
|
|
|
|
numFound = XEventsQueued(display, QueuedAfterReading);
|
|
|
|
|
if (numFound == 0) {
|
1996-09-27 06:29:02 -04:00
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
/*
|
|
|
|
|
* Things are very tricky if there aren't any events readable
|
|
|
|
|
* at this point (after all, there was supposedly data
|
|
|
|
|
* available on the connection). A couple of things could
|
|
|
|
|
* have occurred:
|
|
|
|
|
*
|
|
|
|
|
* One possibility is that there were only error events in the
|
|
|
|
|
* input from the server. If this happens, we should return
|
|
|
|
|
* (we don't want to go to sleep in XNextEvent below, since
|
|
|
|
|
* this would block out other sources of input to the
|
|
|
|
|
* process).
|
|
|
|
|
*
|
|
|
|
|
* Another possibility is that our connection to the server
|
|
|
|
|
* has been closed. This will not necessarily be detected in
|
|
|
|
|
* XEventsQueued (!!), so if we just return then there will be
|
|
|
|
|
* an infinite loop. To detect such an error, generate a NoOp
|
|
|
|
|
* protocol request to exercise the connection to the server,
|
|
|
|
|
* then return. However, must disable SIGPIPE while sending
|
|
|
|
|
* the request, or else the process will die from the signal
|
|
|
|
|
* and won't invoke the X error function to print a nice (?!)
|
|
|
|
|
* message.
|
|
|
|
|
*/
|
1996-09-27 06:29:02 -04:00
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
void (*oldHandler)();
|
1996-09-27 06:29:02 -04:00
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
oldHandler = (void (*)()) signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
XNoOp(display);
|
|
|
|
|
XFlush(display);
|
|
|
|
|
(void) signal(SIGPIPE, oldHandler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Transfer events from the X event queue to the Tk event queue.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
while (numFound > 0) {
|
|
|
|
|
XNextEvent(display, &event);
|
|
|
|
|
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
|
|
|
|
numFound--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkUnixDoOneXEvent --
|
|
|
|
|
*
|
|
|
|
|
* This routine waits for an X event to be processed or for
|
|
|
|
|
* a timeout to occur. The timeout is specified as an absolute
|
|
|
|
|
* time. This routine is called when Tk needs to wait for a
|
|
|
|
|
* particular X event without letting arbitrary events be
|
|
|
|
|
* processed. The caller will typically call Tk_RestrictEvents
|
|
|
|
|
* to set up an event filter before calling this routine. This
|
|
|
|
|
* routine will service at most one event per invocation.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 if the timeout has expired, otherwise returns 1.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Can invoke arbitrary Tcl scripts.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
TkUnixDoOneXEvent(timePtr)
|
|
|
|
|
Tcl_Time *timePtr; /* Specifies the absolute time when the
|
|
|
|
|
* call should time out. */
|
|
|
|
|
{
|
|
|
|
|
TkDisplay *dispPtr;
|
|
|
|
|
static fd_mask readMask[MASK_SIZE];
|
|
|
|
|
struct timeval blockTime, *timeoutPtr;
|
|
|
|
|
Tcl_Time now;
|
|
|
|
|
int fd, index, bit, numFound, numFdBits = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Look for queued events first.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Compute the next block time and check to see if we have timed out.
|
|
|
|
|
* Note that HP-UX defines tv_sec to be unsigned so we have to be
|
|
|
|
|
* careful in our arithmetic.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (timePtr) {
|
|
|
|
|
TclpGetTime(&now);
|
|
|
|
|
blockTime.tv_sec = timePtr->sec;
|
|
|
|
|
blockTime.tv_usec = timePtr->usec - now.usec;
|
|
|
|
|
if (blockTime.tv_usec < 0) {
|
|
|
|
|
now.sec += 1;
|
|
|
|
|
blockTime.tv_usec += 1000000;
|
|
|
|
|
}
|
|
|
|
|
if (blockTime.tv_sec < now.sec) {
|
|
|
|
|
blockTime.tv_sec = 0;
|
|
|
|
|
blockTime.tv_usec = 0;
|
1996-09-27 06:29:02 -04:00
|
|
|
|
} else {
|
1998-04-10 06:59:06 -04:00
|
|
|
|
blockTime.tv_sec -= now.sec;
|
1996-09-27 06:29:02 -04:00
|
|
|
|
}
|
1998-04-10 06:59:06 -04:00
|
|
|
|
timeoutPtr = &blockTime;
|
|
|
|
|
} else {
|
|
|
|
|
timeoutPtr = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set up the select mask for all of the displays. If a display has
|
|
|
|
|
* data pending, then we want to poll instead of blocking.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
memset((VOID *) readMask, 0, MASK_SIZE*sizeof(fd_mask));
|
|
|
|
|
for (dispPtr = tkDisplayList; dispPtr != NULL;
|
|
|
|
|
dispPtr = dispPtr->nextPtr) {
|
|
|
|
|
XFlush(dispPtr->display);
|
|
|
|
|
if (XQLength(dispPtr->display) > 0) {
|
|
|
|
|
blockTime.tv_sec = 0;
|
|
|
|
|
blockTime.tv_usec = 0;
|
|
|
|
|
}
|
|
|
|
|
fd = ConnectionNumber(dispPtr->display);
|
|
|
|
|
index = fd/(NBBY*sizeof(fd_mask));
|
|
|
|
|
bit = 1 << (fd%(NBBY*sizeof(fd_mask)));
|
|
|
|
|
readMask[index] |= bit;
|
|
|
|
|
if (numFdBits <= fd) {
|
|
|
|
|
numFdBits = fd+1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numFound = select(numFdBits, (SELECT_MASK *) &readMask[0], NULL, NULL,
|
|
|
|
|
timeoutPtr);
|
|
|
|
|
if (numFound <= 0) {
|
1996-09-27 06:29:02 -04:00
|
|
|
|
/*
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* Some systems don't clear the masks after an error, so
|
|
|
|
|
* we have to do it here.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*/
|
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
memset((VOID *) readMask, 0, MASK_SIZE*sizeof(fd_mask));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Process any new events on the display connections.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
for (dispPtr = tkDisplayList; dispPtr != NULL;
|
|
|
|
|
dispPtr = dispPtr->nextPtr) {
|
|
|
|
|
fd = ConnectionNumber(dispPtr->display);
|
|
|
|
|
index = fd/(NBBY*sizeof(fd_mask));
|
|
|
|
|
bit = 1 << (fd%(NBBY*sizeof(fd_mask)));
|
|
|
|
|
if ((readMask[index] & bit) || (XQLength(dispPtr->display) > 0)) {
|
|
|
|
|
DisplayFileProc((ClientData)dispPtr, TCL_READABLE);
|
1996-09-27 06:29:02 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
1998-04-10 06:59:06 -04:00
|
|
|
|
if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check to see if we timed out.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (timePtr) {
|
|
|
|
|
TclpGetTime(&now);
|
|
|
|
|
if ((now.sec > timePtr->sec) || ((now.sec == timePtr->sec)
|
|
|
|
|
&& (now.usec > timePtr->usec))) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We had an event but we did not generate a Tcl event from it. Behave
|
|
|
|
|
* as though we dealt with it. (JYL&SS)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return 1;
|
1996-09-27 06:29:02 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* TkpSync --
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* This routine ensures that all pending X requests have been
|
|
|
|
|
* seen by the server, and that any pending X events have been
|
|
|
|
|
* moved onto the Tk event queue.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
1998-04-10 06:59:06 -04:00
|
|
|
|
* Places new events on the Tk event queue.
|
1996-09-27 06:29:02 -04:00
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
1998-04-10 06:59:06 -04:00
|
|
|
|
TkpSync(display)
|
|
|
|
|
Display *display; /* Display to sync. */
|
1996-09-27 06:29:02 -04:00
|
|
|
|
{
|
1998-04-10 06:59:06 -04:00
|
|
|
|
int numFound = 0;
|
|
|
|
|
XEvent event;
|
1996-09-27 06:29:02 -04:00
|
|
|
|
|
1998-04-10 06:59:06 -04:00
|
|
|
|
XSync(display, False);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Transfer events from the X event queue to the Tk event queue.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
numFound = XQLength(display);
|
|
|
|
|
while (numFound > 0) {
|
|
|
|
|
XNextEvent(display, &event);
|
|
|
|
|
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
|
|
|
|
numFound--;
|
1996-09-27 06:29:02 -04:00
|
|
|
|
}
|
|
|
|
|
}
|