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

📄 tkgrab.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  * tkGrab.c -- * *	This file provides procedures that implement grabs for Tk. * * Copyright (c) 1992-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: @(#) tkGrab.c 1.52 97/03/21 11:14:34 */#include "tkPort.h"#include "tkInt.h"/* * The grab state machine has four states: ungrabbed, button pressed, * grabbed, and button pressed while grabbed.  In addition, there are * three pieces of grab state information: the current grab window, * the current restrict window, and whether the mouse is captured. * * The current grab window specifies the point in the Tk window * heirarchy above which pointer events will not be reported.  Any * window within the subtree below the grab window will continue to * receive events as normal.  Events outside of the grab tree will be * reported to the grab window. * * If the current restrict window is set, then all pointer events will * be reported only to the restrict window.  The restrict window is * normally set during an automatic button grab. * * The mouse capture state specifies whether the window system will * report mouse events outside of any Tk toplevels.  This is set * during a global grab or an automatic button grab. * * The transitions between different states is given in the following * table: *  * Event\State	U	B	G	GB * -----------	--	--	--	-- * FirstPress	B	B	GB	GB * Press	B	B	G	GB * Release	U	B	G	GB * LastRelease	U	U	G	G * Grab		G	G	G	G * Ungrab	U	B	U	U * * Note: U=Ungrabbed, B=Button, G=Grabbed, GB=Grab and Button * * In addition, the following conditions are always true: * * State\Variable	Grab	     Restrict	     Capture * --------------	----	     --------	     ------- * Ungrabbed		 0		0		0 * Button		 0		1		1 * Grabbed		 1		0		b/g * Grab and Button	 1		1		1 * * Note: 0 means variable is set to NULL, 1 means variable is set to * some window, b/g means the variable is set to a window if a button * is currently down or a global grab is in effect. * * The final complication to all of this is enter and leave events. * In order to correctly handle all of the various cases, Tk cannot * rely on X enter/leave events in all situations.  The following * describes the correct sequence of enter and leave events that * should be observed by Tk scripts: * * Event(state)		Enter/Leave From -> To * ------------		---------------------- * LastRelease(B | GB): restrict window -> anc(grab window, event window) * Grab(U | B): 	event window -> anc(grab window, event window) * Grab(G):		anc(old grab window, event window) -> * 				anc(new grab window, event window) * Grab(GB):		restrict window -> anc(new grab window, event window) * Ungrab(G):		anc(grab window, event window) -> event window * Ungrab(GB):		restrict window -> event window * * Note: anc(x,y) returns the least ancestor of y that is in the tree * of x, terminating at toplevels. *//* * The following structure is used to pass information to  * GrabRestrictProc from EatGrabEvents. */typedef struct {    Display *display;		/* Display from which to discard events. */    unsigned int serial;	/* Serial number with which to compare. */} GrabInfo;/* * Bit definitions for grabFlags field of TkDisplay structures: * * GRAB_GLOBAL			1 means this is a global grab (we grabbed via *				the server so all applications are locked out). *				0 means this is a local grab that affects *				only this application. * GRAB_TEMP_GLOBAL		1 means we've temporarily grabbed via the *				server because a button is down and we want *				to make sure that we get the button-up *				event.  The grab will be released when the *				last mouse button goes up. */#define GRAB_GLOBAL		1#define GRAB_TEMP_GLOBAL	4/* * The following structure is a Tcl_Event that triggers a change in * the grabWinPtr field of a display.  This event guarantees that * the change occurs in the proper order relative to enter and leave * events. */typedef struct NewGrabWinEvent {    Tcl_Event header;		/* Standard information for all Tcl events. */    TkDisplay *dispPtr;		/* Display whose grab window is to change. */    Window grabWindow;		/* New grab window for display.  This is				 * recorded instead of a (TkWindow *) because				 * it will allow us to detect cases where				 * the window is destroyed before this event				 * is processed. */} NewGrabWinEvent;/* * The following magic value is stored in the "send_event" field of * EnterNotify and LeaveNotify events that are generated in this * file.  This allows us to separate "real" events coming from the * server from those that we generated. */#define GENERATED_EVENT_MAGIC ((Bool) 0x147321ac)/* * Mask that selects any of the state bits corresponding to buttons, * plus masks that select individual buttons' bits: */#define ALL_BUTTONS \	(Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)static unsigned int buttonStates[] = {    Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask};/* * Forward declarations for procedures declared later in this file: */static void		EatGrabEvents _ANSI_ARGS_((TkDisplay *dispPtr,			    unsigned int serial));static TkWindow *	FindCommonAncestor _ANSI_ARGS_((TkWindow *winPtr1,			    TkWindow *winPtr2, int *countPtr1,			    int *countPtr2));static Tk_RestrictAction GrabRestrictProc _ANSI_ARGS_((ClientData arg,			    XEvent *eventPtr));static int		GrabWinEventProc _ANSI_ARGS_((Tcl_Event *evPtr,			    int flags));static void		MovePointer2 _ANSI_ARGS_((TkWindow *sourcePtr,			    TkWindow *destPtr, int mode, int leaveEvents,			    int EnterEvents));static void		QueueGrabWindowChange _ANSI_ARGS_((TkDisplay *dispPtr,			    TkWindow *grabWinPtr));static void		ReleaseButtonGrab _ANSI_ARGS_((TkDisplay *dispPtr));/* *---------------------------------------------------------------------- * * Tk_GrabCmd -- * *	This procedure is invoked to process the "grab" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */	/* ARGSUSED */intTk_GrabCmd(clientData, interp, argc, argv)    ClientData clientData;	/* Main window associated with				 * interpreter. */    Tcl_Interp *interp;		/* Current interpreter. */    int argc;			/* Number of arguments. */    char **argv;		/* Argument strings. */{    int globalGrab, c;    Tk_Window tkwin;    TkDisplay *dispPtr;    size_t length;    if (argc < 2) {	badArgs:	Tcl_AppendResult(interp, "wrong # args: should be \"",		argv[0], " ?-global? window\" or \"", argv[0],		" option ?arg arg ...?\"", (char *) NULL);	return TCL_ERROR;    }    c = argv[1][0];    length = strlen(argv[1]);    if (c == '.') {	if (argc != 2) {	    goto badArgs;	}	tkwin = Tk_NameToWindow(interp, argv[1], (Tk_Window) clientData);	if (tkwin == NULL) {	    return TCL_ERROR;	}	return Tk_Grab(interp, tkwin, 0);    } else if ((c == '-') && (strncmp(argv[1], "-global", length) == 0)	    && (length >= 2)) {	if (argc != 3) {	    goto badArgs;	}	tkwin = Tk_NameToWindow(interp, argv[2], (Tk_Window) clientData);	if (tkwin == NULL) {	    return TCL_ERROR;	}	return Tk_Grab(interp, tkwin, 1);    } else if ((c == 'c') && (strncmp(argv[1], "current", length) == 0)) {	if (argc > 3) {	    Tcl_AppendResult(interp, "wrong # args: should be \"",		    argv[0], " current ?window?\"", (char *) NULL);	    return TCL_ERROR;	}	if (argc == 3) {	    tkwin = Tk_NameToWindow(interp, argv[2], (Tk_Window) clientData);	    if (tkwin == NULL) {		return TCL_ERROR;	    }	    dispPtr = ((TkWindow *) tkwin)->dispPtr;	    if (dispPtr->eventualGrabWinPtr != NULL) {		interp->result = dispPtr->eventualGrabWinPtr->pathName;	    }	} else {	    for (dispPtr = tkDisplayList; dispPtr != NULL;		    dispPtr = dispPtr->nextPtr) {		if (dispPtr->eventualGrabWinPtr != NULL) {		    Tcl_AppendElement(interp,			    dispPtr->eventualGrabWinPtr->pathName);		}	    }	}	return TCL_OK;    } else if ((c == 'r') && (strncmp(argv[1], "release", length) == 0)) {	if (argc != 3) {	    Tcl_AppendResult(interp, "wrong # args: should be \"",		    argv[0], " release window\"", (char *) NULL);	    return TCL_ERROR;	}	tkwin = Tk_NameToWindow(interp, argv[2], (Tk_Window) clientData);	if (tkwin == NULL) {	    Tcl_ResetResult(interp);	} else {	    Tk_Ungrab(tkwin);	}    } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)	    && (length >= 2)) {	if ((argc != 3) && (argc != 4)) {	    Tcl_AppendResult(interp, "wrong # args: should be \"",		    argv[0], " set ?-global? window\"", (char *) NULL);	    return TCL_ERROR;	}	if (argc == 3) {	    globalGrab = 0;	    tkwin = Tk_NameToWindow(interp, argv[2], (Tk_Window) clientData);	} else {	    globalGrab = 1;	    length = strlen(argv[2]);	    if ((strncmp(argv[2], "-global", length) != 0) || (length < 2)) {		Tcl_AppendResult(interp, "bad argument \"", argv[2],			"\": must be \"", argv[0], " set ?-global? window\"",			(char *) NULL);		return TCL_ERROR;	    }	    tkwin = Tk_NameToWindow(interp, argv[3], (Tk_Window) clientData);	}	if (tkwin == NULL) {	    return TCL_ERROR;	}	return Tk_Grab(interp, tkwin, globalGrab);    } else if ((c == 's') && (strncmp(argv[1], "status", length) == 0)	    && (length >= 2)) {	TkWindow *winPtr;	if (argc != 3) {	    Tcl_AppendResult(interp, "wrong # args: should be \"",		    argv[0], " status window\"", (char *) NULL);	    return TCL_ERROR;	}	winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2],		(Tk_Window) clientData);	if (winPtr == NULL) {	    return TCL_ERROR;	}	dispPtr = winPtr->dispPtr;	if (dispPtr->eventualGrabWinPtr != winPtr) {	    interp->result = "none";	} else if (dispPtr->grabFlags & GRAB_GLOBAL) {	    interp->result = "global";	} else {	    interp->result = "local";	}    } else {	Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],		"\": must be current, release, set, or status",		(char *) NULL);	return TCL_ERROR;    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * Tk_Grab -- * *	Grabs the pointer and keyboard, so that mouse-related events are *	only reported relative to a given window and its descendants. * * Results: *	A standard Tcl result is returned.  TCL_OK is the normal return *	value;  if the grab could not be set then TCL_ERROR is returned *	and interp->result will hold an error message. * * Side effects: *	Once this call completes successfully, no window outside the *	tree rooted at tkwin will receive pointer- or keyboard-related *	events until the next call to Tk_Ungrab.  If a previous grab was *	in effect within this application, then it is replaced with a new *	one. * *---------------------------------------------------------------------- */intTk_Grab(interp, tkwin, grabGlobal)    Tcl_Interp *interp;			/* Used for error reporting. */    Tk_Window tkwin;			/* Window on whose behalf the pointer					 * is to be grabbed. */    int grabGlobal;			/* Non-zero means issue a grab to the					 * server so that no other application					 * gets mouse or keyboard events.					 * Zero means the grab only applies					 * within this application. */{    int grabResult, numTries;    TkWindow *winPtr = (TkWindow *) tkwin;    TkDisplay *dispPtr = winPtr->dispPtr;    TkWindow *winPtr2;    unsigned int serial;    ReleaseButtonGrab(dispPtr);    if (dispPtr->eventualGrabWinPtr != NULL) {	if ((dispPtr->eventualGrabWinPtr == winPtr)		&& (grabGlobal == ((dispPtr->grabFlags & GRAB_GLOBAL) != 0))) {	    return TCL_OK;	}	if (dispPtr->eventualGrabWinPtr->mainPtr != winPtr->mainPtr) {	    alreadyGrabbed:	    interp->result = "grab failed: another application has grab";	    return TCL_ERROR;	}	Tk_Ungrab((Tk_Window) dispPtr->eventualGrabWinPtr);    }    Tk_MakeWindowExist(tkwin);    if (!grabGlobal) {	Window dummy1, dummy2;	int dummy3, dummy4, dummy5, dummy6;	unsigned int state;	/*	 * Local grab.  However, if any mouse buttons are down, turn	 * it into a global grab temporarily, until the last button	 * goes up.  This does two things: (a) it makes sure that we

⌨️ 快捷键说明

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