OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkEvent.c] - Diff between revs 579 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 579 Rev 1765
/*
/*
 * tkEvent.c --
 * tkEvent.c --
 *
 *
 *      This file provides basic low-level facilities for managing
 *      This file provides basic low-level facilities for managing
 *      X events in Tk.
 *      X events in Tk.
 *
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright (c) 1998 by Scriptics Corporation.
 *
 *
 * See the file "license.terms" for information on usage and redistribution
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *
 * RCS: @(#) $Id: tkEvent.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
 * RCS: @(#) $Id: tkEvent.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
 */
 */
 
 
#include "tkPort.h"
#include "tkPort.h"
#include "tkInt.h"
#include "tkInt.h"
#include <signal.h>
#include <signal.h>
 
 
/*
/*
 * There's a potential problem if a handler is deleted while it's
 * There's a potential problem if a handler is deleted while it's
 * current (i.e. its procedure is executing), since Tk_HandleEvent
 * current (i.e. its procedure is executing), since Tk_HandleEvent
 * will need to read the handler's "nextPtr" field when the procedure
 * will need to read the handler's "nextPtr" field when the procedure
 * returns.  To handle this problem, structures of the type below
 * returns.  To handle this problem, structures of the type below
 * indicate the next handler to be processed for any (recursively
 * indicate the next handler to be processed for any (recursively
 * nested) dispatches in progress.  The nextHandler fields get
 * nested) dispatches in progress.  The nextHandler fields get
 * updated if the handlers pointed to are deleted.  Tk_HandleEvent
 * updated if the handlers pointed to are deleted.  Tk_HandleEvent
 * also needs to know if the entire window gets deleted;  the winPtr
 * also needs to know if the entire window gets deleted;  the winPtr
 * field is set to zero if that particular window gets deleted.
 * field is set to zero if that particular window gets deleted.
 */
 */
 
 
typedef struct InProgress {
typedef struct InProgress {
    XEvent *eventPtr;            /* Event currently being handled. */
    XEvent *eventPtr;            /* Event currently being handled. */
    TkWindow *winPtr;            /* Window for event.  Gets set to None if
    TkWindow *winPtr;            /* Window for event.  Gets set to None if
                                  * window is deleted while event is being
                                  * window is deleted while event is being
                                  * handled. */
                                  * handled. */
    TkEventHandler *nextHandler; /* Next handler in search. */
    TkEventHandler *nextHandler; /* Next handler in search. */
    struct InProgress *nextPtr;  /* Next higher nested search. */
    struct InProgress *nextPtr;  /* Next higher nested search. */
} InProgress;
} InProgress;
 
 
static InProgress *pendingPtr = NULL;
static InProgress *pendingPtr = NULL;
                                /* Topmost search in progress, or
                                /* Topmost search in progress, or
                                 * NULL if none. */
                                 * NULL if none. */
 
 
/*
/*
 * For each call to Tk_CreateGenericHandler, an instance of the following
 * For each call to Tk_CreateGenericHandler, an instance of the following
 * structure will be created.  All of the active handlers are linked into a
 * structure will be created.  All of the active handlers are linked into a
 * list.
 * list.
 */
 */
 
 
typedef struct GenericHandler {
typedef struct GenericHandler {
    Tk_GenericProc *proc;       /* Procedure to dispatch on all X events. */
    Tk_GenericProc *proc;       /* Procedure to dispatch on all X events. */
    ClientData clientData;      /* Client data to pass to procedure. */
    ClientData clientData;      /* Client data to pass to procedure. */
    int deleteFlag;             /* Flag to set when this handler is deleted. */
    int deleteFlag;             /* Flag to set when this handler is deleted. */
    struct GenericHandler *nextPtr;
    struct GenericHandler *nextPtr;
                                /* Next handler in list of all generic
                                /* Next handler in list of all generic
                                 * handlers, or NULL for end of list. */
                                 * handlers, or NULL for end of list. */
} GenericHandler;
} GenericHandler;
 
 
static GenericHandler *genericList = NULL;
static GenericHandler *genericList = NULL;
                                /* First handler in the list, or NULL. */
                                /* First handler in the list, or NULL. */
static GenericHandler *lastGenericPtr = NULL;
static GenericHandler *lastGenericPtr = NULL;
                                /* Last handler in list. */
                                /* Last handler in list. */
 
 
/*
/*
 * There's a potential problem if Tk_HandleEvent is entered recursively.
 * There's a potential problem if Tk_HandleEvent is entered recursively.
 * A handler cannot be deleted physically until we have returned from
 * A handler cannot be deleted physically until we have returned from
 * calling it.  Otherwise, we're looking at unallocated memory in advancing to
 * calling it.  Otherwise, we're looking at unallocated memory in advancing to
 * its `next' entry.  We deal with the problem by using the `delete flag' and
 * its `next' entry.  We deal with the problem by using the `delete flag' and
 * deleting handlers only when it's known that there's no handler active.
 * deleting handlers only when it's known that there's no handler active.
 *
 *
 * The following variable has a non-zero value when a handler is active.
 * The following variable has a non-zero value when a handler is active.
 */
 */
 
 
static int genericHandlersActive = 0;
static int genericHandlersActive = 0;
 
 
/*
/*
 * The following structure is used for queueing X-style events on the
 * The following structure is used for queueing X-style events on the
 * Tcl event queue.
 * Tcl event queue.
 */
 */
 
 
typedef struct TkWindowEvent {
typedef struct TkWindowEvent {
    Tcl_Event header;           /* Standard information for all events. */
    Tcl_Event header;           /* Standard information for all events. */
    XEvent event;               /* The X event. */
    XEvent event;               /* The X event. */
} TkWindowEvent;
} TkWindowEvent;
 
 
/*
/*
 * Array of event masks corresponding to each X event:
 * Array of event masks corresponding to each X event:
 */
 */
 
 
static unsigned long eventMasks[TK_LASTEVENT] = {
static unsigned long eventMasks[TK_LASTEVENT] = {
    0,
    0,
    0,
    0,
    KeyPressMask,                       /* KeyPress */
    KeyPressMask,                       /* KeyPress */
    KeyReleaseMask,                     /* KeyRelease */
    KeyReleaseMask,                     /* KeyRelease */
    ButtonPressMask,                    /* ButtonPress */
    ButtonPressMask,                    /* ButtonPress */
    ButtonReleaseMask,                  /* ButtonRelease */
    ButtonReleaseMask,                  /* ButtonRelease */
    PointerMotionMask|PointerMotionHintMask|ButtonMotionMask
    PointerMotionMask|PointerMotionHintMask|ButtonMotionMask
            |Button1MotionMask|Button2MotionMask|Button3MotionMask
            |Button1MotionMask|Button2MotionMask|Button3MotionMask
            |Button4MotionMask|Button5MotionMask,
            |Button4MotionMask|Button5MotionMask,
                                        /* MotionNotify */
                                        /* MotionNotify */
    EnterWindowMask,                    /* EnterNotify */
    EnterWindowMask,                    /* EnterNotify */
    LeaveWindowMask,                    /* LeaveNotify */
    LeaveWindowMask,                    /* LeaveNotify */
    FocusChangeMask,                    /* FocusIn */
    FocusChangeMask,                    /* FocusIn */
    FocusChangeMask,                    /* FocusOut */
    FocusChangeMask,                    /* FocusOut */
    KeymapStateMask,                    /* KeymapNotify */
    KeymapStateMask,                    /* KeymapNotify */
    ExposureMask,                       /* Expose */
    ExposureMask,                       /* Expose */
    ExposureMask,                       /* GraphicsExpose */
    ExposureMask,                       /* GraphicsExpose */
    ExposureMask,                       /* NoExpose */
    ExposureMask,                       /* NoExpose */
    VisibilityChangeMask,               /* VisibilityNotify */
    VisibilityChangeMask,               /* VisibilityNotify */
    SubstructureNotifyMask,             /* CreateNotify */
    SubstructureNotifyMask,             /* CreateNotify */
    StructureNotifyMask,                /* DestroyNotify */
    StructureNotifyMask,                /* DestroyNotify */
    StructureNotifyMask,                /* UnmapNotify */
    StructureNotifyMask,                /* UnmapNotify */
    StructureNotifyMask,                /* MapNotify */
    StructureNotifyMask,                /* MapNotify */
    SubstructureRedirectMask,           /* MapRequest */
    SubstructureRedirectMask,           /* MapRequest */
    StructureNotifyMask,                /* ReparentNotify */
    StructureNotifyMask,                /* ReparentNotify */
    StructureNotifyMask,                /* ConfigureNotify */
    StructureNotifyMask,                /* ConfigureNotify */
    SubstructureRedirectMask,           /* ConfigureRequest */
    SubstructureRedirectMask,           /* ConfigureRequest */
    StructureNotifyMask,                /* GravityNotify */
    StructureNotifyMask,                /* GravityNotify */
    ResizeRedirectMask,                 /* ResizeRequest */
    ResizeRedirectMask,                 /* ResizeRequest */
    StructureNotifyMask,                /* CirculateNotify */
    StructureNotifyMask,                /* CirculateNotify */
    SubstructureRedirectMask,           /* CirculateRequest */
    SubstructureRedirectMask,           /* CirculateRequest */
    PropertyChangeMask,                 /* PropertyNotify */
    PropertyChangeMask,                 /* PropertyNotify */
    0,                                   /* SelectionClear */
    0,                                   /* SelectionClear */
    0,                                   /* SelectionRequest */
    0,                                   /* SelectionRequest */
    0,                                   /* SelectionNotify */
    0,                                   /* SelectionNotify */
    ColormapChangeMask,                 /* ColormapNotify */
    ColormapChangeMask,                 /* ColormapNotify */
    0,                                   /* ClientMessage */
    0,                                   /* ClientMessage */
    0,                                   /* Mapping Notify */
    0,                                   /* Mapping Notify */
    VirtualEventMask,                   /* VirtualEvents */
    VirtualEventMask,                   /* VirtualEvents */
    ActivateMask,                       /* ActivateNotify */
    ActivateMask,                       /* ActivateNotify */
    ActivateMask,                       /* DeactivateNotify */
    ActivateMask,                       /* DeactivateNotify */
    MouseWheelMask                      /* MouseWheelEvent */
    MouseWheelMask                      /* MouseWheelEvent */
};
};
 
 
/*
/*
 * If someone has called Tk_RestrictEvents, the information below
 * If someone has called Tk_RestrictEvents, the information below
 * keeps track of it.
 * keeps track of it.
 */
 */
 
 
static Tk_RestrictProc *restrictProc;
static Tk_RestrictProc *restrictProc;
                                /* Procedure to call.  NULL means no
                                /* Procedure to call.  NULL means no
                                 * restrictProc is currently in effect. */
                                 * restrictProc is currently in effect. */
static ClientData restrictArg;  /* Argument to pass to restrictProc. */
static ClientData restrictArg;  /* Argument to pass to restrictProc. */
 
 
/*
/*
 * Prototypes for procedures that are only referenced locally within
 * Prototypes for procedures that are only referenced locally within
 * this file.
 * this file.
 */
 */
 
 
static void             DelayedMotionProc _ANSI_ARGS_((ClientData clientData));
static void             DelayedMotionProc _ANSI_ARGS_((ClientData clientData));
static int              WindowEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
static int              WindowEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
                            int flags));
                            int flags));


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_CreateEventHandler --
 * Tk_CreateEventHandler --
 *
 *
 *      Arrange for a given procedure to be invoked whenever
 *      Arrange for a given procedure to be invoked whenever
 *      events from a given class occur in a given window.
 *      events from a given class occur in a given window.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      From now on, whenever an event of the type given by
 *      From now on, whenever an event of the type given by
 *      mask occurs for token and is processed by Tk_HandleEvent,
 *      mask occurs for token and is processed by Tk_HandleEvent,
 *      proc will be called.  See the manual entry for details
 *      proc will be called.  See the manual entry for details
 *      of the calling sequence and return value for proc.
 *      of the calling sequence and return value for proc.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_CreateEventHandler(token, mask, proc, clientData)
Tk_CreateEventHandler(token, mask, proc, clientData)
    Tk_Window token;            /* Token for window in which to
    Tk_Window token;            /* Token for window in which to
                                 * create handler. */
                                 * create handler. */
    unsigned long mask;         /* Events for which proc should
    unsigned long mask;         /* Events for which proc should
                                 * be called. */
                                 * be called. */
    Tk_EventProc *proc;         /* Procedure to call for each
    Tk_EventProc *proc;         /* Procedure to call for each
                                 * selected event */
                                 * selected event */
    ClientData clientData;      /* Arbitrary data to pass to proc. */
    ClientData clientData;      /* Arbitrary data to pass to proc. */
{
{
    register TkEventHandler *handlerPtr;
    register TkEventHandler *handlerPtr;
    register TkWindow *winPtr = (TkWindow *) token;
    register TkWindow *winPtr = (TkWindow *) token;
    int found;
    int found;
 
 
    /*
    /*
     * Skim through the list of existing handlers to (a) compute the
     * Skim through the list of existing handlers to (a) compute the
     * overall event mask for the window (so we can pass this new
     * overall event mask for the window (so we can pass this new
     * value to the X system) and (b) see if there's already a handler
     * value to the X system) and (b) see if there's already a handler
     * declared with the same callback and clientData (if so, just
     * declared with the same callback and clientData (if so, just
     * change the mask).  If no existing handler matches, then create
     * change the mask).  If no existing handler matches, then create
     * a new handler.
     * a new handler.
     */
     */
 
 
    found = 0;
    found = 0;
    if (winPtr->handlerList == NULL) {
    if (winPtr->handlerList == NULL) {
        handlerPtr = (TkEventHandler *) ckalloc(
        handlerPtr = (TkEventHandler *) ckalloc(
                (unsigned) sizeof(TkEventHandler));
                (unsigned) sizeof(TkEventHandler));
        winPtr->handlerList = handlerPtr;
        winPtr->handlerList = handlerPtr;
        goto initHandler;
        goto initHandler;
    } else {
    } else {
        for (handlerPtr = winPtr->handlerList; ;
        for (handlerPtr = winPtr->handlerList; ;
                handlerPtr = handlerPtr->nextPtr) {
                handlerPtr = handlerPtr->nextPtr) {
            if ((handlerPtr->proc == proc)
            if ((handlerPtr->proc == proc)
                    && (handlerPtr->clientData == clientData)) {
                    && (handlerPtr->clientData == clientData)) {
                handlerPtr->mask = mask;
                handlerPtr->mask = mask;
                found = 1;
                found = 1;
            }
            }
            if (handlerPtr->nextPtr == NULL) {
            if (handlerPtr->nextPtr == NULL) {
                break;
                break;
            }
            }
        }
        }
    }
    }
 
 
    /*
    /*
     * Create a new handler if no matching old handler was found.
     * Create a new handler if no matching old handler was found.
     */
     */
 
 
    if (!found) {
    if (!found) {
        handlerPtr->nextPtr = (TkEventHandler *)
        handlerPtr->nextPtr = (TkEventHandler *)
                ckalloc(sizeof(TkEventHandler));
                ckalloc(sizeof(TkEventHandler));
        handlerPtr = handlerPtr->nextPtr;
        handlerPtr = handlerPtr->nextPtr;
        initHandler:
        initHandler:
        handlerPtr->mask = mask;
        handlerPtr->mask = mask;
        handlerPtr->proc = proc;
        handlerPtr->proc = proc;
        handlerPtr->clientData = clientData;
        handlerPtr->clientData = clientData;
        handlerPtr->nextPtr = NULL;
        handlerPtr->nextPtr = NULL;
    }
    }
 
 
    /*
    /*
     * No need to call XSelectInput:  Tk always selects on all events
     * No need to call XSelectInput:  Tk always selects on all events
     * for all windows (needed to support bindings on classes and "all").
     * for all windows (needed to support bindings on classes and "all").
     */
     */
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_DeleteEventHandler --
 * Tk_DeleteEventHandler --
 *
 *
 *      Delete a previously-created handler.
 *      Delete a previously-created handler.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      If there existed a handler as described by the
 *      If there existed a handler as described by the
 *      parameters, the handler is deleted so that proc
 *      parameters, the handler is deleted so that proc
 *      will not be invoked again.
 *      will not be invoked again.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_DeleteEventHandler(token, mask, proc, clientData)
Tk_DeleteEventHandler(token, mask, proc, clientData)
    Tk_Window token;            /* Same as corresponding arguments passed */
    Tk_Window token;            /* Same as corresponding arguments passed */
    unsigned long mask;         /* previously to Tk_CreateEventHandler. */
    unsigned long mask;         /* previously to Tk_CreateEventHandler. */
    Tk_EventProc *proc;
    Tk_EventProc *proc;
    ClientData clientData;
    ClientData clientData;
{
{
    register TkEventHandler *handlerPtr;
    register TkEventHandler *handlerPtr;
    register InProgress *ipPtr;
    register InProgress *ipPtr;
    TkEventHandler *prevPtr;
    TkEventHandler *prevPtr;
    register TkWindow *winPtr = (TkWindow *) token;
    register TkWindow *winPtr = (TkWindow *) token;
 
 
    /*
    /*
     * Find the event handler to be deleted, or return
     * Find the event handler to be deleted, or return
     * immediately if it doesn't exist.
     * immediately if it doesn't exist.
     */
     */
 
 
    for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ;
    for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ;
            prevPtr = handlerPtr, handlerPtr = handlerPtr->nextPtr) {
            prevPtr = handlerPtr, handlerPtr = handlerPtr->nextPtr) {
        if (handlerPtr == NULL) {
        if (handlerPtr == NULL) {
            return;
            return;
        }
        }
        if ((handlerPtr->mask == mask) && (handlerPtr->proc == proc)
        if ((handlerPtr->mask == mask) && (handlerPtr->proc == proc)
                && (handlerPtr->clientData == clientData)) {
                && (handlerPtr->clientData == clientData)) {
            break;
            break;
        }
        }
    }
    }
 
 
    /*
    /*
     * If Tk_HandleEvent is about to process this handler, tell it to
     * If Tk_HandleEvent is about to process this handler, tell it to
     * process the next one instead.
     * process the next one instead.
     */
     */
 
 
    for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
    for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
        if (ipPtr->nextHandler == handlerPtr) {
        if (ipPtr->nextHandler == handlerPtr) {
            ipPtr->nextHandler = handlerPtr->nextPtr;
            ipPtr->nextHandler = handlerPtr->nextPtr;
        }
        }
    }
    }
 
 
    /*
    /*
     * Free resources associated with the handler.
     * Free resources associated with the handler.
     */
     */
 
 
    if (prevPtr == NULL) {
    if (prevPtr == NULL) {
        winPtr->handlerList = handlerPtr->nextPtr;
        winPtr->handlerList = handlerPtr->nextPtr;
    } else {
    } else {
        prevPtr->nextPtr = handlerPtr->nextPtr;
        prevPtr->nextPtr = handlerPtr->nextPtr;
    }
    }
    ckfree((char *) handlerPtr);
    ckfree((char *) handlerPtr);
 
 
 
 
    /*
    /*
     * No need to call XSelectInput:  Tk always selects on all events
     * No need to call XSelectInput:  Tk always selects on all events
     * for all windows (needed to support bindings on classes and "all").
     * for all windows (needed to support bindings on classes and "all").
     */
     */
}
}


/*--------------------------------------------------------------
/*--------------------------------------------------------------
 *
 *
 * Tk_CreateGenericHandler --
 * Tk_CreateGenericHandler --
 *
 *
 *      Register a procedure to be called on each X event, regardless
 *      Register a procedure to be called on each X event, regardless
 *      of display or window.  Generic handlers are useful for capturing
 *      of display or window.  Generic handlers are useful for capturing
 *      events that aren't associated with windows, or events for windows
 *      events that aren't associated with windows, or events for windows
 *      not managed by Tk.
 *      not managed by Tk.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side Effects:
 * Side Effects:
 *      From now on, whenever an X event is given to Tk_HandleEvent,
 *      From now on, whenever an X event is given to Tk_HandleEvent,
 *      invoke proc, giving it clientData and the event as arguments.
 *      invoke proc, giving it clientData and the event as arguments.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_CreateGenericHandler(proc, clientData)
Tk_CreateGenericHandler(proc, clientData)
     Tk_GenericProc *proc;      /* Procedure to call on every event. */
     Tk_GenericProc *proc;      /* Procedure to call on every event. */
     ClientData clientData;     /* One-word value to pass to proc. */
     ClientData clientData;     /* One-word value to pass to proc. */
{
{
    GenericHandler *handlerPtr;
    GenericHandler *handlerPtr;
 
 
    handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler));
    handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler));
 
 
    handlerPtr->proc = proc;
    handlerPtr->proc = proc;
    handlerPtr->clientData = clientData;
    handlerPtr->clientData = clientData;
    handlerPtr->deleteFlag = 0;
    handlerPtr->deleteFlag = 0;
    handlerPtr->nextPtr = NULL;
    handlerPtr->nextPtr = NULL;
    if (genericList == NULL) {
    if (genericList == NULL) {
        genericList = handlerPtr;
        genericList = handlerPtr;
    } else {
    } else {
        lastGenericPtr->nextPtr = handlerPtr;
        lastGenericPtr->nextPtr = handlerPtr;
    }
    }
    lastGenericPtr = handlerPtr;
    lastGenericPtr = handlerPtr;
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_DeleteGenericHandler --
 * Tk_DeleteGenericHandler --
 *
 *
 *      Delete a previously-created generic handler.
 *      Delete a previously-created generic handler.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side Effects:
 * Side Effects:
 *      If there existed a handler as described by the parameters,
 *      If there existed a handler as described by the parameters,
 *      that handler is logically deleted so that proc will not be
 *      that handler is logically deleted so that proc will not be
 *      invoked again.  The physical deletion happens in the event
 *      invoked again.  The physical deletion happens in the event
 *      loop in Tk_HandleEvent.
 *      loop in Tk_HandleEvent.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_DeleteGenericHandler(proc, clientData)
Tk_DeleteGenericHandler(proc, clientData)
     Tk_GenericProc *proc;
     Tk_GenericProc *proc;
     ClientData clientData;
     ClientData clientData;
{
{
    GenericHandler * handler;
    GenericHandler * handler;
 
 
    for (handler = genericList; handler; handler = handler->nextPtr) {
    for (handler = genericList; handler; handler = handler->nextPtr) {
        if ((handler->proc == proc) && (handler->clientData == clientData)) {
        if ((handler->proc == proc) && (handler->clientData == clientData)) {
            handler->deleteFlag = 1;
            handler->deleteFlag = 1;
        }
        }
    }
    }
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_HandleEvent --
 * Tk_HandleEvent --
 *
 *
 *      Given an event, invoke all the handlers that have
 *      Given an event, invoke all the handlers that have
 *      been registered for the event.
 *      been registered for the event.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Depends on the handlers.
 *      Depends on the handlers.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_HandleEvent(eventPtr)
Tk_HandleEvent(eventPtr)
    XEvent *eventPtr;           /* Event to dispatch. */
    XEvent *eventPtr;           /* Event to dispatch. */
{
{
    register TkEventHandler *handlerPtr;
    register TkEventHandler *handlerPtr;
    register GenericHandler *genericPtr;
    register GenericHandler *genericPtr;
    register GenericHandler *genPrevPtr;
    register GenericHandler *genPrevPtr;
    TkWindow *winPtr;
    TkWindow *winPtr;
    unsigned long mask;
    unsigned long mask;
    InProgress ip;
    InProgress ip;
    Window handlerWindow;
    Window handlerWindow;
    TkDisplay *dispPtr;
    TkDisplay *dispPtr;
    Tcl_Interp *interp = (Tcl_Interp *) NULL;
    Tcl_Interp *interp = (Tcl_Interp *) NULL;
 
 
    /*
    /*
     * Next, invoke all the generic event handlers (those that are
     * Next, invoke all the generic event handlers (those that are
     * invoked for all events).  If a generic event handler reports that
     * invoked for all events).  If a generic event handler reports that
     * an event is fully processed, go no further.
     * an event is fully processed, go no further.
     */
     */
 
 
    for (genPrevPtr = NULL, genericPtr = genericList;  genericPtr != NULL; ) {
    for (genPrevPtr = NULL, genericPtr = genericList;  genericPtr != NULL; ) {
        if (genericPtr->deleteFlag) {
        if (genericPtr->deleteFlag) {
            if (!genericHandlersActive) {
            if (!genericHandlersActive) {
                GenericHandler *tmpPtr;
                GenericHandler *tmpPtr;
 
 
                /*
                /*
                 * This handler needs to be deleted and there are no
                 * This handler needs to be deleted and there are no
                 * calls pending through the handler, so now is a safe
                 * calls pending through the handler, so now is a safe
                 * time to delete it.
                 * time to delete it.
                 */
                 */
 
 
                tmpPtr = genericPtr->nextPtr;
                tmpPtr = genericPtr->nextPtr;
                if (genPrevPtr == NULL) {
                if (genPrevPtr == NULL) {
                    genericList = tmpPtr;
                    genericList = tmpPtr;
                } else {
                } else {
                    genPrevPtr->nextPtr = tmpPtr;
                    genPrevPtr->nextPtr = tmpPtr;
                }
                }
                if (tmpPtr == NULL) {
                if (tmpPtr == NULL) {
                    lastGenericPtr = genPrevPtr;
                    lastGenericPtr = genPrevPtr;
                }
                }
                (void) ckfree((char *) genericPtr);
                (void) ckfree((char *) genericPtr);
                genericPtr = tmpPtr;
                genericPtr = tmpPtr;
                continue;
                continue;
            }
            }
        } else {
        } else {
            int done;
            int done;
 
 
            genericHandlersActive++;
            genericHandlersActive++;
            done = (*genericPtr->proc)(genericPtr->clientData, eventPtr);
            done = (*genericPtr->proc)(genericPtr->clientData, eventPtr);
            genericHandlersActive--;
            genericHandlersActive--;
            if (done) {
            if (done) {
                return;
                return;
            }
            }
        }
        }
        genPrevPtr = genericPtr;
        genPrevPtr = genericPtr;
        genericPtr = genPrevPtr->nextPtr;
        genericPtr = genPrevPtr->nextPtr;
    }
    }
 
 
    /*
    /*
     * If the event is a MappingNotify event, find its display and
     * If the event is a MappingNotify event, find its display and
     * refresh the keyboard mapping information for the display.
     * refresh the keyboard mapping information for the display.
     * After that there's nothing else to do with the event, so just
     * After that there's nothing else to do with the event, so just
     * quit.
     * quit.
     */
     */
 
 
    if (eventPtr->type == MappingNotify) {
    if (eventPtr->type == MappingNotify) {
        dispPtr = TkGetDisplay(eventPtr->xmapping.display);
        dispPtr = TkGetDisplay(eventPtr->xmapping.display);
        if (dispPtr != NULL) {
        if (dispPtr != NULL) {
            XRefreshKeyboardMapping(&eventPtr->xmapping);
            XRefreshKeyboardMapping(&eventPtr->xmapping);
            dispPtr->bindInfoStale = 1;
            dispPtr->bindInfoStale = 1;
        }
        }
        return;
        return;
    }
    }
 
 
    /*
    /*
     * Events selected by StructureNotify require special handling.
     * Events selected by StructureNotify require special handling.
     * They look the same as those selected by SubstructureNotify.
     * They look the same as those selected by SubstructureNotify.
     * The only difference is whether the "event" and "window" fields
     * The only difference is whether the "event" and "window" fields
     * are the same.  Compare the two fields and convert StructureNotify
     * are the same.  Compare the two fields and convert StructureNotify
     * to SubstructureNotify if necessary.
     * to SubstructureNotify if necessary.
     */
     */
 
 
    handlerWindow = eventPtr->xany.window;
    handlerWindow = eventPtr->xany.window;
    mask = eventMasks[eventPtr->xany.type];
    mask = eventMasks[eventPtr->xany.type];
    if (mask == StructureNotifyMask) {
    if (mask == StructureNotifyMask) {
        if (eventPtr->xmap.event != eventPtr->xmap.window) {
        if (eventPtr->xmap.event != eventPtr->xmap.window) {
            mask = SubstructureNotifyMask;
            mask = SubstructureNotifyMask;
            handlerWindow = eventPtr->xmap.event;
            handlerWindow = eventPtr->xmap.event;
        }
        }
    }
    }
    winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);
    winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);
    if (winPtr == NULL) {
    if (winPtr == NULL) {
 
 
        /*
        /*
         * There isn't a TkWindow structure for this window.
         * There isn't a TkWindow structure for this window.
         * However, if the event is a PropertyNotify event then call
         * However, if the event is a PropertyNotify event then call
         * the selection manager (it deals beneath-the-table with
         * the selection manager (it deals beneath-the-table with
         * certain properties).
         * certain properties).
         */
         */
 
 
        if (eventPtr->type == PropertyNotify) {
        if (eventPtr->type == PropertyNotify) {
            TkSelPropProc(eventPtr);
            TkSelPropProc(eventPtr);
        }
        }
        return;
        return;
    }
    }
 
 
    /*
    /*
     * Once a window has started getting deleted, don't process any more
     * Once a window has started getting deleted, don't process any more
     * events for it except for the DestroyNotify event.  This check is
     * events for it except for the DestroyNotify event.  This check is
     * needed because a DestroyNotify handler could re-invoke the event
     * needed because a DestroyNotify handler could re-invoke the event
     * loop, causing other pending events to be handled for the window
     * loop, causing other pending events to be handled for the window
     * (the window doesn't get totally expunged from our tables until
     * (the window doesn't get totally expunged from our tables until
     * after the DestroyNotify event has been completely handled).
     * after the DestroyNotify event has been completely handled).
     */
     */
 
 
    if ((winPtr->flags & TK_ALREADY_DEAD)
    if ((winPtr->flags & TK_ALREADY_DEAD)
            && (eventPtr->type != DestroyNotify)) {
            && (eventPtr->type != DestroyNotify)) {
        return;
        return;
    }
    }
 
 
    if (winPtr->mainPtr != NULL) {
    if (winPtr->mainPtr != NULL) {
 
 
        /*
        /*
         * Protect interpreter for this window from possible deletion
         * Protect interpreter for this window from possible deletion
         * while we are dealing with the event for this window. Thus,
         * while we are dealing with the event for this window. Thus,
         * widget writers do not have to worry about protecting the
         * widget writers do not have to worry about protecting the
         * interpreter in their own code.
         * interpreter in their own code.
         */
         */
 
 
        interp = winPtr->mainPtr->interp;
        interp = winPtr->mainPtr->interp;
        Tcl_Preserve((ClientData) interp);
        Tcl_Preserve((ClientData) interp);
 
 
        /*
        /*
         * Call focus-related code to look at FocusIn, FocusOut, Enter,
         * Call focus-related code to look at FocusIn, FocusOut, Enter,
         * and Leave events;  depending on its return value, ignore the
         * and Leave events;  depending on its return value, ignore the
         * event.
         * event.
         */
         */
 
 
        if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask))
        if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask))
                && !TkFocusFilterEvent(winPtr, eventPtr)) {
                && !TkFocusFilterEvent(winPtr, eventPtr)) {
            Tcl_Release((ClientData) interp);
            Tcl_Release((ClientData) interp);
            return;
            return;
        }
        }
 
 
        /*
        /*
         * Redirect KeyPress and KeyRelease events to the focus window,
         * Redirect KeyPress and KeyRelease events to the focus window,
         * or ignore them entirely if there is no focus window.  We also
         * or ignore them entirely if there is no focus window.  We also
         * route the MouseWheel event to the focus window.  The MouseWheel
         * route the MouseWheel event to the focus window.  The MouseWheel
         * event is an extension to the X event set.  Currently, it is only
         * event is an extension to the X event set.  Currently, it is only
         * available on the Windows version of Tk.
         * available on the Windows version of Tk.
         */
         */
 
 
        if (mask & (KeyPressMask|KeyReleaseMask|MouseWheelMask)) {
        if (mask & (KeyPressMask|KeyReleaseMask|MouseWheelMask)) {
            winPtr->dispPtr->lastEventTime = eventPtr->xkey.time;
            winPtr->dispPtr->lastEventTime = eventPtr->xkey.time;
            winPtr = TkFocusKeyEvent(winPtr, eventPtr);
            winPtr = TkFocusKeyEvent(winPtr, eventPtr);
            if (winPtr == NULL) {
            if (winPtr == NULL) {
                Tcl_Release((ClientData) interp);
                Tcl_Release((ClientData) interp);
                return;
                return;
            }
            }
        }
        }
 
 
        /*
        /*
         * Call a grab-related procedure to do special processing on
         * Call a grab-related procedure to do special processing on
         * pointer events.
         * pointer events.
         */
         */
 
 
        if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask
        if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask
                |EnterWindowMask|LeaveWindowMask)) {
                |EnterWindowMask|LeaveWindowMask)) {
            if (mask & (ButtonPressMask|ButtonReleaseMask)) {
            if (mask & (ButtonPressMask|ButtonReleaseMask)) {
                winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time;
                winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time;
            } else if (mask & PointerMotionMask) {
            } else if (mask & PointerMotionMask) {
                winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time;
                winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time;
            } else {
            } else {
                winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time;
                winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time;
            }
            }
            if (TkPointerEvent(eventPtr, winPtr) == 0) {
            if (TkPointerEvent(eventPtr, winPtr) == 0) {
                goto done;
                goto done;
            }
            }
        }
        }
    }
    }
 
 
#ifdef TK_USE_INPUT_METHODS
#ifdef TK_USE_INPUT_METHODS
    /*
    /*
     * Pass the event to the input method(s), if there are any, and
     * Pass the event to the input method(s), if there are any, and
     * discard the event if the input method(s) insist.  Create the
     * discard the event if the input method(s) insist.  Create the
     * input context for the window if it hasn't already been done
     * input context for the window if it hasn't already been done
     * (XFilterEvent needs this context).
     * (XFilterEvent needs this context).
     */
     */
 
 
    if (!(winPtr->flags & TK_CHECKED_IC)) {
    if (!(winPtr->flags & TK_CHECKED_IC)) {
        if (winPtr->dispPtr->inputMethod != NULL) {
        if (winPtr->dispPtr->inputMethod != NULL) {
            winPtr->inputContext = XCreateIC(
            winPtr->inputContext = XCreateIC(
                    winPtr->dispPtr->inputMethod, XNInputStyle,
                    winPtr->dispPtr->inputMethod, XNInputStyle,
                    XIMPreeditNothing|XIMStatusNothing,
                    XIMPreeditNothing|XIMStatusNothing,
                    XNClientWindow, winPtr->window,
                    XNClientWindow, winPtr->window,
                    XNFocusWindow, winPtr->window, NULL);
                    XNFocusWindow, winPtr->window, NULL);
        }
        }
        winPtr->flags |= TK_CHECKED_IC;
        winPtr->flags |= TK_CHECKED_IC;
    }
    }
    if (XFilterEvent(eventPtr, None)) {
    if (XFilterEvent(eventPtr, None)) {
        goto done;
        goto done;
    }
    }
#endif /* TK_USE_INPUT_METHODS */
#endif /* TK_USE_INPUT_METHODS */
 
 
    /*
    /*
     * For events where it hasn't already been done, update the current
     * For events where it hasn't already been done, update the current
     * time in the display.
     * time in the display.
     */
     */
 
 
    if (eventPtr->type == PropertyNotify) {
    if (eventPtr->type == PropertyNotify) {
        winPtr->dispPtr->lastEventTime = eventPtr->xproperty.time;
        winPtr->dispPtr->lastEventTime = eventPtr->xproperty.time;
    }
    }
 
 
    /*
    /*
     * There's a potential interaction here with Tk_DeleteEventHandler.
     * There's a potential interaction here with Tk_DeleteEventHandler.
     * Read the documentation for pendingPtr.
     * Read the documentation for pendingPtr.
     */
     */
 
 
    ip.eventPtr = eventPtr;
    ip.eventPtr = eventPtr;
    ip.winPtr = winPtr;
    ip.winPtr = winPtr;
    ip.nextHandler = NULL;
    ip.nextHandler = NULL;
    ip.nextPtr = pendingPtr;
    ip.nextPtr = pendingPtr;
    pendingPtr = &ip;
    pendingPtr = &ip;
    if (mask == 0) {
    if (mask == 0) {
        if ((eventPtr->type == SelectionClear)
        if ((eventPtr->type == SelectionClear)
                || (eventPtr->type == SelectionRequest)
                || (eventPtr->type == SelectionRequest)
                || (eventPtr->type == SelectionNotify)) {
                || (eventPtr->type == SelectionNotify)) {
            TkSelEventProc((Tk_Window) winPtr, eventPtr);
            TkSelEventProc((Tk_Window) winPtr, eventPtr);
        } else if ((eventPtr->type == ClientMessage)
        } else if ((eventPtr->type == ClientMessage)
                && (eventPtr->xclient.message_type ==
                && (eventPtr->xclient.message_type ==
                    Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS"))) {
                    Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS"))) {
            TkWmProtocolEventProc(winPtr, eventPtr);
            TkWmProtocolEventProc(winPtr, eventPtr);
        }
        }
    } else {
    } else {
        for (handlerPtr = winPtr->handlerList; handlerPtr != NULL; ) {
        for (handlerPtr = winPtr->handlerList; handlerPtr != NULL; ) {
            if ((handlerPtr->mask & mask) != 0) {
            if ((handlerPtr->mask & mask) != 0) {
                ip.nextHandler = handlerPtr->nextPtr;
                ip.nextHandler = handlerPtr->nextPtr;
                (*(handlerPtr->proc))(handlerPtr->clientData, eventPtr);
                (*(handlerPtr->proc))(handlerPtr->clientData, eventPtr);
                handlerPtr = ip.nextHandler;
                handlerPtr = ip.nextHandler;
            } else {
            } else {
                handlerPtr = handlerPtr->nextPtr;
                handlerPtr = handlerPtr->nextPtr;
            }
            }
        }
        }
 
 
        /*
        /*
         * Pass the event to the "bind" command mechanism.  But, don't
         * Pass the event to the "bind" command mechanism.  But, don't
         * do this for SubstructureNotify events.  The "bind" command
         * do this for SubstructureNotify events.  The "bind" command
         * doesn't support them anyway, and it's easier to filter out
         * doesn't support them anyway, and it's easier to filter out
         * these events here than in the lower-level procedures.
         * these events here than in the lower-level procedures.
         */
         */
 
 
        if ((ip.winPtr != None) && (mask != SubstructureNotifyMask)) {
        if ((ip.winPtr != None) && (mask != SubstructureNotifyMask)) {
            TkBindEventProc(winPtr, eventPtr);
            TkBindEventProc(winPtr, eventPtr);
        }
        }
    }
    }
    pendingPtr = ip.nextPtr;
    pendingPtr = ip.nextPtr;
done:
done:
 
 
    /*
    /*
     * Release the interpreter for this window so that it can be potentially
     * Release the interpreter for this window so that it can be potentially
     * deleted if requested.
     * deleted if requested.
     */
     */
 
 
    if (interp != (Tcl_Interp *) NULL) {
    if (interp != (Tcl_Interp *) NULL) {
        Tcl_Release((ClientData) interp);
        Tcl_Release((ClientData) interp);
    }
    }
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * TkEventDeadWindow --
 * TkEventDeadWindow --
 *
 *
 *      This procedure is invoked when it is determined that
 *      This procedure is invoked when it is determined that
 *      a window is dead.  It cleans up event-related information
 *      a window is dead.  It cleans up event-related information
 *      about the window.
 *      about the window.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Various things get cleaned up and recycled.
 *      Various things get cleaned up and recycled.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
TkEventDeadWindow(winPtr)
TkEventDeadWindow(winPtr)
    TkWindow *winPtr;           /* Information about the window
    TkWindow *winPtr;           /* Information about the window
                                 * that is being deleted. */
                                 * that is being deleted. */
{
{
    register TkEventHandler *handlerPtr;
    register TkEventHandler *handlerPtr;
    register InProgress *ipPtr;
    register InProgress *ipPtr;
 
 
    /*
    /*
     * While deleting all the handlers, be careful to check for
     * While deleting all the handlers, be careful to check for
     * Tk_HandleEvent being about to process one of the deleted
     * Tk_HandleEvent being about to process one of the deleted
     * handlers.  If it is, tell it to quit (all of the handlers
     * handlers.  If it is, tell it to quit (all of the handlers
     * are being deleted).
     * are being deleted).
     */
     */
 
 
    while (winPtr->handlerList != NULL) {
    while (winPtr->handlerList != NULL) {
        handlerPtr = winPtr->handlerList;
        handlerPtr = winPtr->handlerList;
        winPtr->handlerList = handlerPtr->nextPtr;
        winPtr->handlerList = handlerPtr->nextPtr;
        for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
        for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
            if (ipPtr->nextHandler == handlerPtr) {
            if (ipPtr->nextHandler == handlerPtr) {
                ipPtr->nextHandler = NULL;
                ipPtr->nextHandler = NULL;
            }
            }
            if (ipPtr->winPtr == winPtr) {
            if (ipPtr->winPtr == winPtr) {
                ipPtr->winPtr = None;
                ipPtr->winPtr = None;
            }
            }
        }
        }
        ckfree((char *) handlerPtr);
        ckfree((char *) handlerPtr);
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * TkCurrentTime --
 * TkCurrentTime --
 *
 *
 *      Try to deduce the current time.  "Current time" means the time
 *      Try to deduce the current time.  "Current time" means the time
 *      of the event that led to the current code being executed, which
 *      of the event that led to the current code being executed, which
 *      means the time in the most recently-nested invocation of
 *      means the time in the most recently-nested invocation of
 *      Tk_HandleEvent.
 *      Tk_HandleEvent.
 *
 *
 * Results:
 * Results:
 *      The return value is the time from the current event, or
 *      The return value is the time from the current event, or
 *      CurrentTime if there is no current event or if the current
 *      CurrentTime if there is no current event or if the current
 *      event contains no time.
 *      event contains no time.
 *
 *
 * Side effects:
 * Side effects:
 *      None.
 *      None.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
Time
Time
TkCurrentTime(dispPtr)
TkCurrentTime(dispPtr)
    TkDisplay *dispPtr;         /* Display for which the time is desired. */
    TkDisplay *dispPtr;         /* Display for which the time is desired. */
{
{
    register XEvent *eventPtr;
    register XEvent *eventPtr;
 
 
    if (pendingPtr == NULL) {
    if (pendingPtr == NULL) {
        return dispPtr->lastEventTime;
        return dispPtr->lastEventTime;
    }
    }
    eventPtr = pendingPtr->eventPtr;
    eventPtr = pendingPtr->eventPtr;
    switch (eventPtr->type) {
    switch (eventPtr->type) {
        case ButtonPress:
        case ButtonPress:
        case ButtonRelease:
        case ButtonRelease:
            return eventPtr->xbutton.time;
            return eventPtr->xbutton.time;
        case KeyPress:
        case KeyPress:
        case KeyRelease:
        case KeyRelease:
            return eventPtr->xkey.time;
            return eventPtr->xkey.time;
        case MotionNotify:
        case MotionNotify:
            return eventPtr->xmotion.time;
            return eventPtr->xmotion.time;
        case EnterNotify:
        case EnterNotify:
        case LeaveNotify:
        case LeaveNotify:
            return eventPtr->xcrossing.time;
            return eventPtr->xcrossing.time;
        case PropertyNotify:
        case PropertyNotify:
            return eventPtr->xproperty.time;
            return eventPtr->xproperty.time;
    }
    }
    return dispPtr->lastEventTime;
    return dispPtr->lastEventTime;
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * Tk_RestrictEvents --
 * Tk_RestrictEvents --
 *
 *
 *      This procedure is used to globally restrict the set of events
 *      This procedure is used to globally restrict the set of events
 *      that will be dispatched.  The restriction is done by filtering
 *      that will be dispatched.  The restriction is done by filtering
 *      all incoming X events through a procedure that determines
 *      all incoming X events through a procedure that determines
 *      whether they are to be processed immediately, deferred, or
 *      whether they are to be processed immediately, deferred, or
 *      discarded.
 *      discarded.
 *
 *
 * Results:
 * Results:
 *      The return value is the previous restriction procedure in effect,
 *      The return value is the previous restriction procedure in effect,
 *      if there was one, or NULL if there wasn't.
 *      if there was one, or NULL if there wasn't.
 *
 *
 * Side effects:
 * Side effects:
 *      From now on, proc will be called to determine whether to process,
 *      From now on, proc will be called to determine whether to process,
 *      defer or discard each incoming X event.
 *      defer or discard each incoming X event.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
Tk_RestrictProc *
Tk_RestrictProc *
Tk_RestrictEvents(proc, arg, prevArgPtr)
Tk_RestrictEvents(proc, arg, prevArgPtr)
    Tk_RestrictProc *proc;      /* Procedure to call for each incoming
    Tk_RestrictProc *proc;      /* Procedure to call for each incoming
                                 * event. */
                                 * event. */
    ClientData arg;             /* Arbitrary argument to pass to proc. */
    ClientData arg;             /* Arbitrary argument to pass to proc. */
    ClientData *prevArgPtr;     /* Place to store information about previous
    ClientData *prevArgPtr;     /* Place to store information about previous
                                 * argument. */
                                 * argument. */
{
{
    Tk_RestrictProc *prev;
    Tk_RestrictProc *prev;
 
 
    prev = restrictProc;
    prev = restrictProc;
    *prevArgPtr = restrictArg;
    *prevArgPtr = restrictArg;
    restrictProc = proc;
    restrictProc = proc;
    restrictArg = arg;
    restrictArg = arg;
    return prev;
    return prev;
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * Tk_QueueWindowEvent --
 * Tk_QueueWindowEvent --
 *
 *
 *      Given an X-style window event, this procedure adds it to the
 *      Given an X-style window event, this procedure adds it to the
 *      Tcl event queue at the given position.  This procedure also
 *      Tcl event queue at the given position.  This procedure also
 *      performs mouse motion event collapsing if possible.
 *      performs mouse motion event collapsing if possible.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Adds stuff to the event queue, which will eventually be
 *      Adds stuff to the event queue, which will eventually be
 *      processed.
 *      processed.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
void
void
Tk_QueueWindowEvent(eventPtr, position)
Tk_QueueWindowEvent(eventPtr, position)
    XEvent *eventPtr;                   /* Event to add to queue.  This
    XEvent *eventPtr;                   /* Event to add to queue.  This
                                         * procedures copies it before adding
                                         * procedures copies it before adding
                                         * it to the queue. */
                                         * it to the queue. */
    Tcl_QueuePosition position;         /* Where to put it on the queue:
    Tcl_QueuePosition position;         /* Where to put it on the queue:
                                         * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
                                         * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
                                         * or TCL_QUEUE_MARK. */
                                         * or TCL_QUEUE_MARK. */
{
{
    TkWindowEvent *wevPtr;
    TkWindowEvent *wevPtr;
    TkDisplay *dispPtr;
    TkDisplay *dispPtr;
 
 
    /*
    /*
     * Find our display structure for the event's display.
     * Find our display structure for the event's display.
     */
     */
 
 
    for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
    for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
        if (dispPtr == NULL) {
        if (dispPtr == NULL) {
            return;
            return;
        }
        }
        if (dispPtr->display == eventPtr->xany.display) {
        if (dispPtr->display == eventPtr->xany.display) {
            break;
            break;
        }
        }
    }
    }
 
 
    if ((dispPtr->delayedMotionPtr != NULL) && (position == TCL_QUEUE_TAIL)) {
    if ((dispPtr->delayedMotionPtr != NULL) && (position == TCL_QUEUE_TAIL)) {
        if ((eventPtr->type == MotionNotify) && (eventPtr->xmotion.window
        if ((eventPtr->type == MotionNotify) && (eventPtr->xmotion.window
                == dispPtr->delayedMotionPtr->event.xmotion.window)) {
                == dispPtr->delayedMotionPtr->event.xmotion.window)) {
            /*
            /*
             * The new event is a motion event in the same window as the
             * The new event is a motion event in the same window as the
             * saved motion event.  Just replace the saved event with the
             * saved motion event.  Just replace the saved event with the
             * new one.
             * new one.
             */
             */
 
 
            dispPtr->delayedMotionPtr->event = *eventPtr;
            dispPtr->delayedMotionPtr->event = *eventPtr;
            return;
            return;
        } else if ((eventPtr->type != GraphicsExpose)
        } else if ((eventPtr->type != GraphicsExpose)
                && (eventPtr->type != NoExpose)
                && (eventPtr->type != NoExpose)
                && (eventPtr->type != Expose)) {
                && (eventPtr->type != Expose)) {
            /*
            /*
             * The new event may conflict with the saved motion event.  Queue
             * The new event may conflict with the saved motion event.  Queue
             * the saved motion event now so that it will be processed before
             * the saved motion event now so that it will be processed before
             * the new event.
             * the new event.
             */
             */
 
 
            Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, position);
            Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, position);
            dispPtr->delayedMotionPtr = NULL;
            dispPtr->delayedMotionPtr = NULL;
            Tcl_CancelIdleCall(DelayedMotionProc, (ClientData) dispPtr);
            Tcl_CancelIdleCall(DelayedMotionProc, (ClientData) dispPtr);
        }
        }
    }
    }
 
 
    wevPtr = (TkWindowEvent *) ckalloc(sizeof(TkWindowEvent));
    wevPtr = (TkWindowEvent *) ckalloc(sizeof(TkWindowEvent));
    wevPtr->header.proc = WindowEventProc;
    wevPtr->header.proc = WindowEventProc;
    wevPtr->event = *eventPtr;
    wevPtr->event = *eventPtr;
    if ((eventPtr->type == MotionNotify) && (position == TCL_QUEUE_TAIL)) {
    if ((eventPtr->type == MotionNotify) && (position == TCL_QUEUE_TAIL)) {
        /*
        /*
         * The new event is a motion event so don't queue it immediately;
         * The new event is a motion event so don't queue it immediately;
         * save it around in case another motion event arrives that it can
         * save it around in case another motion event arrives that it can
         * be collapsed with.
         * be collapsed with.
         */
         */
 
 
        if (dispPtr->delayedMotionPtr != NULL) {
        if (dispPtr->delayedMotionPtr != NULL) {
            panic("Tk_QueueWindowEvent found unexpected delayed motion event");
            panic("Tk_QueueWindowEvent found unexpected delayed motion event");
        }
        }
        dispPtr->delayedMotionPtr = wevPtr;
        dispPtr->delayedMotionPtr = wevPtr;
        Tcl_DoWhenIdle(DelayedMotionProc, (ClientData) dispPtr);
        Tcl_DoWhenIdle(DelayedMotionProc, (ClientData) dispPtr);
    } else {
    } else {
        Tcl_QueueEvent(&wevPtr->header, position);
        Tcl_QueueEvent(&wevPtr->header, position);
    }
    }
}
}


/*
/*
 *---------------------------------------------------------------------------
 *---------------------------------------------------------------------------
 *
 *
 * TkQueueEventForAllChildren --
 * TkQueueEventForAllChildren --
 *
 *
 *      Given an XEvent, recursively queue the event for this window and
 *      Given an XEvent, recursively queue the event for this window and
 *      all non-toplevel children of the given window.
 *      all non-toplevel children of the given window.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Events queued.
 *      Events queued.
 *
 *
 *---------------------------------------------------------------------------
 *---------------------------------------------------------------------------
 */
 */
 
 
void
void
TkQueueEventForAllChildren(winPtr, eventPtr)
TkQueueEventForAllChildren(winPtr, eventPtr)
    TkWindow *winPtr;       /* Window to which event is sent. */
    TkWindow *winPtr;       /* Window to which event is sent. */
    XEvent *eventPtr;       /* The event to be sent. */
    XEvent *eventPtr;       /* The event to be sent. */
{
{
    TkWindow *childPtr;
    TkWindow *childPtr;
 
 
    eventPtr->xany.window = winPtr->window;
    eventPtr->xany.window = winPtr->window;
    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
 
 
    childPtr = winPtr->childList;
    childPtr = winPtr->childList;
    while (childPtr != NULL) {
    while (childPtr != NULL) {
        if (!Tk_IsTopLevel(childPtr)) {
        if (!Tk_IsTopLevel(childPtr)) {
            TkQueueEventForAllChildren(childPtr, eventPtr);
            TkQueueEventForAllChildren(childPtr, eventPtr);
        }
        }
        childPtr = childPtr->nextPtr;
        childPtr = childPtr->nextPtr;
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * WindowEventProc --
 * WindowEventProc --
 *
 *
 *      This procedure is called by Tcl_DoOneEvent when a window event
 *      This procedure is called by Tcl_DoOneEvent when a window event
 *      reaches the front of the event queue.  This procedure is responsible
 *      reaches the front of the event queue.  This procedure is responsible
 *      for actually handling the event.
 *      for actually handling the event.
 *
 *
 * Results:
 * Results:
 *      Returns 1 if the event was handled, meaning it should be removed
 *      Returns 1 if the event was handled, meaning it should be removed
 *      from the queue.  Returns 0 if the event was not handled, meaning
 *      from the queue.  Returns 0 if the event was not handled, meaning
 *      it should stay on the queue.  The event isn't handled if the
 *      it should stay on the queue.  The event isn't handled if the
 *      TCL_WINDOW_EVENTS bit isn't set in flags, if a restrict proc
 *      TCL_WINDOW_EVENTS bit isn't set in flags, if a restrict proc
 *      prevents the event from being handled.
 *      prevents the event from being handled.
 *
 *
 * Side effects:
 * Side effects:
 *      Whatever the event handlers for the event do.
 *      Whatever the event handlers for the event do.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static int
static int
WindowEventProc(evPtr, flags)
WindowEventProc(evPtr, flags)
    Tcl_Event *evPtr;           /* Event to service. */
    Tcl_Event *evPtr;           /* Event to service. */
    int flags;                  /* Flags that indicate what events to
    int flags;                  /* Flags that indicate what events to
                                 * handle, such as TCL_WINDOW_EVENTS. */
                                 * handle, such as TCL_WINDOW_EVENTS. */
{
{
    TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;
    TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;
    Tk_RestrictAction result;
    Tk_RestrictAction result;
 
 
    if (!(flags & TCL_WINDOW_EVENTS)) {
    if (!(flags & TCL_WINDOW_EVENTS)) {
        return 0;
        return 0;
    }
    }
    if (restrictProc != NULL) {
    if (restrictProc != NULL) {
        result = (*restrictProc)(restrictArg, &wevPtr->event);
        result = (*restrictProc)(restrictArg, &wevPtr->event);
        if (result != TK_PROCESS_EVENT) {
        if (result != TK_PROCESS_EVENT) {
            if (result == TK_DEFER_EVENT) {
            if (result == TK_DEFER_EVENT) {
                return 0;
                return 0;
            } else {
            } else {
                /*
                /*
                 * TK_DELETE_EVENT: return and say we processed the event,
                 * TK_DELETE_EVENT: return and say we processed the event,
                 * even though we didn't do anything at all.
                 * even though we didn't do anything at all.
                 */
                 */
                return 1;
                return 1;
            }
            }
        }
        }
    }
    }
    Tk_HandleEvent(&wevPtr->event);
    Tk_HandleEvent(&wevPtr->event);
    return 1;
    return 1;
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * DelayedMotionProc --
 * DelayedMotionProc --
 *
 *
 *      This procedure is invoked as an idle handler when a mouse motion
 *      This procedure is invoked as an idle handler when a mouse motion
 *      event has been delayed.  It queues the delayed event so that it
 *      event has been delayed.  It queues the delayed event so that it
 *      will finally be serviced.
 *      will finally be serviced.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      The delayed mouse motion event gets added to the Tcl event
 *      The delayed mouse motion event gets added to the Tcl event
 *      queue for servicing.
 *      queue for servicing.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
DelayedMotionProc(clientData)
DelayedMotionProc(clientData)
    ClientData clientData;      /* Pointer to display containing a delayed
    ClientData clientData;      /* Pointer to display containing a delayed
                                 * motion event to be serviced. */
                                 * motion event to be serviced. */
{
{
    TkDisplay *dispPtr = (TkDisplay *) clientData;
    TkDisplay *dispPtr = (TkDisplay *) clientData;
 
 
    if (dispPtr->delayedMotionPtr == NULL) {
    if (dispPtr->delayedMotionPtr == NULL) {
        panic("DelayedMotionProc found no delayed mouse motion event");
        panic("DelayedMotionProc found no delayed mouse motion event");
    }
    }
    Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, TCL_QUEUE_TAIL);
    Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, TCL_QUEUE_TAIL);
    dispPtr->delayedMotionPtr = NULL;
    dispPtr->delayedMotionPtr = NULL;
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_MainLoop --
 * Tk_MainLoop --
 *
 *
 *      Call Tcl_DoOneEvent over and over again in an infinite
 *      Call Tcl_DoOneEvent over and over again in an infinite
 *      loop as long as there exist any main windows.
 *      loop as long as there exist any main windows.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Arbitrary;  depends on handlers for events.
 *      Arbitrary;  depends on handlers for events.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_MainLoop()
Tk_MainLoop()
{
{
    while (Tk_GetNumMainWindows() > 0) {
    while (Tk_GetNumMainWindows() > 0) {
        Tcl_DoOneEvent(0);
        Tcl_DoOneEvent(0);
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.