summaryrefslogtreecommitdiffstats
path: root/generic/tkEvent.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2005-09-21 10:54:40 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2005-09-21 10:54:40 (GMT)
commitc6e0e2261b1585c0b28b7abfb41852b5750aaf13 (patch)
tree568c1c4a6a82c9fe3153dba25af68d61019419bc /generic/tkEvent.c
parent998bc689837b9f81b076f05e0320a141c72e8540 (diff)
downloadtk-c6e0e2261b1585c0b28b7abfb41852b5750aaf13.zip
tk-c6e0e2261b1585c0b28b7abfb41852b5750aaf13.tar.gz
tk-c6e0e2261b1585c0b28b7abfb41852b5750aaf13.tar.bz2
Tk-internal exit handler improvements. [Bug 749908]
Diffstat (limited to 'generic/tkEvent.c')
-rw-r--r--generic/tkEvent.c1338
1 files changed, 725 insertions, 613 deletions
diff --git a/generic/tkEvent.c b/generic/tkEvent.c
index 388fa49..fa81b65 100644
--- a/generic/tkEvent.c
+++ b/generic/tkEvent.c
@@ -1,18 +1,18 @@
/*
* tkEvent.c --
*
- * This file provides basic low-level facilities for managing
- * X events in Tk.
+ * This file provides basic low-level facilities for managing X events in
+ * Tk.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 Ajuba Solutions.
* Copyright (c) 2004 George Peter Staplin
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * 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.28 2005/06/03 19:03:23 wolfsuit Exp $
+ * RCS: @(#) $Id: tkEvent.c,v 1.29 2005/09/21 10:54:40 dkf Exp $
*/
#include "tkPort.h"
@@ -20,53 +20,52 @@
#include <signal.h>
/*
- * There's a potential problem if a handler is deleted while it's
- * current (i.e. its procedure is executing), since Tk_HandleEvent
- * will need to read the handler's "nextPtr" field when the procedure
- * returns. To handle this problem, structures of the type below
- * indicate the next handler to be processed for any (recursively
- * nested) dispatches in progress. The nextHandler fields get
- * updated if the handlers pointed to are deleted. Tk_HandleEvent
- * also needs to know if the entire window gets deleted; the winPtr
- * field is set to zero if that particular window gets deleted.
+ * There's a potential problem if a handler is deleted while it's current
+ * (i.e. its function is executing), since Tk_HandleEvent will need to read
+ * the handler's "nextPtr" field when the function returns. To handle this
+ * problem, structures of the type below indicate the next handler to be
+ * processed for any (recursively nested) dispatches in progress. The
+ * nextHandler fields get updated if the handlers pointed to are deleted.
+ * Tk_HandleEvent also needs to know if the entire window gets deleted; the
+ * winPtr field is set to zero if that particular window gets deleted.
*/
typedef struct InProgress {
- XEvent *eventPtr; /* Event currently being handled. */
- TkWindow *winPtr; /* Window for event. Gets set to None if
- * window is deleted while event is being
- * handled. */
- TkEventHandler *nextHandler; /* Next handler in search. */
- struct InProgress *nextPtr; /* Next higher nested search. */
+ XEvent *eventPtr; /* Event currently being handled. */
+ TkWindow *winPtr; /* Window for event. Gets set to None if
+ * window is deleted while event is being
+ * handled. */
+ TkEventHandler *nextHandler;/* Next handler in search. */
+ struct InProgress *nextPtr; /* Next higher nested search. */
} InProgress;
/*
* For each call to Tk_CreateGenericHandler or Tk_CreateClientMessageHandler,
- * an instance of the following structure will be created. All of the
- * active handlers are linked into a list.
+ * an instance of the following structure will be created. All of the active
+ * handlers are linked into a list.
*/
typedef struct GenericHandler {
- Tk_GenericProc *proc; /* Procedure to dispatch on all X events. */
- ClientData clientData; /* Client data to pass to procedure. */
- int deleteFlag; /* Flag to set when this handler is deleted. */
+ Tk_GenericProc *proc; /* Function to dispatch on all X events. */
+ ClientData clientData; /* Client data to pass to function. */
+ int deleteFlag; /* Flag to set when this handler is
+ * deleted. */
struct GenericHandler *nextPtr;
/* Next handler in list of all generic
* handlers, or NULL for end of list. */
} GenericHandler;
/*
- * There's a potential problem if Tk_HandleEvent is entered recursively.
- * A handler cannot be deleted physically until we have returned from
- * 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
+ * There's a potential problem if Tk_HandleEvent is entered recursively. A
+ * handler cannot be deleted physically until we have returned from 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
* deleting handlers only when it's known that there's no handler active.
- *
*/
/*
- * The following structure is used for queueing X-style events on the
- * Tcl event queue.
+ * The following structure is used for queueing X-style events on the Tcl
+ * event queue.
*/
typedef struct TkWindowEvent {
@@ -123,25 +122,37 @@ static unsigned long eventMasks[TK_LASTEVENT] = {
MouseWheelMask /* MouseWheelEvent */
};
+/*
+ * For each exit handler created with a call to TkCreateExitHandler or
+ * TkCreateThreadExitHandler there is a structure of the following type:
+ */
+
+typedef struct ExitHandler {
+ Tcl_ExitProc *proc; /* Function to call when process exits. */
+ ClientData clientData; /* One word of information to pass to proc. */
+ struct ExitHandler *nextPtr;/* Next in list of all exit handlers for this
+ * application, or NULL for end of list. */
+} ExitHandler;
/*
- * 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.
+ * 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.
*/
typedef struct ThreadSpecificData {
- int handlersActive; /* The following variable has a non-zero
- * value when a handler is active. */
- InProgress *pendingPtr; /* Topmost search in progress, or
- * NULL if none. */
+ int handlersActive; /* The following variable has a non-zero value
+ * when a handler is active. */
+ InProgress *pendingPtr; /* Topmost search in progress, or NULL if
+ * none. */
/*
* List of generic handler records.
*/
- GenericHandler *genericList; /* First handler in the list, or NULL. */
- GenericHandler *lastGenericPtr; /* Last handler in list. */
+ GenericHandler *genericList;/* First handler in the list, or NULL. */
+ GenericHandler *lastGenericPtr;
+ /* Last handler in list. */
/*
* List of client message handler records.
@@ -151,33 +162,25 @@ typedef struct ThreadSpecificData {
GenericHandler *lastCmPtr; /* Last handler in list. */
/*
- * If someone has called Tk_RestrictEvents, the information below
- * keeps track of it.
+ * If someone has called Tk_RestrictEvents, the information below keeps
+ * track of it.
*/
Tk_RestrictProc *restrictProc;
- /* Procedure to call. NULL means no
+ /* Function to call. NULL means no
* restrictProc is currently in effect. */
ClientData restrictArg; /* Argument to pass to restrictProc. */
+ ExitHandler *firstExitPtr; /* First in list of all exit handlers for this
+ * thread. */
+ int inExit; /* True when this thread is exiting. This is
+ * used as a hack to decide to close the
+ * standard channels. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
/*
- * For each exit handler created with a call to TkCreateExitHandler
- * there is a structure of the following type:
- */
-
-typedef struct ExitHandler {
- Tcl_ExitProc *proc; /* Procedure to call when process exits. */
- ClientData clientData; /* One word of information to pass to proc. */
- struct ExitHandler *nextPtr;/* Next in list of all exit handlers for
- * this application, or NULL for end of list. */
-} ExitHandler;
-
-/*
- * There is both per-process and per-thread exit handlers.
- * The first list is controlled by a mutex. The other is in
- * thread local storage.
+ * There are both per-process and per-thread exit handlers. The first list is
+ * controlled by a mutex. The other is in thread local storage.
*/
static ExitHandler *firstExitPtr = NULL;
@@ -186,95 +189,79 @@ static ExitHandler *firstExitPtr = NULL;
TCL_DECLARE_MUTEX(exitMutex)
/*
- * Prototypes for procedures that are only referenced locally within
- * this file.
+ * Prototypes for functions that are only referenced locally within this file.
*/
-static void DelayedMotionProc _ANSI_ARGS_((ClientData clientData));
-static int WindowEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
- int flags));
-static int TkXErrorHandler _ANSI_ARGS_((ClientData clientData,
- XErrorEvent *errEventPtr));
-
-static int InvokeGenericHandlers _ANSI_ARGS_((
- ThreadSpecificData *tsdPtr,
- XEvent *eventPtr));
-
-static int GetButtonMask _ANSI_ARGS_((unsigned int Button));
-
-static void UpdateButtonEventState _ANSI_ARGS_((XEvent *eventPtr));
-
-static void InvokeClientMessageHandlers _ANSI_ARGS_((
- ThreadSpecificData *tsdPtr,
- Tk_Window tkwin,
- XEvent *eventPtr));
-
-static int RefreshKeyboardMappingIfNeeded _ANSI_ARGS_((
- XEvent *eventPtr));
-
-static unsigned long GetEventMaskFromXEvent _ANSI_ARGS_((XEvent *eventPtr));
-
-static Window ParentXId _ANSI_ARGS_((Display *display, Window w));
-
-static TkWindow * GetTkWindowFromXEvent _ANSI_ARGS_((XEvent *eventPtr));
-
+static void DelayedMotionProc(ClientData clientData);
+static int GetButtonMask(unsigned int Button);
+static unsigned long GetEventMaskFromXEvent(XEvent *eventPtr);
+static TkWindow * GetTkWindowFromXEvent(XEvent *eventPtr);
+static void InvokeClientMessageHandlers(ThreadSpecificData *tsdPtr,
+ Tk_Window tkwin, XEvent *eventPtr);
+static int InvokeFocusHandlers(TkWindow **winPtrPtr,
+ unsigned long mask, XEvent *eventPtr);
+static int InvokeGenericHandlers(ThreadSpecificData *tsdPtr,
+ XEvent *eventPtr);
+static int InvokeMouseHandlers(TkWindow *winPtr,
+ unsigned long mask, XEvent *eventPtr);
+static Window ParentXId(Display *display, Window w);
+static int RefreshKeyboardMappingIfNeeded(XEvent *eventPtr);
+static int TkXErrorHandler(ClientData clientData,
+ XErrorEvent *errEventPtr);
+static void UpdateButtonEventState(XEvent *eventPtr);
+static int WindowEventProc(Tcl_Event *evPtr, int flags);
#ifdef TK_USE_INPUT_METHODS
-static int InvokeInputMethods _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *eventPtr));
+static int InvokeInputMethods(TkWindow *winPtr, XEvent *eventPtr);
#if TK_XIM_SPOT
-static void CreateXIMSpotMethods _ANSI_ARGS_((TkWindow *winPtr));
-#endif
-
+static void CreateXIMSpotMethods(TkWindow *winPtr);
+#endif /* TK_XIM_SPOT */
#endif /* TK_USE_INPUT_METHODS */
-
-static int InvokeMouseHandlers _ANSI_ARGS_((TkWindow *winPtr,
- unsigned long mask, XEvent *eventPtr));
-
-static int InvokeFocusHandlers _ANSI_ARGS_((TkWindow **winPtrPtr,
- unsigned long mask, XEvent *eventPtr));
-
/*
*----------------------------------------------------------------------
*
* InvokeFocusHandlers --
- *
- * Call focus-related code to look at FocusIn, FocusOut, Enter,
- * and Leave events; depending on its return * value, ignore the
- * event.
- *
- * Results:
- * 0 further processing can be done on the event.
- * 1 we are done with the event passed.
- *
+ *
+ * Call focus-related code to look at FocusIn, FocusOut, Enter, and Leave
+ * events; depending on its return value, ignore the event.
+ *
+ * Results:
+ * 0 further processing can be done on the event.
+ * 1 we are done with the event passed.
+ *
* Side effects:
- * The *winPtrPtr in the caller may be changed to the TkWindow
- * for the window with focus.
+ * The *winPtrPtr in the caller may be changed to the TkWindow for the
+ * window with focus.
*
*----------------------------------------------------------------------
*/
static int
-InvokeFocusHandlers(winPtrPtr, mask, eventPtr)
- TkWindow **winPtrPtr;
- unsigned long mask;
- XEvent *eventPtr;
+InvokeFocusHandlers(
+ TkWindow **winPtrPtr,
+ unsigned long mask,
+ XEvent *eventPtr)
{
if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask))
&& (TkFocusFilterEvent(*winPtrPtr, eventPtr) == 0)) {
return 1;
}
+ /*
+ * MouseWheel events are not focus specific on Mac OS X.
+ */
+
#ifdef MAC_OSX_TK
- /* MouseWheel events are not focus specific on Mac OS X */
- if (mask & (KeyPressMask|KeyReleaseMask)) {
+#define FOCUS_DIRECTED_EVENT_MASK (KeyPressMask|KeyReleaseMask)
#else
- if (mask & (KeyPressMask|KeyReleaseMask|MouseWheelMask)) {
+#define FOCUS_DIRECTED_EVENT_MASK (KeyPressMask|KeyReleaseMask|MouseWheelMask)
#endif
+
+ if (mask & FOCUS_DIRECTED_EVENT_MASK) {
(*winPtrPtr)->dispPtr->lastEventTime = eventPtr->xkey.time;
*winPtrPtr = TkFocusKeyEvent(*winPtrPtr, eventPtr);
if (*winPtrPtr == NULL) {
- return 1;
+ return 1;
}
}
@@ -286,30 +273,30 @@ InvokeFocusHandlers(winPtrPtr, mask, eventPtr)
*
* InvokeMouseHandlers --
*
- * Call a grab-related procedure to do special processing on
- * pointer events.
+ * Call a grab-related function to do special processing on pointer
+ * events.
+ *
+ * Results:
+ * 0 further processing can be done on the event.
+ * 1 we are done with the event passed.
*
- * Results:
- * 0 further processing can be done on the event.
- * 1 we are done with the event passed.
- *
* Side effects:
- * New events may be queued from TkPointerEvent and grabs may be
- * added/removed. The eventPtr may be changed by TkPointerEvent
- * in some cases.
+ * New events may be queued from TkPointerEvent and grabs may be added
+ * and/or removed. The eventPtr may be changed by TkPointerEvent in some
+ * cases.
*
*----------------------------------------------------------------------
*/
static int
-InvokeMouseHandlers(winPtr, mask, eventPtr)
- TkWindow *winPtr;
- unsigned long mask;
- XEvent *eventPtr;
+InvokeMouseHandlers(
+ TkWindow *winPtr,
+ unsigned long mask,
+ XEvent *eventPtr)
{
if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask
|EnterWindowMask|LeaveWindowMask)) {
-
+
if (mask & (ButtonPressMask|ButtonReleaseMask)) {
winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time;
} else if (mask & PointerMotionMask) {
@@ -317,15 +304,17 @@ InvokeMouseHandlers(winPtr, mask, eventPtr)
} else {
winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time;
}
-
+
if (TkPointerEvent(eventPtr, winPtr) == 0) {
- /*
- * The event should be ignored to make grab work
- * correctly (as the comment for TkPointerEvent states).
+ /*
+ * The event should be ignored to make grab work correctly (as the
+ * comment for TkPointerEvent states).
*/
+
return 1;
}
- }
+ }
+
return 0;
}
@@ -334,37 +323,38 @@ InvokeMouseHandlers(winPtr, mask, eventPtr)
*
* CreateXIMSpotMethods --
*
- * Create the X input methods for our winPtr. XIM is only ever
- * enabled on Unix.
+ * Create the X input methods for our winPtr. XIM is only ever enabled on
+ * Unix.
+ *
+ * Results:
+ * None.
*
- * Results:
- * None.
- *
* Side effects:
- * An input context is created or we Tcl_Panic.
+ * An input context is created or we Tcl_Panic.
*
*----------------------------------------------------------------------
*/
#if defined(TK_USE_INPUT_METHODS) && TK_XIM_SPOT
static void
-CreateXIMSpotMethods(winPtr)
- TkWindow *winPtr;
+CreateXIMSpotMethods(
+ TkWindow *winPtr)
{
TkDisplay *dispPtr = winPtr->dispPtr;
if (dispPtr->flags & TK_DISPLAY_XIM_SPOT) {
XVaNestedList preedit_attr;
XPoint spot = {0, 0};
-
+
if (dispPtr->inputXfs == NULL) {
/*
* We only need to create one XFontSet
*/
- char **missing_list;
- int missing_count;
- char *def_string;
-
+
+ char **missing_list;
+ int missing_count;
+ char *def_string;
+
dispPtr->inputXfs = XCreateFontSet(dispPtr->display,
"-*-*-*-R-Normal--14-130-75-75-*-*",
&missing_list, &missing_count, &def_string);
@@ -372,7 +362,7 @@ CreateXIMSpotMethods(winPtr)
XFreeStringList(missing_list);
}
}
-
+
preedit_attr = XVaCreateNestedList(0, XNSpotLocation,
&spot, XNFontSet, dispPtr->inputXfs, NULL);
if (winPtr->inputContext != NULL) {
@@ -402,31 +392,31 @@ CreateXIMSpotMethods(winPtr)
*----------------------------------------------------------------------
*
* InvokeInputMethods --
- * Pass the event to the input method(s), if there are any, and
- * discard the event if the input method(s) * insist. Create the
- * input context for the window if * it hasn't already been done
- * (XFilterEvent needs this * context).
- *
- * When the event is a FocusIn event, set the input context focus
- * to the receiving window. This is needed for certain * versions
- * of Solaris, but we are still not sure whether it * is being
- * done in the right way.
- *
- * Results:
- * 1 when we are done with the event.
- * 0 when the event can be processed further.
- *
+ *
+ * Pass the event to the input method(s), if there are any, and discard
+ * the event if the input method(s) insist. Create the input context for
+ * the window if it hasn't already been done (XFilterEvent needs this
+ * context).
+ *
+ * When the event is a FocusIn event, set the input context focus to the
+ * receiving window. This is needed for certain versions of Solaris, but
+ * we are still not sure whether it is being done in the right way.
+ *
+ * Results:
+ * 1 when we are done with the event.
+ * 0 when the event can be processed further.
+ *
* Side effects:
- * Input contexts/methods may be created.
+ * Input contexts/methods may be created.
*
*----------------------------------------------------------------------
*/
#ifdef TK_USE_INPUT_METHODS
static int
-InvokeInputMethods(winPtr,eventPtr)
- TkWindow *winPtr;
- XEvent *eventPtr;
+InvokeInputMethods(
+ TkWindow *winPtr,
+ XEvent *eventPtr)
{
TkDisplay *dispPtr = winPtr->dispPtr;
@@ -471,60 +461,60 @@ InvokeInputMethods(winPtr,eventPtr)
*----------------------------------------------------------------------
*
* GetTkWindowFromXEvent --
- *
- * Attempt to find which TkWindow is associated with an event.
- * If it fails we attempt to get the * TkWindow from the parent
- * for a property notification.
- *
- * Results:
- * The TkWindow associated with the event or NULL.
- *
+ *
+ * Attempt to find which TkWindow is associated with an event. If it
+ * fails we attempt to get the TkWindow from the parent for a property
+ * notification.
+ *
+ * Results:
+ * The TkWindow associated with the event or NULL.
+ *
* Side effects:
- * TkSelPropProc may influence selection on windows not known to
- * Tk.
+ * TkSelPropProc may influence selection on windows not known to Tk.
*
*----------------------------------------------------------------------
*/
static TkWindow *
-GetTkWindowFromXEvent(eventPtr)
- XEvent *eventPtr;
+GetTkWindowFromXEvent(
+ XEvent *eventPtr)
{
TkWindow *winPtr;
Window parentXId, handlerWindow = eventPtr->xany.window;
- if ((eventPtr->xany.type == StructureNotifyMask)
+ if ((eventPtr->xany.type == StructureNotifyMask)
&& (eventPtr->xmap.event != eventPtr->xmap.window)) {
- handlerWindow = eventPtr->xmap.event;
+ handlerWindow = eventPtr->xmap.event;
}
winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);
-
+
if (winPtr == NULL) {
/*
- * There isn't a TkWindow structure for this window.
- * However, if the event is a PropertyNotify event then call
- * the selection manager (it deals beneath-the-table with
- * certain properties). Also, if the window's parent is a
- * Tk window that has the TK_PROP_PROPCHANGE flag set, then
- * we must propagate the PropertyNotify event up to the parent.
+ * There isn't a TkWindow structure for this window. However, if the
+ * event is a PropertyNotify event then call the selection manager (it
+ * deals beneath-the-table with certain properties). Also, if the
+ * window's parent is a Tk window that has the TK_PROP_PROPCHANGE flag
+ * set, then we must propagate the PropertyNotify event up to the
+ * parent.
*/
- if (eventPtr->type != PropertyNotify) {
+
+ if (eventPtr->type != PropertyNotify) {
return NULL;
}
TkSelPropProc(eventPtr);
- parentXId = ParentXId(eventPtr->xany.display, handlerWindow);
- if (parentXId == None) {
- return NULL;
- }
+ parentXId = ParentXId(eventPtr->xany.display, handlerWindow);
+ if (parentXId == None) {
+ return NULL;
+ }
winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, parentXId);
if (winPtr == NULL) {
- return NULL;
- }
+ return NULL;
+ }
if (!(winPtr->flags & TK_PROP_PROPCHANGE)) {
- return NULL;
- }
- }
+ return NULL;
+ }
+ }
return winPtr;
}
@@ -532,32 +522,32 @@ GetTkWindowFromXEvent(eventPtr)
*----------------------------------------------------------------------
*
* GetEventMaskFromXEvent --
- *
- * The event type is looked up in our eventMasks table, and may
- * be changed to a different mask * depending on the state of the
- * event and window * members.
- *
- * Results:
- * The mask for the event.
- *
+ *
+ * The event type is looked up in our eventMasks table, and may be
+ * changed to a different mask depending on the state of the event and
+ * window members.
+ *
+ * Results:
+ * The mask for the event.
+ *
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
static unsigned long
-GetEventMaskFromXEvent(eventPtr)
- XEvent *eventPtr;
+GetEventMaskFromXEvent(
+ XEvent *eventPtr)
{
unsigned long mask = eventMasks[eventPtr->xany.type];
/*
- * Events selected by StructureNotify require special handling.
- * They look the same as those selected by SubstructureNotify.
- * The only difference is whether the "event" and "window" fields
- * are the same. Compare the two fields and convert
- * StructureNotify to SubstructureNotify if necessary.
+ * Events selected by StructureNotify require special handling. They look
+ * the same as those selected by SubstructureNotify. The only difference
+ * is whether the "event" and "window" fields are the same. Compare the
+ * two fields and convert StructureNotify to SubstructureNotify if
+ * necessary.
*/
if (mask == StructureNotifyMask) {
@@ -572,28 +562,28 @@ GetEventMaskFromXEvent(eventPtr)
*----------------------------------------------------------------------
*
* RefreshKeyboardMappingIfNeeded --
- *
- * If the event is a MappingNotify event, find its display and
- * refresh the keyboard mapping * information for the display.
- *
- * Results:
- * 0 if the event was not a MappingNotify event
- * 1 if the event was a MappingNotify event
- *
+ *
+ * If the event is a MappingNotify event, find its display and refresh
+ * the keyboard mapping information for the display.
+ *
+ * Results:
+ * 0 if the event was not a MappingNotify event
+ * 1 if the event was a MappingNotify event
+ *
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
static int
-RefreshKeyboardMappingIfNeeded(eventPtr)
- XEvent *eventPtr;
+RefreshKeyboardMappingIfNeeded(
+ XEvent *eventPtr)
{
TkDisplay *dispPtr;
if (eventPtr->type == MappingNotify) {
- dispPtr = TkGetDisplay(eventPtr->xmapping.display);
+ dispPtr = TkGetDisplay(eventPtr->xmapping.display);
if (dispPtr != NULL) {
XRefreshKeyboardMapping(&eventPtr->xmapping);
dispPtr->bindInfoStale = 1;
@@ -607,33 +597,33 @@ RefreshKeyboardMappingIfNeeded(eventPtr)
*----------------------------------------------------------------------
*
* GetButtonMask --
- *
+ *
* Return the proper Button${n}Mask for the button.
- *
- * Results:
- * A button mask.
- *
+ *
+ * Results:
+ * A button mask.
+ *
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
static int
-GetButtonMask(button)
- unsigned int button;
+GetButtonMask(
+ unsigned int button)
{
switch (button) {
- case 1:
- return Button1Mask;
- case 2:
- return Button2Mask;
- case 3:
- return Button3Mask;
- case 4:
- return Button4Mask;
- case 5:
- return Button5Mask;
+ case 1:
+ return Button1Mask;
+ case 2:
+ return Button2Mask;
+ case 3:
+ return Button3Mask;
+ case 4:
+ return Button4Mask;
+ case 5:
+ return Button5Mask;
}
return 0;
}
@@ -642,66 +632,64 @@ GetButtonMask(button)
*----------------------------------------------------------------------
*
* UpdateButtonEventState --
- *
- * Update the button event state in our TkDisplay using the
- * XEvent passed. We also may modify the the XEvent passed to
- * fit some aspects of our TkDisplay.
- *
- * Results:
- * None.
- *
+ *
+ * Update the button event state in our TkDisplay using the XEvent
+ * passed. We also may modify the the XEvent passed to fit some aspects
+ * of our TkDisplay.
+ *
+ * Results:
+ * None.
+ *
* Side effects:
- * The TkDisplay's private button state may be modified. The
- * eventPtr's state may be updated * to reflect masks stored in
- * our TkDisplay that * the event doesn't contain. The eventPtr
- * may also * be modified to not contain a button state for the *
- * window in which it was not pressed in.
+ * The TkDisplay's private button state may be modified. The eventPtr's
+ * state may be updated to reflect masks stored in our TkDisplay that the
+ * event doesn't contain. The eventPtr may also be modified to not
+ * contain a button state for the window in which it was not pressed in.
*
*----------------------------------------------------------------------
*/
static void
-UpdateButtonEventState(eventPtr)
- XEvent *eventPtr;
+UpdateButtonEventState(
+ XEvent *eventPtr)
{
TkDisplay *dispPtr;
- int allButtonsMask = Button1Mask | Button2Mask | Button3Mask
+ int allButtonsMask = Button1Mask | Button2Mask | Button3Mask
| Button4Mask | Button5Mask;
switch (eventPtr->type) {
- case ButtonPress:
- dispPtr = TkGetDisplay(eventPtr->xbutton.display);
- dispPtr->mouseButtonWindow = eventPtr->xbutton.window;
- eventPtr->xbutton.state |= dispPtr->mouseButtonState;
-
- dispPtr->mouseButtonState |=
- GetButtonMask(eventPtr->xbutton.button);
- break;
-
- case ButtonRelease:
- dispPtr = TkGetDisplay(eventPtr->xbutton.display);
- dispPtr->mouseButtonWindow = None;
- dispPtr->mouseButtonState &=
- ~GetButtonMask(eventPtr->xbutton.button);
- eventPtr->xbutton.state |= dispPtr->mouseButtonState;
- break;
+ case ButtonPress:
+ dispPtr = TkGetDisplay(eventPtr->xbutton.display);
+ dispPtr->mouseButtonWindow = eventPtr->xbutton.window;
+ eventPtr->xbutton.state |= dispPtr->mouseButtonState;
+
+ dispPtr->mouseButtonState |= GetButtonMask(eventPtr->xbutton.button);
+ break;
+
+ case ButtonRelease:
+ dispPtr = TkGetDisplay(eventPtr->xbutton.display);
+ dispPtr->mouseButtonWindow = None;
+ dispPtr->mouseButtonState &= ~GetButtonMask(eventPtr->xbutton.button);
+ eventPtr->xbutton.state |= dispPtr->mouseButtonState;
+ break;
+
+ case MotionNotify:
+ dispPtr = TkGetDisplay(eventPtr->xmotion.display);
+ if (dispPtr->mouseButtonState & allButtonsMask) {
+ if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) {
+ /*
+ * This motion event should not be interpreted as a button
+ * press + motion event since this is not the same window the
+ * button was pressed down in.
+ */
- case MotionNotify:
- dispPtr = TkGetDisplay(eventPtr->xmotion.display);
- if (dispPtr->mouseButtonState & allButtonsMask) {
- if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) {
- /*
- * This motion event should not be interpreted as a button
- * press + motion event since this is not the same window
- * the button was pressed down in.
- */
- dispPtr->mouseButtonState &= ~allButtonsMask;
- dispPtr->mouseButtonWindow = None;
- } else {
- eventPtr->xmotion.state |= dispPtr->mouseButtonState;
- }
+ dispPtr->mouseButtonState &= ~allButtonsMask;
+ dispPtr->mouseButtonWindow = None;
+ } else {
+ eventPtr->xmotion.state |= dispPtr->mouseButtonState;
}
- break;
+ }
+ break;
}
}
@@ -709,11 +697,10 @@ UpdateButtonEventState(eventPtr)
*----------------------------------------------------------------------
*
* InvokeClientMessageHandlers --
- *
- * Iterate the list of handlers and invoke the function pointer
- * for each.
- *
- * Results:
+ *
+ * Iterate the list of handlers and invoke the function pointer for each.
+ *
+ * Results:
* None.
*
* Side effects:
@@ -723,23 +710,23 @@ UpdateButtonEventState(eventPtr)
*/
static void
-InvokeClientMessageHandlers(tsdPtr, tkwin, eventPtr)
- ThreadSpecificData *tsdPtr;
- Tk_Window tkwin;
- XEvent *eventPtr;
+InvokeClientMessageHandlers(
+ ThreadSpecificData *tsdPtr,
+ Tk_Window tkwin,
+ XEvent *eventPtr)
{
GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->cmList;
for (prevPtr = NULL; curPtr != NULL; ) {
- if (curPtr->deleteFlag) {
+ if (curPtr->deleteFlag) {
if (!tsdPtr->handlersActive) {
- /*
- * This handler needs to be deleted and there are
- * no calls pending through any handlers, so now
- * is a safe time to delete it.
+ /*
+ * This handler needs to be deleted and there are no calls
+ * pending through any handlers, so now is a safe time to
+ * delete it.
*/
-
- tmpPtr = curPtr->nextPtr;
+
+ tmpPtr = curPtr->nextPtr;
if (prevPtr == NULL) {
tsdPtr->cmList = tmpPtr;
} else {
@@ -754,6 +741,7 @@ InvokeClientMessageHandlers(tsdPtr, tkwin, eventPtr)
}
} else {
int done;
+
tsdPtr->handlersActive++;
done = (*(Tk_ClientMessageProc *)curPtr->proc)(tkwin, eventPtr);
tsdPtr->handlersActive--;
@@ -770,37 +758,37 @@ InvokeClientMessageHandlers(tsdPtr, tkwin, eventPtr)
*----------------------------------------------------------------------
*
* InvokeGenericHandlers --
- *
- * Iterate the list of handlers and invoke the function pointer
- * for each. If the handler invoked returns a non-zero value
- * then we are done.
- *
- * Results:
- * 0 when the event wasn't handled by a handler. non-zero when
- * it was processed and handled by a handler.
- *
+ *
+ * Iterate the list of handlers and invoke the function pointer for each.
+ * If the handler invoked returns a non-zero value then we are done.
+ *
+ * Results:
+ * 0 when the event wasn't handled by a handler. Non-zero when it was
+ * processed and handled by a handler.
+ *
* Side effects:
* Handlers may be deleted and events may be sent to handlers.
*
*----------------------------------------------------------------------
*/
-static int
-InvokeGenericHandlers(tsdPtr, eventPtr)
- ThreadSpecificData *tsdPtr;
- XEvent *eventPtr;
+static int
+InvokeGenericHandlers(
+ ThreadSpecificData *tsdPtr,
+ XEvent *eventPtr)
{
GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->genericList;
for (prevPtr = NULL; curPtr != NULL; ) {
- if (curPtr->deleteFlag) {
+ if (curPtr->deleteFlag) {
if (!tsdPtr->handlersActive) {
- /*
- * This handler needs to be deleted and there are no
- * calls pending through the handler, so now is a safe
- * time to delete it.
+ /*
+ * This handler needs to be deleted and there are no calls
+ * pending through the handler, so now is a safe time to
+ * delete it.
*/
- tmpPtr = curPtr->nextPtr;
+
+ tmpPtr = curPtr->nextPtr;
if (prevPtr == NULL) {
tsdPtr->genericList = tmpPtr;
} else {
@@ -815,11 +803,12 @@ InvokeGenericHandlers(tsdPtr, eventPtr)
}
} else {
int done;
+
tsdPtr->handlersActive++;
done = (*curPtr->proc)(curPtr->clientData, eventPtr);
tsdPtr->handlersActive--;
if (done) {
- return done;
+ return done;
}
}
prevPtr = curPtr;
@@ -833,41 +822,38 @@ InvokeGenericHandlers(tsdPtr, eventPtr)
*
* Tk_CreateEventHandler --
*
- * Arrange for a given procedure to be invoked whenever events
- * from a given class occur in a given window.
+ * Arrange for a given function to be invoked whenever events from a
+ * given class occur in a given window.
*
* Results:
* None.
*
* Side effects:
- * From now on, whenever an event of the type given by mask
- * occurs for token and is processed by Tk_HandleEvent, proc will
- * be called. See the manual entry for details of the calling
- * sequence and return value for proc.
+ * From now on, whenever an event of the type given by mask occurs for
+ * token and is processed by Tk_HandleEvent, proc will be called. See the
+ * manual entry for details of the calling sequence and return value for
+ * proc.
*
*----------------------------------------------------------------------
*/
void
-Tk_CreateEventHandler(token, mask, proc, clientData)
- Tk_Window token; /* Token for window in which to
- * create handler. */
- unsigned long mask; /* Events for which proc should
- * be called. */
- Tk_EventProc *proc; /* Procedure to call for each
- * selected event */
- ClientData clientData; /* Arbitrary data to pass to proc. */
+Tk_CreateEventHandler(
+ Tk_Window token, /* Token for window in which to create
+ * handler. */
+ unsigned long mask, /* Events for which proc should be called. */
+ Tk_EventProc *proc, /* Function to call for each selected event */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
{
register TkEventHandler *handlerPtr;
register TkWindow *winPtr = (TkWindow *) token;
/*
- * Skim through the list of existing handlers to (a) compute the
- * 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
- * declared with the same callback and clientData (if so, just
- * change the mask). If no existing handler matches, then create
- * a new handler.
+ * Skim through the list of existing handlers to (a) compute the 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 declared with the same
+ * callback and clientData (if so, just change the mask). If no existing
+ * handler matches, then create a new handler.
*/
if (winPtr->handlerList == NULL) {
@@ -875,11 +861,11 @@ Tk_CreateEventHandler(token, mask, proc, clientData)
* No event handlers defined at all, so must create.
*/
- handlerPtr = (TkEventHandler *) ckalloc(
- (unsigned) sizeof(TkEventHandler));
+ handlerPtr = (TkEventHandler *) ckalloc(sizeof(TkEventHandler));
winPtr->handlerList = handlerPtr;
} else {
int found = 0;
+
for (handlerPtr = winPtr->handlerList; ;
handlerPtr = handlerPtr->nextPtr) {
if ((handlerPtr->proc == proc)
@@ -893,10 +879,9 @@ Tk_CreateEventHandler(token, mask, proc, clientData)
}
/*
- * If we found anything, we're done because we do not need to
- * use XSelectInput; Tk always selects on all events anyway in
- * order to support binding on classes, 'all' and other
- * bind-tags.
+ * If we found anything, we're done because we do not need to use
+ * XSelectInput; Tk always selects on all events anyway in order to
+ * support binding on classes, 'all' and other bind-tags.
*/
if (found) {
@@ -922,9 +907,8 @@ Tk_CreateEventHandler(token, mask, proc, clientData)
handlerPtr->nextPtr = NULL;
/*
- * No need to call XSelectInput: Tk always selects on all events
- * for all windows (needed to support bindings on classes and
- * "all").
+ * No need to call XSelectInput: Tk always selects on all events for all
+ * windows (needed to support bindings on classes and "all").
*/
}
@@ -939,29 +923,29 @@ Tk_CreateEventHandler(token, mask, proc, clientData)
* None.
*
* Side effects:
- * If there existed a handler as described by the parameters, the
- * handler is deleted so that proc will not be invoked again.
+ * If there existed a handler as described by the parameters, the handler
+ * is deleted so that proc will not be invoked again.
*
*----------------------------------------------------------------------
*/
void
-Tk_DeleteEventHandler(token, mask, proc, clientData)
- Tk_Window token; /* Same as corresponding arguments passed */
- unsigned long mask; /* previously to Tk_CreateEventHandler. */
- Tk_EventProc *proc;
- ClientData clientData;
+Tk_DeleteEventHandler(
+ Tk_Window token, /* Same as corresponding arguments passed */
+ unsigned long mask, /* previously to Tk_CreateEventHandler. */
+ Tk_EventProc *proc,
+ ClientData clientData)
{
register TkEventHandler *handlerPtr;
register InProgress *ipPtr;
TkEventHandler *prevPtr;
register TkWindow *winPtr = (TkWindow *) token;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
- * Find the event handler to be deleted, or return
- * immediately if it doesn't exist.
+ * Find the event handler to be deleted, or return immediately if it
+ * doesn't exist.
*/
for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ;
@@ -976,8 +960,8 @@ Tk_DeleteEventHandler(token, mask, proc, clientData)
}
/*
- * If Tk_HandleEvent is about to process this handler, tell it to
- * process the next one instead.
+ * If Tk_HandleEvent is about to process this handler, tell it to process
+ * the next one instead.
*/
for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
@@ -997,10 +981,9 @@ Tk_DeleteEventHandler(token, mask, proc, clientData)
}
ckfree((char *) handlerPtr);
-
/*
- * No need to call XSelectInput: Tk always selects on all events
- * for all windows (needed to support bindings on classes and "all").
+ * No need to call XSelectInput: Tk always selects on all events for all
+ * windows (needed to support bindings on classes and "all").
*/
}
@@ -1008,32 +991,32 @@ Tk_DeleteEventHandler(token, mask, proc, clientData)
*
* Tk_CreateGenericHandler --
*
- * Register a procedure to be called on each X event, regardless
- * of display or window. Generic handlers are useful for capturing
- * events that aren't associated with windows, or events for windows
- * not managed by Tk.
+ * Register a function to be called on each X event, regardless of
+ * display or window. Generic handlers are useful for capturing events
+ * that aren't associated with windows, or events for windows not managed
+ * by Tk.
*
* Results:
* None.
*
* Side Effects:
- * From now on, whenever an X event is given to Tk_HandleEvent,
- * invoke proc, giving it clientData and the event as arguments.
+ * From now on, whenever an X event is given to Tk_HandleEvent, invoke
+ * proc, giving it clientData and the event as arguments.
*
*----------------------------------------------------------------------
*/
void
-Tk_CreateGenericHandler(proc, clientData)
- Tk_GenericProc *proc; /* Procedure to call on every event. */
- ClientData clientData; /* One-word value to pass to proc. */
+Tk_CreateGenericHandler(
+ Tk_GenericProc *proc, /* Function to call on every event. */
+ ClientData clientData) /* One-word value to pass to proc. */
{
GenericHandler *handlerPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
handlerPtr = (GenericHandler *) ckalloc(sizeof(GenericHandler));
-
+
handlerPtr->proc = proc;
handlerPtr->clientData = clientData;
handlerPtr->deleteFlag = 0;
@@ -1057,23 +1040,22 @@ Tk_CreateGenericHandler(proc, clientData)
* None.
*
* Side Effects:
- * If there existed a handler as described by the parameters,
- * that handler is logically deleted so that proc will not be
- * invoked again. The physical deletion happens in the event
- * loop in Tk_HandleEvent.
+ * If there existed a handler as described by the parameters, that
+ * handler is logically deleted so that proc will not be invoked again.
+ * The physical deletion happens in the event loop in Tk_HandleEvent.
*
*----------------------------------------------------------------------
*/
void
-Tk_DeleteGenericHandler(proc, clientData)
- Tk_GenericProc *proc;
- ClientData clientData;
+Tk_DeleteGenericHandler(
+ Tk_GenericProc *proc,
+ ClientData clientData)
{
GenericHandler * handler;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
+
for (handler=tsdPtr->genericList ; handler ; handler=handler->nextPtr) {
if ((handler->proc == proc) && (handler->clientData == clientData)) {
handler->deleteFlag = 1;
@@ -1085,44 +1067,45 @@ Tk_DeleteGenericHandler(proc, clientData)
*
* Tk_CreateClientMessageHandler --
*
- * Register a procedure to be called on each ClientMessage event.
+ * Register a function to be called on each ClientMessage event.
* ClientMessage handlers are useful for Drag&Drop extensions.
*
* Results:
* None.
*
* Side Effects:
- * From now on, whenever a ClientMessage event is received that isn't
- * a WM_PROTOCOL event or SelectionEvent, invoke proc, giving it
- * tkwin and the event as arguments.
+ * From now on, whenever a ClientMessage event is received that isn't a
+ * WM_PROTOCOL event or SelectionEvent, invoke proc, giving it tkwin and
+ * the event as arguments.
*
*----------------------------------------------------------------------
*/
void
-Tk_CreateClientMessageHandler(proc)
- Tk_ClientMessageProc *proc; /* Procedure to call on event. */
+Tk_CreateClientMessageHandler(
+ Tk_ClientMessageProc *proc) /* Function to call on event. */
{
GenericHandler *handlerPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
- * We use a GenericHandler struct, because it's basically the same,
- * except with an extra clientData field we'll never use.
+ * We use a GenericHandler struct, because it's basically the same, except
+ * with an extra clientData field we'll never use.
*/
+
handlerPtr = (GenericHandler *) ckalloc(sizeof(GenericHandler));
- handlerPtr->proc = (Tk_GenericProc *) proc;
- handlerPtr->clientData = NULL; /* never used */
- handlerPtr->deleteFlag = 0;
- handlerPtr->nextPtr = NULL;
+ handlerPtr->proc = (Tk_GenericProc *) proc;
+ handlerPtr->clientData = NULL; /* never used */
+ handlerPtr->deleteFlag = 0;
+ handlerPtr->nextPtr = NULL;
if (tsdPtr->cmList == NULL) {
- tsdPtr->cmList = handlerPtr;
+ tsdPtr->cmList = handlerPtr;
} else {
tsdPtr->lastCmPtr->nextPtr = handlerPtr;
}
- tsdPtr->lastCmPtr = handlerPtr;
+ tsdPtr->lastCmPtr = handlerPtr;
}
/*
@@ -1136,20 +1119,20 @@ Tk_CreateClientMessageHandler(proc)
* None.
*
* Side Effects:
- * If there existed a handler as described by the parameters,
- * that handler is logically deleted so that proc will not be
- * invoked again. The physical deletion happens in the event
- * loop in TkClientMessageEventProc.
+ * If there existed a handler as described by the parameters, that
+ * handler is logically deleted so that proc will not be invoked again.
+ * The physical deletion happens in the event loop in
+ * TkClientMessageEventProc.
*
*----------------------------------------------------------------------
*/
void
-Tk_DeleteClientMessageHandler(proc)
- Tk_ClientMessageProc *proc;
+Tk_DeleteClientMessageHandler(
+ Tk_ClientMessageProc *proc)
{
GenericHandler * handler;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
for (handler=tsdPtr->cmList ; handler!=NULL ; handler=handler->nextPtr) {
@@ -1164,10 +1147,9 @@ Tk_DeleteClientMessageHandler(proc)
*
* 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.
+ * This functions initializes all the event module structures used by the
+ * current thread. It must be called before any other function in this
+ * file is called.
*
* Results:
* None.
@@ -1179,10 +1161,10 @@ Tk_DeleteClientMessageHandler(proc)
*/
void
-TkEventInit _ANSI_ARGS_((void))
+TkEventInit(void)
{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
tsdPtr->handlersActive = 0;
tsdPtr->pendingPtr = NULL;
@@ -1200,12 +1182,10 @@ TkEventInit _ANSI_ARGS_((void))
* TkXErrorHandler --
*
* TkXErrorHandler is an error handler, to be installed via
- * Tk_CreateErrorHandler, that will set a flag if an X error
- * occurred.
+ * Tk_CreateErrorHandler, that will set a flag if an X error occurred.
*
* Results:
- * Always returns 0, indicating that the X error was
- * handled.
+ * Always returns 0, indicating that the X error was handled.
*
* Side effects:
* None.
@@ -1214,9 +1194,9 @@ TkEventInit _ANSI_ARGS_((void))
*/
static int
-TkXErrorHandler(clientData, errEventPtr)
- ClientData clientData; /* Pointer to flag we set */
- XErrorEvent *errEventPtr; /* X error info */
+TkXErrorHandler(
+ ClientData clientData, /* Pointer to flag we set. */
+ XErrorEvent *errEventPtr) /* X error info. */
{
int *error;
@@ -1230,8 +1210,8 @@ TkXErrorHandler(clientData, errEventPtr)
*
* ParentXId --
*
- * Returns the parent of the given window, or "None"
- * if the window doesn't exist.
+ * Returns the parent of the given window, or "None" if the window
+ * doesn't exist.
*
* Results:
* Returns an X window ID.
@@ -1243,9 +1223,9 @@ TkXErrorHandler(clientData, errEventPtr)
*/
static Window
-ParentXId(display, w)
- Display *display;
- Window w;
+ParentXId(
+ Display *display,
+ Window w)
{
Tk_ErrorHandler handler;
int gotXError;
@@ -1255,17 +1235,23 @@ ParentXId(display, w)
Window *childList;
unsigned int nChildren;
- /* Handle errors ourselves. */
+ /*
+ * Handle errors ourselves.
+ */
gotXError = 0;
handler = Tk_CreateErrorHandler(display, -1, -1, -1,
TkXErrorHandler, (ClientData) (&gotXError));
- /* Get the parent window. */
+ /*
+ * Get the parent window.
+ */
status = XQueryTree(display, w, &root, &parent, &childList, &nChildren);
- /* Do some cleanup; gotta return "None" if we got an error. */
+ /*
+ * Do some cleanup; gotta return "None" if we got an error.
+ */
Tk_DeleteErrorHandler(handler);
XSync(display, False);
@@ -1273,7 +1259,7 @@ ParentXId(display, w)
XFree(childList);
}
if (status == 0) {
- parent = None;
+ parent = None;
}
return parent;
@@ -1284,8 +1270,8 @@ ParentXId(display, w)
*
* Tk_HandleEvent --
*
- * Given an event, invoke all the handlers that have been
- * registered for the event.
+ * Given an event, invoke all the handlers that have been registered for
+ * the event.
*
* Results:
* None.
@@ -1297,33 +1283,32 @@ ParentXId(display, w)
*/
void
-Tk_HandleEvent(eventPtr)
- XEvent *eventPtr; /* Event to dispatch. */
+Tk_HandleEvent(
+ XEvent *eventPtr) /* Event to dispatch. */
{
register TkEventHandler *handlerPtr;
TkWindow *winPtr;
unsigned long mask;
InProgress ip;
Tcl_Interp *interp = (Tcl_Interp *) NULL;
-
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- UpdateButtonEventState (eventPtr);
+ UpdateButtonEventState(eventPtr);
- /*
- * If the generic handler processed this event we are done
- * and can return.
+ /*
+ * If the generic handler processed this event we are done and can return.
*/
+
if (InvokeGenericHandlers(tsdPtr, eventPtr)) {
goto releaseUserData;
}
-
- if (RefreshKeyboardMappingIfNeeded (eventPtr)) {
+
+ if (RefreshKeyboardMappingIfNeeded(eventPtr)) {
/*
* We are done with a MappingNotify event.
*/
+
goto releaseUserData;
}
@@ -1336,11 +1321,11 @@ Tk_HandleEvent(eventPtr)
/*
* Once a window has started getting deleted, don't process any more
- * events for it except for the DestroyNotify event. This check is
- * needed because a DestroyNotify handler could re-invoke the event
- * loop, causing other pending events to be handled for the window
- * (the window doesn't get totally expunged from our tables until
- * after the DestroyNotify event has been completely handled).
+ * events for it except for the DestroyNotify event. This check is needed
+ * because a DestroyNotify handler could re-invoke the event loop, causing
+ * other pending events to be handled for the window (the window doesn't
+ * get totally expunged from our tables until after the DestroyNotify
+ * event has been completely handled).
*/
if ((winPtr->flags & TK_ALREADY_DEAD)
@@ -1354,14 +1339,15 @@ Tk_HandleEvent(eventPtr)
interp = winPtr->mainPtr->interp;
/*
- * Protect interpreter for this window from possible deletion
- * while we are dealing with the event for this window. Thus,
- * widget writers do not have to worry about protecting the
- * interpreter in their own code.
+ * Protect interpreter for this window from possible deletion while we
+ * are dealing with the event for this window. Thus, widget writers do
+ * not have to worry about protecting the interpreter in their own
+ * code.
*/
+
Tcl_Preserve((ClientData) interp);
- result = ((InvokeFocusHandlers(&winPtr, mask, eventPtr))
+ result = ((InvokeFocusHandlers(&winPtr, mask, eventPtr))
|| (InvokeMouseHandlers(winPtr, mask, eventPtr)));
if (result) {
@@ -1374,9 +1360,10 @@ Tk_HandleEvent(eventPtr)
goto releaseInterpreter;
}
#endif
+
/*
- * For events where it hasn't already been done, update the current
- * time in the display.
+ * For events where it hasn't already been done, update the current time
+ * in the display.
*/
if (eventPtr->type == PropertyNotify) {
@@ -1384,8 +1371,8 @@ Tk_HandleEvent(eventPtr)
}
/*
- * There's a potential interaction here with Tk_DeleteEventHandler.
- * Read the documentation for pendingPtr.
+ * There's a potential interaction here with Tk_DeleteEventHandler. Read
+ * the documentation for pendingPtr.
*/
ip.eventPtr = eventPtr;
@@ -1403,7 +1390,8 @@ Tk_HandleEvent(eventPtr)
Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS")) {
TkWmProtocolEventProc(winPtr, eventPtr);
} else {
- InvokeClientMessageHandlers(tsdPtr, (Tk_Window)winPtr, eventPtr);
+ InvokeClientMessageHandlers(tsdPtr, (Tk_Window)winPtr,
+ eventPtr);
}
}
} else {
@@ -1418,15 +1406,15 @@ Tk_HandleEvent(eventPtr)
}
/*
- * Pass the event to the "bind" command mechanism. But, don't
- * do this for SubstructureNotify events. The "bind" command
- * doesn't support them anyway, and it's easier to filter out
- * these events here than in the lower-level procedures.
+ * Pass the event to the "bind" command mechanism. But, don't do this
+ * for SubstructureNotify events. The "bind" command doesn't support
+ * them anyway, and it's easier to filter out these events here than
+ * in the lower-level functions.
*/
/*
- * ...well, except when we use the tkwm patches, in which case
- * we DO handle CreateNotify events, so we gotta pass 'em through.
+ * ...well, except when we use the tkwm patches, in which case we DO
+ * handle CreateNotify events, so we gotta pass 'em through.
*/
if ((ip.winPtr != None)
@@ -1441,20 +1429,20 @@ Tk_HandleEvent(eventPtr)
* Release the interpreter for this window so that it can be potentially
* deleted if requested.
*/
-
-releaseInterpreter:
+
+ releaseInterpreter:
if (interp != (Tcl_Interp *) NULL) {
Tcl_Release((ClientData) interp);
}
/*
- * Release the user_data from the event (if it is a virtual event
- * and the field was non-NULL in the first place.) Note that this
- * is done using a Tcl_Obj interface, and we set the field back to
- * NULL afterwards out of paranoia.
+ * Release the user_data from the event (if it is a virtual event and the
+ * field was non-NULL in the first place.) Note that this is done using a
+ * Tcl_Obj interface, and we set the field back to NULL afterwards out of
+ * paranoia.
*/
-releaseUserData:
+ releaseUserData:
if (eventPtr->type == VirtualEvent) {
XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr;
@@ -1470,9 +1458,8 @@ releaseUserData:
*
* TkEventDeadWindow --
*
- * This procedure is invoked when it is determined that
- * a window is dead. It cleans up event-related information
- * about the window.
+ * This function is invoked when it is determined that a window is dead.
+ * It cleans up event-related information about the window.
*
* Results:
* None.
@@ -1484,27 +1471,26 @@ releaseUserData:
*/
void
-TkEventDeadWindow(winPtr)
- TkWindow *winPtr; /* Information about the window
- * that is being deleted. */
+TkEventDeadWindow(
+ TkWindow *winPtr) /* Information about the window that is being
+ * deleted. */
{
register TkEventHandler *handlerPtr;
register InProgress *ipPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
- * While deleting all the handlers, be careful to check for
- * Tk_HandleEvent being about to process one of the deleted
- * handlers. If it is, tell it to quit (all of the handlers
- * are being deleted).
+ * While deleting all the handlers, be careful to check for Tk_HandleEvent
+ * being about to process one of the deleted handlers. If it is, tell it
+ * to quit (all of the handlers are being deleted).
*/
while (winPtr->handlerList != NULL) {
handlerPtr = winPtr->handlerList;
winPtr->handlerList = handlerPtr->nextPtr;
- for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
- ipPtr = ipPtr->nextPtr) {
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
if (ipPtr->nextHandler == handlerPtr) {
ipPtr->nextHandler = NULL;
}
@@ -1521,15 +1507,13 @@ TkEventDeadWindow(winPtr)
*
* TkCurrentTime --
*
- * Try to deduce the current time. "Current time" means the time
- * of the event that led to the current code being executed, which
- * means the time in the most recently-nested invocation of
- * Tk_HandleEvent.
+ * Try to deduce the current time. "Current time" means the time of the
+ * event that led to the current code being executed, which means the
+ * time in the most recently-nested invocation of Tk_HandleEvent.
*
* Results:
- * The return value is the time from the current event, or
- * CurrentTime if there is no current event or if the current
- * event contains no time.
+ * The return value is the time from the current event, or CurrentTime if
+ * there is no current event or if the current event contains no time.
*
* Side effects:
* None.
@@ -1538,31 +1522,31 @@ TkEventDeadWindow(winPtr)
*/
Time
-TkCurrentTime(dispPtr)
- TkDisplay *dispPtr; /* Display for which the time is desired. */
+TkCurrentTime(
+ TkDisplay *dispPtr) /* Display for which the time is desired. */
{
register XEvent *eventPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (tsdPtr->pendingPtr == NULL) {
return dispPtr->lastEventTime;
}
eventPtr = tsdPtr->pendingPtr->eventPtr;
switch (eventPtr->type) {
- case ButtonPress:
- case ButtonRelease:
- return eventPtr->xbutton.time;
- case KeyPress:
- case KeyRelease:
- return eventPtr->xkey.time;
- case MotionNotify:
- return eventPtr->xmotion.time;
- case EnterNotify:
- case LeaveNotify:
- return eventPtr->xcrossing.time;
- case PropertyNotify:
- return eventPtr->xproperty.time;
+ case ButtonPress:
+ case ButtonRelease:
+ return eventPtr->xbutton.time;
+ case KeyPress:
+ case KeyRelease:
+ return eventPtr->xkey.time;
+ case MotionNotify:
+ return eventPtr->xmotion.time;
+ case EnterNotify:
+ case LeaveNotify:
+ return eventPtr->xcrossing.time;
+ case PropertyNotify:
+ return eventPtr->xproperty.time;
}
return dispPtr->lastEventTime;
}
@@ -1572,15 +1556,14 @@ TkCurrentTime(dispPtr)
*
* Tk_RestrictEvents --
*
- * This procedure is used to globally restrict the set of events
- * that will be dispatched. The restriction is done by filtering
- * all incoming X events through a procedure that determines
- * whether they are to be processed immediately, deferred, or
- * discarded.
+ * This function is used to globally restrict the set of events that will
+ * be dispatched. The restriction is done by filtering all incoming X
+ * events through a function that determines whether they are to be
+ * processed immediately, deferred, or discarded.
*
* Results:
- * The return value is the previous restriction procedure in effect,
- * if there was one, or NULL if there wasn't.
+ * The return value is the previous restriction function in effect, if
+ * there was one, or NULL if there wasn't.
*
* Side effects:
* From now on, proc will be called to determine whether to process,
@@ -1590,16 +1573,15 @@ TkCurrentTime(dispPtr)
*/
Tk_RestrictProc *
-Tk_RestrictEvents(proc, arg, prevArgPtr)
- Tk_RestrictProc *proc; /* Procedure to call for each incoming
- * event. */
- ClientData arg; /* Arbitrary argument to pass to proc. */
- ClientData *prevArgPtr; /* Place to store information about previous
+Tk_RestrictEvents(
+ Tk_RestrictProc *proc, /* Function to call for each incoming event */
+ ClientData arg, /* Arbitrary argument to pass to proc. */
+ ClientData *prevArgPtr) /* Place to store information about previous
* argument. */
{
Tk_RestrictProc *prev;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
prev = tsdPtr->restrictProc;
*prevArgPtr = tsdPtr->restrictArg;
@@ -1613,7 +1595,7 @@ Tk_RestrictEvents(proc, arg, prevArgPtr)
*
* Tk_CollapseMotionEvents --
*
- * This procedure controls whether we collapse motion events in a
+ * This function controls whether we collapse motion events in a
* particular display or not.
*
* Results:
@@ -1626,10 +1608,10 @@ Tk_RestrictEvents(proc, arg, prevArgPtr)
*/
int
-Tk_CollapseMotionEvents(display, collapse)
- Display *display; /* Display handling these events. */
- int collapse; /* boolean value that specifies whether
- * motion events should be collapsed. */
+Tk_CollapseMotionEvents(
+ Display *display, /* Display handling these events. */
+ int collapse) /* Boolean value that specifies whether motion
+ * events should be collapsed. */
{
TkDisplay *dispPtr = (TkDisplay *) display;
int prev = (dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS);
@@ -1647,28 +1629,26 @@ Tk_CollapseMotionEvents(display, collapse)
*
* Tk_QueueWindowEvent --
*
- * Given an X-style window event, this procedure adds it to the
- * Tcl event queue at the given position. This procedure also
- * performs mouse motion event collapsing if possible.
+ * Given an X-style window event, this function adds it to the Tcl event
+ * queue at the given position. This function also performs mouse motion
+ * event collapsing if possible.
*
* Results:
* None.
*
* Side effects:
- * Adds stuff to the event queue, which will eventually be
- * processed.
+ * Adds stuff to the event queue, which will eventually be processed.
*
*----------------------------------------------------------------------
*/
void
-Tk_QueueWindowEvent(eventPtr, position)
- XEvent *eventPtr; /* Event to add to queue. This
- * procedures copies it before adding
- * it to the queue. */
- Tcl_QueuePosition position; /* Where to put it on the queue:
- * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD,
- * or TCL_QUEUE_MARK. */
+Tk_QueueWindowEvent(
+ XEvent *eventPtr, /* Event to add to queue. This function copies
+ * it before adding it to the queue. */
+ Tcl_QueuePosition position) /* Where to put it on the queue:
+ * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, or
+ * TCL_QUEUE_MARK. */
{
TkWindowEvent *wevPtr;
TkDisplay *dispPtr;
@@ -1687,10 +1667,11 @@ Tk_QueueWindowEvent(eventPtr, position)
}
/*
- * Don't filter motion events if the user
- * defaulting to true (1), which could be set to false (0) when the
- * user wishes to receive all the motion data)
+ * Don't filter motion events if the user defaulting to true (1), which
+ * could be set to false (0) when the user wishes to receive all the
+ * motion data)
*/
+
if (!(dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS)) {
wevPtr = (TkWindowEvent *) ckalloc(sizeof(TkWindowEvent));
wevPtr->header.proc = WindowEventProc;
@@ -1703,9 +1684,8 @@ Tk_QueueWindowEvent(eventPtr, position)
if ((eventPtr->type == MotionNotify) && (eventPtr->xmotion.window
== dispPtr->delayedMotionPtr->event.xmotion.window)) {
/*
- * The new event is a motion event in the same window as the
- * saved motion event. Just replace the saved event with the
- * new one.
+ * The new event is a motion event in the same window as the saved
+ * motion event. Just replace the saved event with the new one.
*/
dispPtr->delayedMotionPtr->event = *eventPtr;
@@ -1714,7 +1694,7 @@ Tk_QueueWindowEvent(eventPtr, position)
&& (eventPtr->type != NoExpose)
&& (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 new event.
*/
@@ -1730,9 +1710,9 @@ Tk_QueueWindowEvent(eventPtr, position)
wevPtr->event = *eventPtr;
if ((eventPtr->type == MotionNotify) && (position == TCL_QUEUE_TAIL)) {
/*
- * 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
- * be collapsed with.
+ * 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 be
+ * collapsed with.
*/
if (dispPtr->delayedMotionPtr != NULL) {
@@ -1750,8 +1730,8 @@ Tk_QueueWindowEvent(eventPtr, position)
*
* TkQueueEventForAllChildren --
*
- * Given an XEvent, recursively queue the event for this window and
- * all non-toplevel children of the given window.
+ * Given an XEvent, recursively queue the event for this window and all
+ * non-toplevel children of the given window.
*
* Results:
* None.
@@ -1763,19 +1743,19 @@ Tk_QueueWindowEvent(eventPtr, position)
*/
void
-TkQueueEventForAllChildren(winPtr, eventPtr)
- TkWindow *winPtr; /* Window to which event is sent. */
- XEvent *eventPtr; /* The event to be sent. */
+TkQueueEventForAllChildren(
+ TkWindow *winPtr, /* Window to which event is sent. */
+ XEvent *eventPtr) /* The event to be sent. */
{
TkWindow *childPtr;
if (!Tk_IsMapped(winPtr)) {
- return;
+ return;
}
eventPtr->xany.window = winPtr->window;
Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
-
+
childPtr = winPtr->childList;
while (childPtr != NULL) {
if (!Tk_TopWinHierarchy(childPtr)) {
@@ -1790,16 +1770,16 @@ TkQueueEventForAllChildren(winPtr, eventPtr)
*
* WindowEventProc --
*
- * This procedure is called by Tcl_DoOneEvent when a window event
- * reaches the front of the event queue. This procedure is responsible
- * for actually handling the event.
+ * This function is called by Tcl_DoOneEvent when a window event reaches
+ * the front of the event queue. This function is responsible for
+ * actually handling the event.
*
* Results:
- * Returns 1 if the event was handled, meaning it should be removed
- * 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
- * TCL_WINDOW_EVENTS bit isn't set in flags, if a restrict proc
- * prevents the event from being handled.
+ * Returns 1 if the event was handled, meaning it should be removed 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 TCL_WINDOW_EVENTS
+ * bit isn't set in flags, if a restrict proc prevents the event from
+ * being handled.
*
* Side effects:
* Whatever the event handlers for the event do.
@@ -1808,15 +1788,15 @@ TkQueueEventForAllChildren(winPtr, eventPtr)
*/
static int
-WindowEventProc(evPtr, flags)
- Tcl_Event *evPtr; /* Event to service. */
- int flags; /* Flags that indicate what events to
- * handle, such as TCL_WINDOW_EVENTS. */
+WindowEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to handle,
+ * such as TCL_WINDOW_EVENTS. */
{
TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;
Tk_RestrictAction result;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (!(flags & TCL_WINDOW_EVENTS)) {
return 0;
@@ -1831,6 +1811,7 @@ WindowEventProc(evPtr, flags)
* TK_DELETE_EVENT: return and say we processed the event,
* even though we didn't do anything at all.
*/
+
return 1;
}
}
@@ -1844,23 +1825,23 @@ WindowEventProc(evPtr, flags)
*
* DelayedMotionProc --
*
- * This procedure is invoked as an idle handler when a mouse motion
- * event has been delayed. It queues the delayed event so that it
- * will finally be serviced.
+ * This function is invoked as an idle handler when a mouse motion event
+ * has been delayed. It queues the delayed event so that it will finally
+ * be serviced.
*
* Results:
* None.
*
* Side effects:
- * The delayed mouse motion event gets added to the Tcl event
- * queue for servicing.
+ * The delayed mouse motion event gets added to the Tcl event queue for
+ * servicing.
*
*----------------------------------------------------------------------
*/
static void
-DelayedMotionProc(clientData)
- ClientData clientData; /* Pointer to display containing a delayed
+DelayedMotionProc(
+ ClientData clientData) /* Pointer to display containing a delayed
* motion event to be serviced. */
{
TkDisplay *dispPtr = (TkDisplay *) clientData;
@@ -1889,9 +1870,9 @@ DelayedMotionProc(clientData)
*/
void
-TkCreateExitHandler (proc, clientData)
- Tcl_ExitProc *proc; /* Procedure to invoke. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+TkCreateExitHandler(
+ Tcl_ExitProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
ExitHandler *exitPtr;
@@ -1899,7 +1880,7 @@ TkCreateExitHandler (proc, clientData)
exitPtr->proc = proc;
exitPtr->clientData = clientData;
Tcl_MutexLock(&exitMutex);
- if (firstExitPtr == NULL) {
+ if (firstExitPtr == NULL && !TclInExit()) {
Tcl_CreateExitHandler(TkFinalize, NULL);
}
exitPtr->nextPtr = firstExitPtr;
@@ -1924,9 +1905,9 @@ TkCreateExitHandler (proc, clientData)
*/
void
-TkDeleteExitHandler (proc, clientData)
- Tcl_ExitProc *proc; /* Procedure that was previously registered. */
- ClientData clientData; /* Arbitrary value to pass to proc. */
+TkDeleteExitHandler(
+ Tcl_ExitProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
ExitHandler *exitPtr, *prevPtr;
@@ -1951,13 +1932,89 @@ TkDeleteExitHandler (proc, clientData)
/*
*----------------------------------------------------------------------
*
+ * TkCreateThreadExitHandler --
+ *
+ * Same as Tcl_CreateThreadExitHandler, but private to Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Proc will be invoked with clientData as argument when the application
+ * exits.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkCreateThreadExitHandler(
+ Tcl_ExitProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ exitPtr = (ExitHandler *) ckalloc(sizeof(ExitHandler));
+ exitPtr->proc = proc;
+ exitPtr->clientData = clientData;
+ if (tsdPtr->firstExitPtr == NULL && !TclInExit()) {
+ Tcl_CreateThreadExitHandler(TkFinalizeThread, NULL);
+ }
+ exitPtr->nextPtr = tsdPtr->firstExitPtr;
+ tsdPtr->firstExitPtr = exitPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDeleteThreadExitHandler --
+ *
+ * Same as Tcl_DeleteThreadExitHandler, but private to Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there is an exit handler corresponding to proc and clientData then
+ * it is cancelled; if no such handler exists then nothing happens.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDeleteThreadExitHandler(
+ Tcl_ExitProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr, *prevPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (prevPtr = NULL, exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;
+ prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) {
+ if ((exitPtr->proc == proc)
+ && (exitPtr->clientData == clientData)) {
+ if (prevPtr == NULL) {
+ tsdPtr->firstExitPtr = exitPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = exitPtr->nextPtr;
+ }
+ ckfree((char *) exitPtr);
+ return;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkFinalize --
*
* Runs our private exit handlers and removes itself from Tcl. This is
- * benificial should we want to protect from dangling pointers should
- * the Tk shared library be unloaded prior to Tcl which can happen on
- * windows should the process be forcefully exiting from an exception
- * handler.
+ * benificial should we want to protect from dangling pointers should the
+ * Tk shared library be unloaded prior to Tcl which can happen on windows
+ * should the process be forcefully exiting from an exception handler.
*
* Results:
* None.
@@ -1969,8 +2026,8 @@ TkDeleteExitHandler (proc, clientData)
*/
void
-TkFinalize (clientData)
- ClientData clientData; /* Arbitrary value to pass to proc. */
+TkFinalize(
+ ClientData clientData) /* Arbitrary value to pass to proc. */
{
ExitHandler *exitPtr;
@@ -1979,10 +2036,9 @@ TkFinalize (clientData)
Tcl_MutexLock(&exitMutex);
for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) {
/*
- * Be careful to remove the handler from the list before
- * invoking its callback. This protects us against
- * double-freeing if the callback should call
- * TkDeleteExitHandler on itself.
+ * Be careful to remove the handler from the list before invoking its
+ * callback. This protects us against double-freeing if the callback
+ * should call TkDeleteExitHandler on itself.
*/
firstExitPtr = exitPtr->nextPtr;
@@ -1990,7 +2046,7 @@ TkFinalize (clientData)
(*exitPtr->proc)(exitPtr->clientData);
ckfree((char *) exitPtr);
Tcl_MutexLock(&exitMutex);
- }
+ }
firstExitPtr = NULL;
Tcl_MutexUnlock(&exitMutex);
}
@@ -1998,24 +2054,80 @@ TkFinalize (clientData)
/*
*----------------------------------------------------------------------
*
+ * TkFinalizeThread --
+ *
+ * Runs our private thread exit handlers and removes itself from Tcl.
+ * This is benificial should we want to protect from dangling pointers
+ * should the Tk shared library be unloaded prior to Tcl which can happen
+ * on Windows should the process be forcefully exiting from an exception
+ * handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects.
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFinalizeThread(
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ Tcl_DeleteThreadExitHandler(TkFinalizeThread, NULL);
+
+ if (tsdPtr != NULL) {
+ tsdPtr->inExit = 1;
+
+ for (exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL;
+ exitPtr = tsdPtr->firstExitPtr) {
+ /*
+ * Be careful to remove the handler from the list before invoking
+ * its callback. This protects us against double-freeing if the
+ * callback should call TkDeleteThreadExitHandler on itself.
+ */
+
+ tsdPtr->firstExitPtr = exitPtr->nextPtr;
+ (*exitPtr->proc)(exitPtr->clientData);
+ ckfree((char *) exitPtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_MainLoop --
*
- * Call Tcl_DoOneEvent over and over again in an infinite loop as
- * long as there exist any main windows.
+ * Call Tcl_DoOneEvent over and over again in an infinite loop as long as
+ * there exist any main windows.
*
* Results:
* None.
*
* Side effects:
- * Arbitrary; depends on handlers for events.
+ * Arbitrary; depends on handlers for events.
*
*----------------------------------------------------------------------
*/
void
-Tk_MainLoop()
+Tk_MainLoop(void)
{
while (Tk_GetNumMainWindows() > 0) {
Tcl_DoOneEvent(0);
}
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */