summaryrefslogtreecommitdiffstats
path: root/generic/tkEvent.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkEvent.c')
-rw-r--r--generic/tkEvent.c145
1 files changed, 103 insertions, 42 deletions
diff --git a/generic/tkEvent.c b/generic/tkEvent.c
index 6403001..a72be72 100644
--- a/generic/tkEvent.c
+++ b/generic/tkEvent.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkEvent.c,v 1.3 1998/10/10 00:30:36 rjohnson Exp $
+ * RCS: @(#) $Id: tkEvent.c,v 1.4 1999/04/16 01:51:13 stanton Exp $
*/
#include "tkPort.h"
@@ -39,10 +39,6 @@ typedef struct InProgress {
struct InProgress *nextPtr; /* Next higher nested search. */
} InProgress;
-static InProgress *pendingPtr = NULL;
- /* Topmost search in progress, or
- * NULL if none. */
-
/*
* For each call to Tk_CreateGenericHandler, an instance of the following
* structure will be created. All of the active handlers are linked into a
@@ -58,11 +54,6 @@ typedef struct GenericHandler {
* handlers, or NULL for end of list. */
} GenericHandler;
-static GenericHandler *genericList = NULL;
- /* First handler in the list, or NULL. */
-static GenericHandler *lastGenericPtr = NULL;
- /* Last handler in list. */
-
/*
* There's a potential problem if Tk_HandleEvent is entered recursively.
* A handler cannot be deleted physically until we have returned from
@@ -70,11 +61,8 @@ static GenericHandler *lastGenericPtr = NULL;
* 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.
*
- * The following variable has a non-zero value when a handler is active.
*/
-static int genericHandlersActive = 0;
-
/*
* The following structure is used for queueing X-style events on the
* Tcl event queue.
@@ -134,15 +122,37 @@ static unsigned long eventMasks[TK_LASTEVENT] = {
MouseWheelMask /* MouseWheelEvent */
};
+
/*
- * If someone has called Tk_RestrictEvents, the information below
- * keeps track of it.
+ * The structure below is used to store Data for the Event module that
+ * must be kept thread-local. The "dataKey" is used to fetch the
+ * thread-specific storage for the current thread.
*/
-static Tk_RestrictProc *restrictProc;
+typedef struct ThreadSpecificData {
+
+ int genericHandlersActive;
+ /* The following variable has a non-zero
+ * value when a handler is active. */
+ InProgress *pendingPtr;
+ /* Topmost search in progress, or
+ * NULL if none. */
+ GenericHandler *genericList;
+ /* First handler in the list, or NULL. */
+ GenericHandler *lastGenericPtr;
+ /* Last handler in list. */
+
+ /*
+ * If someone has called Tk_RestrictEvents, the information below
+ * keeps track of it.
+ */
+
+ Tk_RestrictProc *restrictProc;
/* Procedure to call. NULL means no
* restrictProc is currently in effect. */
-static ClientData restrictArg; /* Argument to pass to restrictProc. */
+ ClientData restrictArg; /* Argument to pass to restrictProc. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Prototypes for procedures that are only referenced locally within
@@ -266,6 +276,8 @@ Tk_DeleteEventHandler(token, mask, proc, clientData)
register InProgress *ipPtr;
TkEventHandler *prevPtr;
register TkWindow *winPtr = (TkWindow *) token;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Find the event handler to be deleted, or return
@@ -288,7 +300,7 @@ Tk_DeleteEventHandler(token, mask, proc, clientData)
* process the next one instead.
*/
- for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
if (ipPtr->nextHandler == handlerPtr) {
ipPtr->nextHandler = handlerPtr->nextPtr;
}
@@ -337,6 +349,8 @@ Tk_CreateGenericHandler(proc, clientData)
ClientData clientData; /* One-word value to pass to proc. */
{
GenericHandler *handlerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler));
@@ -344,12 +358,12 @@ Tk_CreateGenericHandler(proc, clientData)
handlerPtr->clientData = clientData;
handlerPtr->deleteFlag = 0;
handlerPtr->nextPtr = NULL;
- if (genericList == NULL) {
- genericList = handlerPtr;
+ if (tsdPtr->genericList == NULL) {
+ tsdPtr->genericList = handlerPtr;
} else {
- lastGenericPtr->nextPtr = handlerPtr;
+ tsdPtr->lastGenericPtr->nextPtr = handlerPtr;
}
- lastGenericPtr = handlerPtr;
+ tsdPtr->lastGenericPtr = handlerPtr;
}
/*
@@ -377,8 +391,10 @@ Tk_DeleteGenericHandler(proc, clientData)
ClientData clientData;
{
GenericHandler * handler;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- for (handler = genericList; handler; handler = handler->nextPtr) {
+ for (handler = tsdPtr->genericList; handler; handler = handler->nextPtr) {
if ((handler->proc == proc) && (handler->clientData == clientData)) {
handler->deleteFlag = 1;
}
@@ -388,6 +404,39 @@ Tk_DeleteGenericHandler(proc, clientData)
/*
*--------------------------------------------------------------
*
+ * TkEventInit --
+ *
+ * This procedures initializes all the event module
+ * structures used by the current thread. It must be
+ * called before any other procedure in this file is
+ * called.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkEventInit(void)
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->genericHandlersActive = 0;
+ tsdPtr->pendingPtr = NULL;
+ tsdPtr->genericList = NULL;
+ tsdPtr->lastGenericPtr = NULL;
+ tsdPtr->restrictProc = NULL;
+ tsdPtr->restrictArg = NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* Tk_HandleEvent --
*
* Given an event, invoke all the handlers that have
@@ -415,6 +464,8 @@ Tk_HandleEvent(eventPtr)
Window handlerWindow;
TkDisplay *dispPtr;
Tcl_Interp *interp = (Tcl_Interp *) NULL;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Next, invoke all the generic event handlers (those that are
@@ -422,9 +473,10 @@ Tk_HandleEvent(eventPtr)
* an event is fully processed, go no further.
*/
- for (genPrevPtr = NULL, genericPtr = genericList; genericPtr != NULL; ) {
+ for (genPrevPtr = NULL, genericPtr = tsdPtr->genericList;
+ genericPtr != NULL; ) {
if (genericPtr->deleteFlag) {
- if (!genericHandlersActive) {
+ if (!tsdPtr->genericHandlersActive) {
GenericHandler *tmpPtr;
/*
@@ -435,12 +487,12 @@ Tk_HandleEvent(eventPtr)
tmpPtr = genericPtr->nextPtr;
if (genPrevPtr == NULL) {
- genericList = tmpPtr;
+ tsdPtr->genericList = tmpPtr;
} else {
genPrevPtr->nextPtr = tmpPtr;
}
if (tmpPtr == NULL) {
- lastGenericPtr = genPrevPtr;
+ tsdPtr->lastGenericPtr = genPrevPtr;
}
(void) ckfree((char *) genericPtr);
genericPtr = tmpPtr;
@@ -449,9 +501,9 @@ Tk_HandleEvent(eventPtr)
} else {
int done;
- genericHandlersActive++;
+ tsdPtr->genericHandlersActive++;
done = (*genericPtr->proc)(genericPtr->clientData, eventPtr);
- genericHandlersActive--;
+ tsdPtr->genericHandlersActive--;
if (done) {
return;
}
@@ -623,8 +675,8 @@ Tk_HandleEvent(eventPtr)
ip.eventPtr = eventPtr;
ip.winPtr = winPtr;
ip.nextHandler = NULL;
- ip.nextPtr = pendingPtr;
- pendingPtr = &ip;
+ ip.nextPtr = tsdPtr->pendingPtr;
+ tsdPtr->pendingPtr = &ip;
if (mask == 0) {
if ((eventPtr->type == SelectionClear)
|| (eventPtr->type == SelectionRequest)
@@ -657,7 +709,7 @@ Tk_HandleEvent(eventPtr)
TkBindEventProc(winPtr, eventPtr);
}
}
- pendingPtr = ip.nextPtr;
+ tsdPtr->pendingPtr = ip.nextPtr;
done:
/*
@@ -695,6 +747,8 @@ TkEventDeadWindow(winPtr)
{
register TkEventHandler *handlerPtr;
register InProgress *ipPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* While deleting all the handlers, be careful to check for
@@ -706,7 +760,8 @@ TkEventDeadWindow(winPtr)
while (winPtr->handlerList != NULL) {
handlerPtr = winPtr->handlerList;
winPtr->handlerList = handlerPtr->nextPtr;
- for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
if (ipPtr->nextHandler == handlerPtr) {
ipPtr->nextHandler = NULL;
}
@@ -744,11 +799,13 @@ TkCurrentTime(dispPtr)
TkDisplay *dispPtr; /* Display for which the time is desired. */
{
register XEvent *eventPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (pendingPtr == NULL) {
+ if (tsdPtr->pendingPtr == NULL) {
return dispPtr->lastEventTime;
}
- eventPtr = pendingPtr->eventPtr;
+ eventPtr = tsdPtr->pendingPtr->eventPtr;
switch (eventPtr->type) {
case ButtonPress:
case ButtonRelease:
@@ -798,11 +855,13 @@ Tk_RestrictEvents(proc, arg, prevArgPtr)
* argument. */
{
Tk_RestrictProc *prev;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- prev = restrictProc;
- *prevArgPtr = restrictArg;
- restrictProc = proc;
- restrictArg = arg;
+ prev = tsdPtr->restrictProc;
+ *prevArgPtr = tsdPtr->restrictArg;
+ tsdPtr->restrictProc = proc;
+ tsdPtr->restrictArg = arg;
return prev;
}
@@ -841,7 +900,7 @@ Tk_QueueWindowEvent(eventPtr, position)
* Find our display structure for the event's display.
*/
- for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
+ for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
if (dispPtr == NULL) {
return;
}
@@ -962,12 +1021,14 @@ WindowEventProc(evPtr, flags)
{
TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;
Tk_RestrictAction result;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (!(flags & TCL_WINDOW_EVENTS)) {
return 0;
}
- if (restrictProc != NULL) {
- result = (*restrictProc)(restrictArg, &wevPtr->event);
+ if (tsdPtr->restrictProc != NULL) {
+ result = (*tsdPtr->restrictProc)(tsdPtr->restrictArg, &wevPtr->event);
if (result != TK_PROCESS_EVENT) {
if (result == TK_DEFER_EVENT) {
return 0;