From d3d7a663b147a1e4b1648a37400c7ea2fb8ee3df Mon Sep 17 00:00:00 2001 From: hobbs Date: Sat, 3 Jun 2000 08:58:14 +0000 Subject: * generic/tk.h: added typdef for Tk_ClientMessageProc * generic/tkStubInit.c: * generic/tkDecls.h: * generic/tk.decls: Added Tk_CreateClientMessageHandler and Tk_DeleteClientMessageHandler declarations. * generic/tkEvent.c (Tk_HandleEvent): Added Tk_CreateClientMessageHandler and Tk_DeleteClientMessageHandler to allow adding event handlers that invoke for ClientMessage events. This is necessary to support unix dnd protocols. FossilOrigin-Name: 4796e716c5c1f9ba0b66cab909d6f057c440ce77 --- generic/tk.decls | 14 +++- generic/tk.h | 6 +- generic/tkDecls.h | 18 ++++- generic/tkEvent.c | 197 ++++++++++++++++++++++++++++++++++++++++++--------- generic/tkStubInit.c | 4 +- 5 files changed, 198 insertions(+), 41 deletions(-) diff --git a/generic/tk.decls b/generic/tk.decls index d5af12a..2843334 100644 --- a/generic/tk.decls +++ b/generic/tk.decls @@ -6,11 +6,12 @@ # tkStub.c, and tkPlatStub.c files. # # -# Copyright (c) 1998-1999 by Scriptics Corporation. +# Copyright (c) 1998-2000 Ajuba Solutions. +# # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: tk.decls,v 1.10 2000/04/25 01:03:05 hobbs Exp $ +# RCS: @(#) $Id: tk.decls,v 1.11 2000/06/03 08:58:14 hobbs Exp $ library tk @@ -1126,6 +1127,15 @@ declare 238 generic { int width, int height) } +# New in 8.4a1 +# +declare 239 generic { + void Tk_CreateClientMessageHandler (Tk_ClientMessageProc *proc) +} +declare 240 generic { + void Tk_DeleteClientMessageHandler (Tk_ClientMessageProc *proc) +} + # Define the platform specific public Tk interface. These functions are # only available on the designated platform. diff --git a/generic/tk.h b/generic/tk.h index 3542015..d833b25 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -7,12 +7,12 @@ * Copyright (c) 1989-1994 The Regents of the University of California. * Copyright (c) 1994 The Australian National University. * Copyright (c) 1994-1998 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Scriptics Corporation. + * Copyright (c) 1998-2000 Ajuba Solutions. * * 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.44 2000/05/29 01:42:47 hobbs Exp $ + * RCS: @(#) $Id: tk.h,v 1.45 2000/06/03 08:58:15 hobbs Exp $ */ #ifndef _TK @@ -1340,6 +1340,8 @@ typedef void (Tk_EventProc) _ANSI_ARGS_((ClientData clientData, XEvent *eventPtr)); typedef int (Tk_GenericProc) _ANSI_ARGS_((ClientData clientData, XEvent *eventPtr)); +typedef int (Tk_ClientMessageProc) _ANSI_ARGS_((Tk_Window tkwin, + XEvent *eventPtr)); typedef int (Tk_GetSelProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, char *portion)); typedef void (Tk_LostSelProc) _ANSI_ARGS_((ClientData clientData)); diff --git a/generic/tkDecls.h b/generic/tkDecls.h index 6b6d241..edd169e 100644 --- a/generic/tkDecls.h +++ b/generic/tkDecls.h @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkDecls.h,v 1.11 2000/04/25 01:03:06 hobbs Exp $ + * RCS: @(#) $Id: tkDecls.h,v 1.12 2000/06/03 08:58:15 hobbs Exp $ */ #ifndef _TKDECLS @@ -820,6 +820,12 @@ EXTERN int Tk_PostscriptPhoto _ANSI_ARGS_((Tcl_Interp * interp, Tk_PhotoImageBlock * blockPtr, Tk_PostscriptInfo psInfo, int width, int height)); +/* 239 */ +EXTERN void Tk_CreateClientMessageHandler _ANSI_ARGS_(( + Tk_ClientMessageProc * proc)); +/* 240 */ +EXTERN void Tk_DeleteClientMessageHandler _ANSI_ARGS_(( + Tk_ClientMessageProc * proc)); typedef struct TkStubHooks { struct TkPlatStubs *tkPlatStubs; @@ -1071,6 +1077,8 @@ typedef struct TkStubs { int (*tk_PostscriptStipple) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap)); /* 236 */ double (*tk_PostscriptY) _ANSI_ARGS_((double y, Tk_PostscriptInfo psInfo)); /* 237 */ int (*tk_PostscriptPhoto) _ANSI_ARGS_((Tcl_Interp * interp, Tk_PhotoImageBlock * blockPtr, Tk_PostscriptInfo psInfo, int width, int height)); /* 238 */ + void (*tk_CreateClientMessageHandler) _ANSI_ARGS_((Tk_ClientMessageProc * proc)); /* 239 */ + void (*tk_DeleteClientMessageHandler) _ANSI_ARGS_((Tk_ClientMessageProc * proc)); /* 240 */ } TkStubs; #ifdef __cplusplus @@ -2037,6 +2045,14 @@ extern TkStubs *tkStubsPtr; #define Tk_PostscriptPhoto \ (tkStubsPtr->tk_PostscriptPhoto) /* 238 */ #endif +#ifndef Tk_CreateClientMessageHandler +#define Tk_CreateClientMessageHandler \ + (tkStubsPtr->tk_CreateClientMessageHandler) /* 239 */ +#endif +#ifndef Tk_DeleteClientMessageHandler +#define Tk_DeleteClientMessageHandler \ + (tkStubsPtr->tk_DeleteClientMessageHandler) /* 240 */ +#endif #endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ diff --git a/generic/tkEvent.c b/generic/tkEvent.c index abb2b14..366ba86 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -6,12 +6,12 @@ * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright (c) 1998-2000 Ajuba Solutions. * * 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.7 1999/12/16 21:57:36 hobbs Exp $ + * RCS: @(#) $Id: tkEvent.c,v 1.8 2000/06/03 08:58:16 hobbs Exp $ */ #include "tkPort.h" @@ -130,17 +130,16 @@ static unsigned long eventMasks[TK_LASTEVENT] = { */ typedef struct ThreadSpecificData { - - int genericHandlersActive; - /* The following variable has a non-zero + int handlersActive; /* The following variable has a non-zero * value when a handler is active. */ - InProgress *pendingPtr; - /* Topmost search in progress, or + 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. */ + + GenericHandler *genericList; /* First handler in the list, or NULL. */ + GenericHandler *lastGenericPtr; /* Last handler in list. */ + + GenericHandler *cmList; /* First handler in the list, or NULL. */ + GenericHandler *lastCmPtr; /* Last handler in list. */ /* * If someone has called Tk_RestrictEvents, the information below @@ -150,7 +149,7 @@ typedef struct ThreadSpecificData { Tk_RestrictProc *restrictProc; /* Procedure to call. NULL means no * restrictProc is currently in effect. */ - ClientData restrictArg; /* Argument to pass to restrictProc. */ + ClientData restrictArg; /* Argument to pass to restrictProc. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -162,6 +161,7 @@ static Tcl_ThreadDataKey dataKey; static void DelayedMotionProc _ANSI_ARGS_((ClientData clientData)); static int WindowEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int flags)); + /* *-------------------------------------------------------------- @@ -354,16 +354,16 @@ Tk_CreateGenericHandler(proc, clientData) handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler)); - handlerPtr->proc = proc; - handlerPtr->clientData = clientData; - handlerPtr->deleteFlag = 0; - handlerPtr->nextPtr = NULL; + handlerPtr->proc = proc; + handlerPtr->clientData = clientData; + handlerPtr->deleteFlag = 0; + handlerPtr->nextPtr = NULL; if (tsdPtr->genericList == NULL) { - tsdPtr->genericList = handlerPtr; + tsdPtr->genericList = handlerPtr; } else { tsdPtr->lastGenericPtr->nextPtr = handlerPtr; } - tsdPtr->lastGenericPtr = handlerPtr; + tsdPtr->lastGenericPtr = handlerPtr; } /* @@ -392,7 +392,7 @@ Tk_DeleteGenericHandler(proc, clientData) { GenericHandler * handler; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (handler = tsdPtr->genericList; handler; handler = handler->nextPtr) { if ((handler->proc == proc) && (handler->clientData == clientData)) { @@ -401,6 +401,86 @@ Tk_DeleteGenericHandler(proc, clientData) } } +/*-------------------------------------------------------------- + * + * Tk_CreateClientMessageHandler -- + * + * Register a procedure 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. + * + *-------------------------------------------------------------- + */ + +void +Tk_CreateClientMessageHandler(proc) + Tk_ClientMessageProc *proc; /* Procedure to call on event. */ +{ + GenericHandler *handlerPtr; + 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. + */ + handlerPtr = (GenericHandler *) + ckalloc (sizeof (GenericHandler)); + + handlerPtr->proc = (Tk_GenericProc *) proc; + handlerPtr->clientData = NULL; /* never used */ + handlerPtr->deleteFlag = 0; + handlerPtr->nextPtr = NULL; + if (tsdPtr->cmList == NULL) { + tsdPtr->cmList = handlerPtr; + } else { + tsdPtr->lastCmPtr->nextPtr = handlerPtr; + } + tsdPtr->lastCmPtr = handlerPtr; +} + +/* + *-------------------------------------------------------------- + * + * Tk_DeleteClientMessageHandler -- + * + * Delete a previously-created ClientMessage handler. + * + * Results: + * 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. + * + *-------------------------------------------------------------- + */ + +void +Tk_DeleteClientMessageHandler(proc) + Tk_ClientMessageProc *proc; +{ + GenericHandler * handler; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + for (handler = tsdPtr->cmList; handler != NULL; + handler = handler->nextPtr) { + if (handler->proc == (Tk_GenericProc *) proc) { + handler->deleteFlag = 1; + } + } +} + /* *-------------------------------------------------------------- * @@ -424,14 +504,16 @@ void TkEventInit _ANSI_ARGS_((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; + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->handlersActive = 0; + tsdPtr->pendingPtr = NULL; + tsdPtr->genericList = NULL; + tsdPtr->lastGenericPtr = NULL; + tsdPtr->cmList = NULL; + tsdPtr->lastCmPtr = NULL; + tsdPtr->restrictProc = NULL; + tsdPtr->restrictArg = NULL; } /* @@ -465,7 +547,7 @@ Tk_HandleEvent(eventPtr) TkDisplay *dispPtr; Tcl_Interp *interp = (Tcl_Interp *) NULL; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Hack for simulated X-events: Correct the state field @@ -503,7 +585,7 @@ Tk_HandleEvent(eventPtr) for (genPrevPtr = NULL, genericPtr = tsdPtr->genericList; genericPtr != NULL; ) { if (genericPtr->deleteFlag) { - if (!tsdPtr->genericHandlersActive) { + if (!tsdPtr->handlersActive) { GenericHandler *tmpPtr; /* @@ -528,9 +610,9 @@ Tk_HandleEvent(eventPtr) } else { int done; - tsdPtr->genericHandlersActive++; + tsdPtr->handlersActive++; done = (*genericPtr->proc)(genericPtr->clientData, eventPtr); - tsdPtr->genericHandlersActive--; + tsdPtr->handlersActive--; if (done) { return; } @@ -710,10 +792,55 @@ Tk_HandleEvent(eventPtr) || (eventPtr->type == SelectionRequest) || (eventPtr->type == SelectionNotify)) { TkSelEventProc((Tk_Window) winPtr, eventPtr); - } else if ((eventPtr->type == ClientMessage) - && (eventPtr->xclient.message_type == - Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS"))) { - TkWmProtocolEventProc(winPtr, eventPtr); + } else if (eventPtr->type == ClientMessage) { + if (eventPtr->xclient.message_type == + Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS")) { + TkWmProtocolEventProc(winPtr, eventPtr); + } else { + /* + * Finally, invoke any ClientMessage event handlers. + */ + + for (genPrevPtr = NULL, genericPtr = tsdPtr->cmList; + genericPtr != NULL; ) { + if (genericPtr->deleteFlag) { + if (!tsdPtr->handlersActive) { + GenericHandler *tmpPtr; + + /* + * 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 = genericPtr->nextPtr; + if (genPrevPtr == NULL) { + tsdPtr->cmList = tmpPtr; + } else { + genPrevPtr->nextPtr = tmpPtr; + } + if (tmpPtr == NULL) { + tsdPtr->lastGenericPtr = genPrevPtr; + } + (void) ckfree((char *) genericPtr); + genericPtr = tmpPtr; + continue; + } + } else { + int done; + + tsdPtr->handlersActive++; + done = (*(Tk_ClientMessageProc *)genericPtr->proc) + ((Tk_Window) winPtr, eventPtr); + tsdPtr->handlersActive--; + if (done) { + break; + } + } + genPrevPtr = genericPtr; + genericPtr = genPrevPtr->nextPtr; + } + } } } else { for (handlerPtr = winPtr->handlerList; handlerPtr != NULL; ) { diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index ea50f6a..67a2add 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkStubInit.c,v 1.22 2000/04/25 01:03:07 hobbs Exp $ + * RCS: @(#) $Id: tkStubInit.c,v 1.23 2000/06/03 08:58:16 hobbs Exp $ */ #include "tkInt.h" @@ -949,6 +949,8 @@ TkStubs tkStubs = { Tk_PostscriptStipple, /* 236 */ Tk_PostscriptY, /* 237 */ Tk_PostscriptPhoto, /* 238 */ + Tk_CreateClientMessageHandler, /* 239 */ + Tk_DeleteClientMessageHandler, /* 240 */ }; /* !END!: Do not edit above this line. */ -- cgit v0.12