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

📄 tkgrab.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 4 页
字号:
     * 3. If a button press or release occurs outside the window where     *    the first button was pressed, retarget the event so it's reported     *    to the window where the first button was pressed.     * 4. If the last button is released in a window different than where     *    the first button was pressed, generate Enter/Leave events to     *    move the mouse from the button window to its current window.     * 5. If the grab is set at a time when a button is already down, or     *    if the window where the button was pressed was deleted, then     *    dispPtr->buttonWinPtr will stay NULL.  Just forget about the     *    auto-grab for the button press;  events will go to whatever     *    window contains the pointer.  If this window isn't in the grab     *    tree then redirect events to the grab window.     * 6. When a button is pressed during a local grab, the X server sets     *    a grab of its own, since it doesn't even know about our local     *    grab.  This causes enter and leave events no longer to be     *    generated in the same way as for global grabs.  To eliminate this     *    problem, set a temporary global grab when the first button goes     *    down and release it when the last button comes up.     */    if ((eventPtr->type == ButtonPress) || (eventPtr->type == ButtonRelease)) {	winPtr2 = dispPtr->buttonWinPtr;	if (winPtr2 == NULL) {	    if (outsideGrabTree) {		winPtr2 = dispPtr->grabWinPtr;			/* Note 5. */	    } else {		winPtr2 = winPtr;				/* Note 5. */	    }	}	if (eventPtr->type == ButtonPress) {	    if ((eventPtr->xbutton.state & ALL_BUTTONS) == 0) {		if (outsideGrabTree) {		    TkChangeEventWindow(eventPtr, dispPtr->grabWinPtr);		    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);		    return 0;					/* Note 2. */		}		if (!(dispPtr->grabFlags & GRAB_GLOBAL)) {	/* Note 6. */		    serial = NextRequest(dispPtr->display);		    if (XGrabPointer(dispPtr->display,			    dispPtr->grabWinPtr->window, True,			    ButtonPressMask|ButtonReleaseMask|ButtonMotionMask,			    GrabModeAsync, GrabModeAsync, None, None,			    CurrentTime) == 0) {			EatGrabEvents(dispPtr, serial);			if (XGrabKeyboard(dispPtr->display, winPtr->window,				False, GrabModeAsync, GrabModeAsync,				CurrentTime) == 0) {			    dispPtr->grabFlags |= GRAB_TEMP_GLOBAL;			} else {			    XUngrabPointer(dispPtr->display, CurrentTime);			}		    }		}		dispPtr->buttonWinPtr = winPtr;		return 1;	    }	} else {	    if ((eventPtr->xbutton.state & ALL_BUTTONS)		    == buttonStates[eventPtr->xbutton.button - Button1]) {		ReleaseButtonGrab(dispPtr);			/* Note 4. */	    }	}	if (winPtr2 != winPtr) {	    TkChangeEventWindow(eventPtr, winPtr2);	    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);	    return 0;						/* Note 3. */	}    }    return 1;}/* *---------------------------------------------------------------------- * * TkChangeEventWindow -- * *	Given an event and a new window to which the event should be *	retargeted, modify fields of the event so that the event is *	properly retargeted to the new window. * * Results: *	The following fields of eventPtr are modified:  window, *	subwindow, x, y, same_screen. * * Side effects: *	None. * *---------------------------------------------------------------------- */voidTkChangeEventWindow(eventPtr, winPtr)    register XEvent *eventPtr;	/* Event to retarget.  Must have				 * type ButtonPress, ButtonRelease, KeyPress,				 * KeyRelease, MotionNotify, EnterNotify,				 * or LeaveNotify. */    TkWindow *winPtr;		/* New target window for event. */{    int x, y, sameScreen, bd;    register TkWindow *childPtr;    eventPtr->xmotion.window = Tk_WindowId(winPtr);    if (eventPtr->xmotion.root ==	    RootWindow(winPtr->display, winPtr->screenNum)) {	Tk_GetRootCoords((Tk_Window) winPtr, &x, &y);	eventPtr->xmotion.x = eventPtr->xmotion.x_root - x;	eventPtr->xmotion.y = eventPtr->xmotion.y_root - y;	eventPtr->xmotion.subwindow = None;	for (childPtr = winPtr->childList; childPtr != NULL;		childPtr = childPtr->nextPtr) {	    if (childPtr->flags & TK_TOP_LEVEL) {		continue;	    }	    x = eventPtr->xmotion.x - childPtr->changes.x;	    y = eventPtr->xmotion.y - childPtr->changes.y;	    bd = childPtr->changes.border_width;	    if ((x >= -bd) && (y >= -bd)		    && (x < (childPtr->changes.width + bd))		    && (y < (childPtr->changes.height + bd))) {		eventPtr->xmotion.subwindow = childPtr->window;	    }	}	sameScreen = 1;    } else {	eventPtr->xmotion.x = 0;	eventPtr->xmotion.y = 0;	eventPtr->xmotion.subwindow = None;	sameScreen = 0;    }    if (eventPtr->type == MotionNotify) {	eventPtr->xmotion.same_screen = sameScreen;    } else {	eventPtr->xbutton.same_screen = sameScreen;    }}/* *---------------------------------------------------------------------- * * TkInOutEvents -- * *	This procedure synthesizes EnterNotify and LeaveNotify events *	to correctly transfer the pointer from one window to another. *	It can also be used to generate FocusIn and FocusOut events *	to move the input focus. * * Results: *	None. * * Side effects: *	Synthesized events may be pushed back onto the event queue. *	The event pointed to by eventPtr is modified. * *---------------------------------------------------------------------- */voidTkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position)    XEvent *eventPtr;		/* A template X event.  Must have all fields				 * properly set except for type, window,				 * subwindow, x, y, detail, and same_screen				 * (Not all of these fields are valid for				 * FocusIn/FocusOut events;  x_root and y_root				 * must be valid for Enter/Leave events, even				 * though x and y needn't be valid). */    TkWindow *sourcePtr;	/* Window that used to have the pointer or				 * focus (NULL means it was not in a window				 * managed by this process). */    TkWindow *destPtr;		/* Window that is to end up with the pointer				 * or focus (NULL means it's not one managed				 * by this process). */    int leaveType;		/* Type of events to generate for windows				 * being left (LeaveNotify or FocusOut).  0				 * means don't generate leave events. */    int enterType;		/* Type of events to generate for windows				 * being entered (EnterNotify or FocusIn).  0				 * means don't generate enter events. */    Tcl_QueuePosition position;	/* Position at which events are added to				 * the system event queue. */{    register TkWindow *winPtr;    int upLevels, downLevels, i, j, focus;    /*     * There are four possible cases to deal with:     *     * 1. SourcePtr and destPtr are the same.  There's nothing to do in     *    this case.     * 2. SourcePtr is an ancestor of destPtr in the same top-level     *    window.  Must generate events down the window tree from source     *    to dest.     * 3. DestPtr is an ancestor of sourcePtr in the same top-level     *    window.  Must generate events up the window tree from sourcePtr     *    to destPtr.     * 4. All other cases.  Must first generate events up the window tree     *    from sourcePtr to its top-level, then down from destPtr's     *    top-level to destPtr. This form is called "non-linear."     *     * The call to FindCommonAncestor separates these four cases and decides     * how many levels up and down events have to be generated for.     */    if (sourcePtr == destPtr) {	return;    }    if ((leaveType == FocusOut) || (enterType == FocusIn)) {	focus = 1;    } else {	focus = 0;    }    FindCommonAncestor(sourcePtr, destPtr, &upLevels, &downLevels);    /*     * Generate enter/leave events and add them to the grab event queue.     */#define QUEUE(w, t, d)					\    if (w->window != None) {				\	eventPtr->type = t;				\	if (focus) {					\	    eventPtr->xfocus.window = w->window;	\	    eventPtr->xfocus.detail = d;		\	} else {					\	    eventPtr->xcrossing.detail = d;		\	    TkChangeEventWindow(eventPtr, w);		\	}						\	Tk_QueueWindowEvent(eventPtr, position);	\    }    if (downLevels == 0) {    	/*	 * SourcePtr is an inferior of destPtr.	 */	if (leaveType != 0) {	    QUEUE(sourcePtr, leaveType, NotifyAncestor);	    for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0;		    winPtr = winPtr->parentPtr, i--) {		QUEUE(winPtr, leaveType, NotifyVirtual);	    }	}	if ((enterType != 0) && (destPtr != NULL)) {	    QUEUE(destPtr, enterType, NotifyInferior);	}    } else if (upLevels == 0) {	/*	 * DestPtr is an inferior of sourcePtr.	 */	if ((leaveType != 0) && (sourcePtr != NULL)) {	    QUEUE(sourcePtr, leaveType, NotifyInferior);	}	if (enterType != 0) {	    for (i = downLevels-1; i > 0; i--) {		for (winPtr = destPtr->parentPtr, j = 1; j < i;			winPtr = winPtr->parentPtr, j++) {		}		QUEUE(winPtr, enterType, NotifyVirtual);	    }	    if (destPtr != NULL) {		QUEUE(destPtr, enterType, NotifyAncestor);	    }	}    } else {	/*	 * Non-linear:  neither window is an inferior of the other.	 */	if (leaveType != 0) {	    QUEUE(sourcePtr, leaveType, NotifyNonlinear);	    for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0;		    winPtr = winPtr->parentPtr, i--) {		QUEUE(winPtr, leaveType, NotifyNonlinearVirtual);	    }	}	if (enterType != 0) {	    for (i = downLevels-1; i > 0; i--) {		for (winPtr = destPtr->parentPtr, j = 1; j < i;			winPtr = winPtr->parentPtr, j++) {		}		QUEUE(winPtr, enterType, NotifyNonlinearVirtual);	    }	    if (destPtr != NULL) {		QUEUE(destPtr, enterType, NotifyNonlinear);	    }	}    }}/* *---------------------------------------------------------------------- * * MovePointer2 -- * *	This procedure synthesizes  EnterNotify and LeaveNotify events *	to correctly transfer the pointer from one window to another. *	It is different from TkInOutEvents in that no template X event *	needs to be supplied;  this procedure generates the template *	event and calls TkInOutEvents. * * Results: *	None. * * Side effects: *	Synthesized events may be pushed back onto the event queue. * *---------------------------------------------------------------------- */static voidMovePointer2(sourcePtr, destPtr, mode, leaveEvents, enterEvents)    TkWindow *sourcePtr;	/* Window currently containing pointer (NULL				 * means it's not one managed by this				 * process). */    TkWindow *destPtr;		/* Window that is to end up containing the				 * pointer (NULL means it's not one managed				 * by this process). */    int mode;			/* Mode for enter/leave events, such as				 * NotifyNormal or NotifyUngrab. */    int leaveEvents;		/* Non-zero means generate leave events for the				 * windows being left.  Zero means don't				 * generate leave events. */    int enterEvents;		/* Non-zero means generate enter events for the				 * windows being entered.  Zero means don't				 * generate enter events. */{    XEvent event;    Window dummy1, dummy2;    int dummy3, dummy4;    TkWindow *winPtr;    winPtr = sourcePtr;    if ((winPtr == NULL) || (winPtr->window == None)) {	winPtr = destPtr;	if ((winPtr == NULL) || (winPtr->window == None)) {	    return;	}    }    event.xcrossing.serial = LastKnownRequestProcessed(	winPtr->display);    event.xcrossing.send_event = GENERATED_EVENT_MAGIC;    event.xcrossing.display = winPtr->display;    event.xcrossing.root = RootWindow(winPtr->display,	    winPtr->screenNum);    event.xcrossing.time = TkCurrentTime(winPtr->dispPtr);    XQueryPointer(winPtr->display, winPtr->window, &dummy1, &dummy2,	    &event.xcrossing.x_root, &event.xcrossing.y_root,	    &dummy3, &dummy4, &event.xcrossing.state);    event.xcrossing.mode = mode;    event.xcrossing.focus = False;    TkInOutEvents(&event, sourcePtr, destPtr, (leaveEvents) ? LeaveNotify : 0,	    (enterEvents) ? EnterNotify : 0, TCL_QUEUE_MARK);}/* *---------------------------------------------------------------------- * * TkGrabDeadWindow -- * *	This procedure is invoked whenever a window is deleted, so that *	grab-related cleanup can be performed. * * Results: *	None. * * Side effects: *	Various cleanups happen, such as generating events to move the *	pointer back to its "natural" window as if an ungrab had been *	done.  See the code. * *---------------------------------------------------------------------- */voidTkGrabDeadWindow(winPtr)    register TkWindow *winPtr;		/* Window that is in the process					 * of being deleted. */{

⌨️ 快捷键说明

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