rem: eventPtr->xmotion.state |= dispPtr->mouseButtonState;
add: if (dispPtr->mouseButtonState & (Button1Mask|Button2Mask|Button3Mask)) { if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) {  dispPtr->mouseButtonState &= ~(Button1Mask|Button2Mask|Button3Mask); dispPtr->mouseButtonWindow = 0; } else { eventPtr->xmotion.state |= dispPtr->mouseButtonState; } }
context: Tk_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;    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));    /*     * Hack for simulated X-events: Correct the state field     * of the event record to match with the ButtonPress     * and ButtonRelease events.     */    if (eventPtr->type==ButtonPress) {	dispPtr = TkGetDisplay(eventPtr->xbutton.display);	eventPtr->xbutton.state |= dispPtr->mouseButtonState;	switch (eventPtr->xbutton.button) {	    case 1: dispPtr->mouseButtonState |= Button1Mask; break; 	    case 2: dispPtr->mouseButtonState |= Button2Mask; break; 	    case 3: dispPtr->mouseButtonState |= Button3Mask; break; 	}    } else if (eventPtr->type==ButtonRelease) {	dispPtr = TkGetDisplay(eventPtr->xbutton.display);	switch (eventPtr->xbutton.button) {	    case 1: dispPtr->mouseButtonState &= ~Button1Mask; break; 	    case 2: dispPtr->mouseButtonState &= ~Button2Mask; break; 	    case 3: dispPtr->mouseButtonState &= ~Button3Mask; break; 	}	eventPtr->xbutton.state |= dispPtr->mouseButtonState;    } else if (eventPtr->type==MotionNotify) {	dispPtr = TkGetDisplay(eventPtr->xmotion.display);	eventPtr->xmotion.state |= dispPtr->mouseButtonState;    }    /*      * 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 = tsdPtr->genericList;              genericPtr != NULL; ) {	if (genericPtr->deleteFlag) {	    if (!tsdPtr->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) {		    tsdPtr->genericList = tmpPtr;		} else {		    genPrevPtr->nextPtr = tmpPtr;		}		if (tmpPtr == NULL) {		    tsdPtr->lastGenericPtr = genPrevPtr;		}		(void) ckfree((char *) genericPtr);		genericPtr = tmpPtr;		continue;	    }	} else {	    int done;	    tsdPtr->genericHandlersActive++;	    done = (*genericPtr->proc)(genericPtr->clientData, eventPtr);	    tsdPtr->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;    }    if (winPtr->mainPtr != NULL) {        /*         * 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.         */                interp = winPtr->mainPtr->interp;        Tcl_Preserve((ClientData) interp);        	/*	 * Call focus-related code to look at FocusIn, FocusOut, Enter,	 * and Leave events;  depending on its return value, ignore the	 * event.	 */    	if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask))		&& !TkFocusFilterEvent(winPtr, eventPtr)) {            Tcl_Release((ClientData) interp);	    return;	}    	/*	 * Redirect KeyPress and KeyRelease events to the focus window,	 * or ignore them entirely if there is no focus window.  We also	 * route the MouseWheel event to the focus window.  The MouseWheel	 * event is an extension to the X event set.  Currently, it is only	 * available on the Windows version of Tk.	 */    	if (mask & (KeyPressMask|KeyReleaseMask|MouseWheelMask)) {	    winPtr->dispPtr->lastEventTime = eventPtr->xkey.time;	    winPtr = TkFocusKeyEvent(winPtr, eventPtr);	    if (winPtr == NULL) {                Tcl_Release((ClientData) interp);		return;	    }	}    	/*	 * Call a grab-related procedure to do special processing on	 * pointer events.	 */    	if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask		|EnterWindowMask|LeaveWindowMask)) {	    if (mask & (ButtonPressMask|ButtonReleaseMask)) {		winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time;	    } else if (mask & PointerMotionMask) {		winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time;	    } else {		winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time;	    }	    if (TkPointerEvent(eventPtr, winPtr) == 0) {                goto done;	    }	}    }#ifdef TK_USE_INPUT_METHODS    /*     * 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).     */    if (winPtr->dispPtr->useInputMethods) {	if (!(winPtr->flags & TK_CHECKED_IC)) {	    if (winPtr->dispPtr->inputMethod != NULL) {		winPtr->inputContext = XCreateIC(		    winPtr->dispPtr->inputMethod, XNInputStyle,		    XIMPreeditNothing|XIMStatusNothing,		    XNClientWindow, winPtr->window,		    XNFocusWindow, winPtr->window, NULL);	    }	    winPtr->flags |= TK_CHECKED_IC;	}	if (XFilterEvent(eventPtr, None)) {	    goto done;	}    }#endif /* TK_USE_INPUT_METHODS */    /*     * For events where it hasn't already been done, update the current     * time in the display.     */    if (eventPtr->type == PropertyNotify) {	winPtr->dispPtr->lastEventTime = eventPtr->xproperty.time;    }    /*     * There's a potential interaction here with Tk_DeleteEventHandler.     * Read the documentation for pendingPtr.     */    ip.eventPtr = eventPtr;    ip.winPtr = winPtr;    ip.nextHandler = NULL;    ip.nextPtr = tsdPtr->pendingPtr;    tsdPtr->pendingPtr = &ip;    if (mask == 0) {	if ((eventPtr->type == SelectionClear)		|| (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 {	for (handlerPtr = winPtr->handlerList; handlerPtr != NULL; ) {	    if ((handlerPtr->mask & mask) != 0) {		ip.nextHandler = handlerPtr->nextPtr;		(*(handlerPtr->proc))(handlerPtr->clientData, eventPtr);		handlerPtr = ip.nextHandler;	    } else {		handlerPtr = handlerPtr->nextPtr;	    }	}	/*	 * 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.	 */	if ((ip.winPtr != None) && (mask != SubstructureNotifyMask)) {	    TkBindEventProc(winPtr, eventPtr);	}    }    tsdPtr->pendingPtr = ip.nextPtr;done:    /*     * Release the interpreter for this window so that it can be potentially     * deleted if requested.     */        if (interp != (Tcl_Interp *) NULL) {        Tcl_Release((ClientData) interp);    }}