summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2004-08-29 09:27:34 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2004-08-29 09:27:34 (GMT)
commit90af9c5e09cfae599352ae2f24d7d8a44ad8f014 (patch)
treefbc7cd8daee10cdaf07eed85d912688132a222f6 /generic
parent97c495ce68eece2aab9e90f92a075dcd4b310b82 (diff)
downloadtk-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.h5
-rw-r--r--generic/tkBind.c45
-rw-r--r--generic/tkEvent.c53
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;
+ }
}
}