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

📄 tkgrab.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * see the button-up event;  and (b) it allows us to track mouse	 * motion among all of the windows of this application.	 */	dispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL);	XQueryPointer(dispPtr->display, winPtr->window, &dummy1,		&dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &state);	if ((state & ALL_BUTTONS) != 0) {	    dispPtr->grabFlags |= GRAB_TEMP_GLOBAL;	    goto setGlobalGrab;	}    } else {	dispPtr->grabFlags |= GRAB_GLOBAL;	setGlobalGrab:	/*	 * Tricky point: must ungrab before grabbing.  This is needed	 * in case there is a button auto-grab already in effect.  If	 * there is, and the mouse has moved to a different window, X	 * won't generate enter and leave events to move the mouse if	 * we grab without ungrabbing.	 */	XUngrabPointer(dispPtr->display, CurrentTime);	serial = NextRequest(dispPtr->display);	/*	 * Another tricky point: there are races with some window	 * managers that can cause grabs to fail because the window	 * manager hasn't released its grab quickly enough.  To work	 * around this problem, retry a few times after AlreadyGrabbed	 * errors to give the grab release enough time to register with	 * the server.	 */	grabResult = 0;			/* Needed only to prevent gcc					 * compiler warnings. */	for (numTries = 0; numTries < 10; numTries++) {	    grabResult = XGrabPointer(dispPtr->display, winPtr->window,		    True, ButtonPressMask|ButtonReleaseMask|ButtonMotionMask		    |PointerMotionMask, GrabModeAsync, GrabModeAsync, None,		    None, CurrentTime);	    if (grabResult != AlreadyGrabbed) {		break;	    }	    Tcl_Sleep(100);	}	if (grabResult != 0) {	    grabError:	    if (grabResult == GrabNotViewable) {		interp->result = "grab failed: window not viewable";	    } else if (grabResult == AlreadyGrabbed) {		goto alreadyGrabbed;	    } else if (grabResult == GrabFrozen) {		interp->result = "grab failed: keyboard or pointer frozen";	    } else if (grabResult == GrabInvalidTime) {		interp->result = "grab failed: invalid time";	    } else {		char msg[100];			sprintf(msg, "grab failed for unknown reason (code %d)",			grabResult);		Tcl_AppendResult(interp, msg, (char *) NULL);	    }	    return TCL_ERROR;	}	grabResult = XGrabKeyboard(dispPtr->display, Tk_WindowId(tkwin),		False, GrabModeAsync, GrabModeAsync, CurrentTime);	if (grabResult != 0) {	    XUngrabPointer(dispPtr->display, CurrentTime);	    goto grabError;	}	/*	 * Eat up any grab-related events generated by the server for the	 * grab.  There are several reasons for doing this:	 *	 * 1. We have to synthesize the events for local grabs anyway, since	 *    the server doesn't participate in them.	 * 2. The server doesn't always generate the right events for global	 *    grabs (e.g. it generates events even if the current window is	 *    in the grab tree, which we don't want).	 * 3. We want all the grab-related events to be processed immediately	 *    (before other events that are already queued); events coming	 *    from the server will be in the wrong place, but events we	 *    synthesize here will go to the front of the queue.	 */	EatGrabEvents(dispPtr, serial);    }    /*     * Synthesize leave events to move the pointer from its current window     * up to the lowest ancestor that it has in common with the grab window.     * However, only do this if the pointer is outside the grab window's     * subtree but inside the grab window's application.     */    if ((dispPtr->serverWinPtr != NULL)	    && (dispPtr->serverWinPtr->mainPtr == winPtr->mainPtr)) {	for (winPtr2 = dispPtr->serverWinPtr; ; winPtr2 = winPtr2->parentPtr) {	    if (winPtr2 == winPtr) {		break;	    }	    if (winPtr2 == NULL) {		MovePointer2(dispPtr->serverWinPtr, winPtr, NotifyGrab, 1, 0);		break;	    }	}    }    QueueGrabWindowChange(dispPtr, winPtr);    return TCL_OK;}/* *---------------------------------------------------------------------- * * Tk_Ungrab -- * *	Releases a grab on the mouse pointer and keyboard, if there *	is one set on the specified window. * * Results: *	None. * * Side effects: *	Pointer and keyboard events will start being delivered to other *	windows again. * *---------------------------------------------------------------------- */voidTk_Ungrab(tkwin)    Tk_Window tkwin;			/* Window whose grab should be					 * released. */{    TkDisplay *dispPtr;    TkWindow *grabWinPtr, *winPtr;    unsigned int serial;    grabWinPtr = (TkWindow *) tkwin;    dispPtr = grabWinPtr->dispPtr;    if (grabWinPtr != dispPtr->eventualGrabWinPtr) {	return;    }    ReleaseButtonGrab(dispPtr);    QueueGrabWindowChange(dispPtr, (TkWindow *) NULL);    if (dispPtr->grabFlags & (GRAB_GLOBAL|GRAB_TEMP_GLOBAL)) {	dispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL);	serial = NextRequest(dispPtr->display);	XUngrabPointer(dispPtr->display, CurrentTime);	XUngrabKeyboard(dispPtr->display, CurrentTime);	EatGrabEvents(dispPtr, serial);    }    /*     * Generate events to move the pointer back to the window where it     * really is.  Some notes:     * 1. As with grabs, only do this if the "real" window is not a     *    descendant of the grab window, since in this case the pointer     *    is already where it's supposed to be.     * 2. If the "real" window is in some other application then don't     *    generate any events at all, since everything's already been     *    reported correctly.     * 3. Only generate enter events.  Don't generate leave events,     *    because we never told the lower-level windows that they     *    had the pointer in the first place.     */    for (winPtr = dispPtr->serverWinPtr; ; winPtr = winPtr->parentPtr) {	if (winPtr == grabWinPtr) {	    break;	}	if (winPtr == NULL) {	    if ((dispPtr->serverWinPtr == NULL) ||		    (dispPtr->serverWinPtr->mainPtr == grabWinPtr->mainPtr)) {		MovePointer2(grabWinPtr, dispPtr->serverWinPtr,			NotifyUngrab, 0, 1);	    }	    break;	}    }}/* *---------------------------------------------------------------------- * * ReleaseButtonGrab -- * *	This procedure is called to release a simulated button grab, if *	there is one in effect.  A button grab is present whenever *	dispPtr->buttonWinPtr is non-NULL or when the GRAB_TEMP_GLOBAL *	flag is set. * * Results: *	None. * * Side effects: *	DispPtr->buttonWinPtr is reset to NULL, and enter and leave *	events are generated if necessary to move the pointer from *	the button grab window to its current window. * *---------------------------------------------------------------------- */static voidReleaseButtonGrab(dispPtr)    register TkDisplay *dispPtr;	/* Display whose button grab is to be					 * released. */{    unsigned int serial;    if (dispPtr->buttonWinPtr != NULL) {	if (dispPtr->buttonWinPtr != dispPtr->serverWinPtr) {	    MovePointer2(dispPtr->buttonWinPtr, dispPtr->serverWinPtr,		    NotifyUngrab, 1, 1);	}	dispPtr->buttonWinPtr = NULL;    }    if (dispPtr->grabFlags & GRAB_TEMP_GLOBAL) {	dispPtr->grabFlags &= ~GRAB_TEMP_GLOBAL;	serial = NextRequest(dispPtr->display);	XUngrabPointer(dispPtr->display, CurrentTime);	XUngrabKeyboard(dispPtr->display, CurrentTime);	EatGrabEvents(dispPtr, serial);    }}/* *---------------------------------------------------------------------- * * TkPointerEvent -- * *	This procedure is called for each pointer-related event, before *	the event has been processed.  It does various things to make *	grabs work correctly. * * Results: *	If the return value is 1 it means the event should be processed *	(event handlers should be invoked).  If the return value is 0 *	it means the event should be ignored in order to make grabs *	work correctly.  In some cases this procedure modifies the event. * * Side effects: *	Grab state information may be updated.  New events may also be *	pushed back onto the event queue to replace or augment the *	one passed in here. * *---------------------------------------------------------------------- */intTkPointerEvent(eventPtr, winPtr)    register XEvent *eventPtr;		/* Pointer to the event. */    TkWindow *winPtr;			/* Tk's information for window					 * where event was reported. */{    register TkWindow *winPtr2;    TkDisplay *dispPtr = winPtr->dispPtr;    unsigned int serial;    int outsideGrabTree = 0;    int ancestorOfGrab = 0;    int appGrabbed = 0;			/* Non-zero means event is being					 * reported to an application that is					 * affected by the grab. */    /*     * Collect information about the grab (if any).     */    switch (TkGrabState(winPtr)) {	case TK_GRAB_IN_TREE:	    appGrabbed = 1;	    break;	case TK_GRAB_ANCESTOR:	    appGrabbed = 1;	    outsideGrabTree = 1;	    ancestorOfGrab = 1;	    break;	case TK_GRAB_EXCLUDED:	    appGrabbed = 1;	    outsideGrabTree = 1;	    break;    }    if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) {	/*	 * Keep track of what window the mouse is *really* over.	 * Any events that we generate have a special send_event value,	 * which is detected below and used to ignore the event for	 * purposes of setting serverWinPtr.	 */	if (eventPtr->xcrossing.send_event != GENERATED_EVENT_MAGIC) {	    if ((eventPtr->type == LeaveNotify) &&		    (winPtr->flags & TK_TOP_LEVEL)) {		dispPtr->serverWinPtr = NULL;	    } else {		dispPtr->serverWinPtr = winPtr;	    }	}	/*	 * When a grab is active, X continues to report enter and leave	 * events for windows outside the tree of the grab window:	 * 1. Detect these events and ignore them except for	 *    windows above the grab window.	 * 2. Allow Enter and Leave events to pass through the	 *    windows above the grab window, but never let them	 *    end up with the pointer *in* one of those windows.	 */	if (dispPtr->grabWinPtr != NULL) {	    if (outsideGrabTree && appGrabbed) {		if (!ancestorOfGrab) {		    return 0;		}		switch (eventPtr->xcrossing.detail) {		    case NotifyInferior:			return 0;		    case NotifyAncestor:			eventPtr->xcrossing.detail = NotifyVirtual;			break;		    case NotifyNonlinear:			eventPtr->xcrossing.detail = NotifyNonlinearVirtual;			break;		}	    }	    /*	     * Make buttons have the same grab-like behavior inside a grab	     * as they do outside a grab:  do this by ignoring enter and	     * leave events except for the window in which the button was	     * pressed.	     */	    if ((dispPtr->buttonWinPtr != NULL)		    && (winPtr != dispPtr->buttonWinPtr)) {		return 0;	    }	}	return 1;    }    if (!appGrabbed) {	return 1;    }    if (eventPtr->type == MotionNotify) {	/*	 * When grabs are active, X reports motion events relative to the	 * window under the pointer.  Instead, it should report the events	 * relative to the window the button went down in, if there is a	 * button down.  Otherwise, if the pointer window is outside the	 * subtree of the grab window, the events should be reported	 * relative to the grab window.  Otherwise, the event should be	 * reported to the pointer window.	 */	winPtr2 = winPtr;	if (dispPtr->buttonWinPtr != NULL) {	    winPtr2 = dispPtr->buttonWinPtr;	} else if (outsideGrabTree || (dispPtr->serverWinPtr == NULL)) {	    winPtr2 = dispPtr->grabWinPtr;	}	if (winPtr2 != winPtr) {	    TkChangeEventWindow(eventPtr, winPtr2);	    Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_HEAD);	    return 0;	}	return 1;    }    /*     * Process ButtonPress and ButtonRelease events:     * 1. Keep track of whether a button is down and what window it     *    went down in.     * 2. If the first button goes down outside the grab tree, pretend     *    it went down in the grab window.  Note: it's important to     *    redirect events to the grab window like this in order to make     *    things like menus work, where button presses outside the     *    grabbed menu need to be seen.  An application can always     *    ignore the events if they occur outside its window.

⌨️ 快捷键说明

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