⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tkevent.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * tkEvent.c -- * *	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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkEvent.c 1.20 96/09/20 09:33:38 */#include "tkPort.h"#include "tkInt.h"#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. */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. */} InProgress;static InProgress *pendingPtr = NULL;				/* Topmost search in progress, or				 * NULL if none. *//* * For each call to Tk_CreateGenericHandler, an instance of the following * structure will be created.  All of the active handlers are linked into a * 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. */    struct GenericHandler *nextPtr;				/* Next handler in list of all generic				 * handlers, or NULL for end of list. */} GenericHandler;static GenericHandler *genericList = NULL;				/* First handler in the list, or NULL. */static GenericHandler *lastGenericPtr = NULL;				/* Last handler in list. *//* * There's a potential problem if Tk_HandleEvent is entered recursively. * A handler cannot be deleted physically until we have returned from * 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 variable has a non-zero value when a handler is active. */static int genericHandlersActive = 0;/* * The following structure is used for queueing X-style events on the * Tcl event queue. */typedef struct TkWindowEvent {    Tcl_Event header;		/* Standard information for all events. */    XEvent event;		/* The X event. */} TkWindowEvent;/* * Array of event masks corresponding to each X event: */static unsigned long eventMasks[TK_LASTEVENT] = {    0,    0,    KeyPressMask,			/* KeyPress */    KeyReleaseMask,			/* KeyRelease */    ButtonPressMask,			/* ButtonPress */    ButtonReleaseMask,			/* ButtonRelease */    PointerMotionMask|PointerMotionHintMask|ButtonMotionMask	    |Button1MotionMask|Button2MotionMask|Button3MotionMask	    |Button4MotionMask|Button5MotionMask,					/* MotionNotify */    EnterWindowMask,			/* EnterNotify */    LeaveWindowMask,			/* LeaveNotify */    FocusChangeMask,			/* FocusIn */    FocusChangeMask,			/* FocusOut */    KeymapStateMask,			/* KeymapNotify */    ExposureMask,			/* Expose */    ExposureMask,			/* GraphicsExpose */    ExposureMask,			/* NoExpose */    VisibilityChangeMask,		/* VisibilityNotify */    SubstructureNotifyMask,		/* CreateNotify */    StructureNotifyMask,		/* DestroyNotify */    StructureNotifyMask,		/* UnmapNotify */    StructureNotifyMask,		/* MapNotify */    SubstructureRedirectMask,		/* MapRequest */    StructureNotifyMask,		/* ReparentNotify */    StructureNotifyMask,		/* ConfigureNotify */    SubstructureRedirectMask,		/* ConfigureRequest */    StructureNotifyMask,		/* GravityNotify */    ResizeRedirectMask,			/* ResizeRequest */    StructureNotifyMask,		/* CirculateNotify */    SubstructureRedirectMask,		/* CirculateRequest */    PropertyChangeMask,			/* PropertyNotify */    0,					/* SelectionClear */    0,					/* SelectionRequest */    0,					/* SelectionNotify */    ColormapChangeMask,			/* ColormapNotify */    0,					/* ClientMessage */    0,					/* Mapping Notify */    VirtualEventMask,			/* VirtualEvents */    ActivateMask,			/* ActivateNotify */    ActivateMask			/* DeactivateNotify */};/* * If someone has called Tk_RestrictEvents, the information below * keeps track of it. */static Tk_RestrictProc *restrictProc;				/* Procedure to call.  NULL means no				 * restrictProc is currently in effect. */static ClientData restrictArg;	/* Argument to pass to restrictProc. *//* * Prototypes for procedures 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));/* *-------------------------------------------------------------- * * Tk_CreateEventHandler -- * *	Arrange for a given procedure 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. * *-------------------------------------------------------------- */voidTk_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. */{    register TkEventHandler *handlerPtr;    register TkWindow *winPtr = (TkWindow *) token;    int found;    /*     * 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.     */    found = 0;    if (winPtr->handlerList == NULL) {	handlerPtr = (TkEventHandler *) ckalloc(		(unsigned) sizeof(TkEventHandler));	winPtr->handlerList = handlerPtr;	goto initHandler;    } else {	for (handlerPtr = winPtr->handlerList; ;		handlerPtr = handlerPtr->nextPtr) {	    if ((handlerPtr->proc == proc)		    && (handlerPtr->clientData == clientData)) {		handlerPtr->mask = mask;		found = 1;	    }	    if (handlerPtr->nextPtr == NULL) {		break;	    }	}    }    /*     * Create a new handler if no matching old handler was found.     */    if (!found) {	handlerPtr->nextPtr = (TkEventHandler *)		ckalloc(sizeof(TkEventHandler));	handlerPtr = handlerPtr->nextPtr;	initHandler:	handlerPtr->mask = mask;	handlerPtr->proc = proc;	handlerPtr->clientData = 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").     */}/* *-------------------------------------------------------------- * * Tk_DeleteEventHandler -- * *	Delete a previously-created handler. * * Results: *	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. * *-------------------------------------------------------------- */voidTk_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;{    register TkEventHandler *handlerPtr;    register InProgress *ipPtr;    TkEventHandler *prevPtr;    register TkWindow *winPtr = (TkWindow *) token;    /*     * Find the event handler to be deleted, or return     * immediately if it doesn't exist.     */    for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ;	    prevPtr = handlerPtr, handlerPtr = handlerPtr->nextPtr) {	if (handlerPtr == NULL) {	    return;	}	if ((handlerPtr->mask == mask) && (handlerPtr->proc == proc)		&& (handlerPtr->clientData == clientData)) {	    break;	}    }    /*     * If Tk_HandleEvent is about to process this handler, tell it to     * process the next one instead.     */    for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {	if (ipPtr->nextHandler == handlerPtr) {	    ipPtr->nextHandler = handlerPtr->nextPtr;	}    }    /*     * Free resources associated with the handler.     */    if (prevPtr == NULL) {	winPtr->handlerList = handlerPtr->nextPtr;    } else {	prevPtr->nextPtr = handlerPtr->nextPtr;    }    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").     */}/*-------------------------------------------------------------- * * 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. * * 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. * *-------------------------------------------------------------- */voidTk_CreateGenericHandler(proc, clientData)     Tk_GenericProc *proc;	/* Procedure to call on every event. */     ClientData clientData;	/* One-word value to pass to proc. */{    GenericHandler *handlerPtr;        handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler));        handlerPtr->proc = proc;    handlerPtr->clientData = clientData;    handlerPtr->deleteFlag = 0;    handlerPtr->nextPtr = NULL;    if (genericList == NULL) {	genericList = handlerPtr;    } else {	lastGenericPtr->nextPtr = handlerPtr;    }    lastGenericPtr = handlerPtr;}/* *-------------------------------------------------------------- * * Tk_DeleteGenericHandler -- * *	Delete a previously-created generic 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 Tk_HandleEvent. * *-------------------------------------------------------------- */voidTk_DeleteGenericHandler(proc, clientData)     Tk_GenericProc *proc;     ClientData clientData;{    GenericHandler * handler;        for (handler = genericList; handler; handler = handler->nextPtr) {	if ((handler->proc == proc) && (handler->clientData == clientData)) {	    handler->deleteFlag = 1;	}    }}/* *-------------------------------------------------------------- * * Tk_HandleEvent -- * *	Given an event, invoke all the handlers that have *	been registered for the event. * * Results: *	None. * * Side effects: *	Depends on the handlers. * *-------------------------------------------------------------- */voidTk_HandleEvent(eventPtr)    XEvent *eventPtr;		/* Event to dispatch. */{    register TkEventHandler *handlerPtr;    register GenericHandler *genericPtr;    register GenericHandler *genPrevPtr;    TkWindow *winPtr;    unsigned long mask;    InProgress ip;    Window handlerWindow;    TkDisplay *dispPtr;    Tcl_Interp *interp = (Tcl_Interp *) NULL;    /*      * Next, invoke all the generic event handlers (those that are     * invoked for all events).  If a generic event handler reports that     * an event is fully processed, go no further.     */    for (genPrevPtr = NULL, genericPtr = genericList;  genericPtr != NULL; ) {	if (genericPtr->deleteFlag) {	    if (!genericHandlersActive) {		GenericHandler *tmpPtr;		/*		 * 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 = genericPtr->nextPtr;		if (genPrevPtr == NULL) {		    genericList = tmpPtr;		} else {		    genPrevPtr->nextPtr = tmpPtr;		}		if (tmpPtr == NULL) {		    lastGenericPtr = genPrevPtr;		}		(void) ckfree((char *) genericPtr);		genericPtr = tmpPtr;		continue;	    }	} else {	    int done;	    genericHandlersActive++;	    done = (*genericPtr->proc)(genericPtr->clientData, eventPtr);	    genericHandlersActive--;	    if (done) {		return;	    }	}	genPrevPtr = genericPtr;	genericPtr = genPrevPtr->nextPtr;    }    /*     * If the event is a MappingNotify event, find its display and     * refresh the keyboard mapping information for the display.     * After that there's nothing else to do with the event, so just     * quit.     */    if (eventPtr->type == MappingNotify) {	dispPtr = TkGetDisplay(eventPtr->xmapping.display);	if (dispPtr != NULL) {	    XRefreshKeyboardMapping(&eventPtr->xmapping);	    dispPtr->bindInfoStale = 1;	}	return;    }    /*     * 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.     */    handlerWindow = eventPtr->xany.window;    mask = eventMasks[eventPtr->xany.type];    if (mask == StructureNotifyMask) {	if (eventPtr->xmap.event != eventPtr->xmap.window) {	    mask = SubstructureNotifyMask;	    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).	 */	if (eventPtr->type == PropertyNotify) {	    TkSelPropProc(eventPtr);	}	return;    }    /*     * 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).     */    if ((winPtr->flags & TK_ALREADY_DEAD)	    && (eventPtr->type != DestroyNotify)) {	return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -