diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2004-08-29 09:27:34 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2004-08-29 09:27:34 (GMT) |
commit | 90af9c5e09cfae599352ae2f24d7d8a44ad8f014 (patch) | |
tree | fbc7cd8daee10cdaf07eed85d912688132a222f6 /generic | |
parent | 97c495ce68eece2aab9e90f92a075dcd4b310b82 (diff) | |
download | tk-90af9c5e09cfae599352ae2f24d7d8a44ad8f014.zip tk-90af9c5e09cfae599352ae2f24d7d8a44ad8f014.tar.gz tk-90af9c5e09cfae599352ae2f24d7d8a44ad8f014.tar.bz2 |
TIP#165 (user data field) implementation.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tk.h | 5 | ||||
-rw-r--r-- | generic/tkBind.c | 45 | ||||
-rw-r--r-- | generic/tkEvent.c | 53 |
3 files changed, 79 insertions, 24 deletions
diff --git a/generic/tk.h b/generic/tk.h index 2ba5439..142f79a 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tk.h,v 1.80 2004/03/26 19:57:34 dgp Exp $ + * RCS: @(#) $Id: tk.h,v 1.81 2004/08/29 09:27:35 dkf Exp $ */ #ifndef _TK @@ -681,6 +681,9 @@ typedef struct { unsigned int state; /* key or button mask */ Tk_Uid name; /* Name of virtual event. */ Bool same_screen; /* same screen flag */ + Tcl_Obj *user_data; /* application-specific data reference; Tk will + * decrement the reference count *once* when it + * has finished processing the event. */ } XVirtualEvent; typedef struct { diff --git a/generic/tkBind.c b/generic/tkBind.c index 03453c8..c8a5b78 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.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: tkBind.c,v 1.34 2004/07/05 21:21:52 dkf Exp $ + * RCS: @(#) $Id: tkBind.c,v 1.35 2004/08/29 09:27:35 dkf Exp $ */ #include "tkPort.h" @@ -2392,6 +2392,14 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr) } else { string = ""; } + } else if (flags & VIRTUAL) { + XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr; + + if (vePtr->user_data != NULL) { + string = Tcl_GetString(vePtr->user_data); + } else { + string = ""; + } } goto doString; case 'f': @@ -3323,10 +3331,11 @@ HandleEventGenerate(interp, mainWin, objc, objv) Tk_Window tkwin, tkwin2; TkWindow *mainPtr; unsigned long eventMask; + Tcl_Obj *userDataObj; static CONST char *fieldStrings[] = { "-when", "-above", "-borderwidth", "-button", - "-count", "-delta", "-detail", "-focus", - "-height", + "-count", "-data", "-delta", "-detail", + "-focus", "-height", "-keycode", "-keysym", "-mode", "-override", "-place", "-root", "-rootx", "-rooty", "-sendevent", "-serial", "-state", "-subwindow", @@ -3335,8 +3344,8 @@ HandleEventGenerate(interp, mainWin, objc, objv) }; enum field { EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON, - EVENT_COUNT, EVENT_DELTA, EVENT_DETAIL, EVENT_FOCUS, - EVENT_HEIGHT, + EVENT_COUNT, EVENT_DATA, EVENT_DELTA, EVENT_DETAIL, + EVENT_FOCUS, EVENT_HEIGHT, EVENT_KEYCODE, EVENT_KEYSYM, EVENT_MODE, EVENT_OVERRIDE, EVENT_PLACE, EVENT_ROOT, EVENT_ROOTX, EVENT_ROOTY, EVENT_SEND, EVENT_SERIAL, EVENT_STATE, EVENT_SUBWINDOW, @@ -3366,6 +3375,7 @@ HandleEventGenerate(interp, mainWin, objc, objv) p = name; eventMask = 0; + userDataObj = NULL; count = ParseEventDescription(interp, &p, &pat, &eventMask); if (count == 0) { return TCL_ERROR; @@ -3519,6 +3529,18 @@ HandleEventGenerate(interp, mainWin, objc, objv) } break; } + case EVENT_DATA: + if (flags & VIRTUAL) { + /* + * Do not increment reference count until after + * parsing completes and we know that the event + * generation is really going to happen. + */ + userDataObj = valuePtr; + } else { + goto badopt; + } + break; case EVENT_DELTA: { if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; @@ -3846,6 +3868,19 @@ HandleEventGenerate(interp, mainWin, objc, objv) Tcl_GetStringFromObj(optionPtr, NULL), "\" option", NULL); return TCL_ERROR; } + if (userDataObj != NULL) { + XVirtualEvent *vePtr = (XVirtualEvent *) &event; + + /* + * Must be virtual event to set that variable to non-NULL. + * Now we want to install the object into the event. Note + * that we must incr the refcount before firing it into the + * low-level event subsystem; the refcount will be decremented + * once the event has been processed. + */ + vePtr->user_data = userDataObj; + Tcl_IncrRefCount(userDataObj); + } if (synch != 0) { Tk_HandleEvent(&event); } else { diff --git a/generic/tkEvent.c b/generic/tkEvent.c index ad9e29a..3b4b5a1 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -12,7 +12,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.24 2004/07/29 21:48:07 georgeps Exp $ + * RCS: @(#) $Id: tkEvent.c,v 1.25 2004/08/29 09:27:35 dkf Exp $ */ #include "tkPort.h" @@ -1281,7 +1281,7 @@ Tk_HandleEvent(eventPtr) Tcl_Interp *interp = (Tcl_Interp *) NULL; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); UpdateButtonEventState (eventPtr); @@ -1291,21 +1291,21 @@ Tk_HandleEvent(eventPtr) * and can return. */ if (InvokeGenericHandlers (tsdPtr, eventPtr)) { - return; + goto releaseUserData; } if (RefreshKeyboardMappingIfNeeded (eventPtr)) { - /* + /* * We are done with a MappingNotify event. */ - return; + goto releaseUserData; } mask = GetEventMaskFromXEvent(eventPtr); winPtr = GetTkWindowFromXEvent(eventPtr); if (winPtr == NULL) { - return; + goto releaseUserData; } /* @@ -1319,7 +1319,7 @@ Tk_HandleEvent(eventPtr) if ((winPtr->flags & TK_ALREADY_DEAD) && (eventPtr->type != DestroyNotify)) { - return; + goto releaseUserData; } if (winPtr->mainPtr != NULL) { @@ -1328,24 +1328,24 @@ 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)) - || (InvokeMouseHandlers(winPtr, mask, eventPtr))); + || (InvokeMouseHandlers(winPtr, mask, eventPtr))); if (result) { - goto done; + goto releaseInterpreter; } } #ifdef TK_USE_INPUT_METHODS if (InvokeInputMethods(winPtr, eventPtr)) { - goto done; + goto releaseInterpreter; } #endif /* @@ -1377,7 +1377,7 @@ 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 { @@ -1410,15 +1410,32 @@ Tk_HandleEvent(eventPtr) } } tsdPtr->pendingPtr = ip.nextPtr; -done: /* * Release the interpreter for this window so that it can be potentially * deleted if requested. */ +releaseInterpreter: if (interp != (Tcl_Interp *) NULL) { - Tcl_Release((ClientData) interp); + 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. + */ + +releaseUserData: + if (eventPtr->type == VirtualEvent) { + XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr; + + if (vePtr->user_data != NULL) { + Tcl_DecrRefCount(vePtr->user_data); + vePtr->user_data = NULL; + } } } |