📄 tkbind.c
字号:
/* * tkBind.c -- * * This file provides procedures that associate Tcl commands * with X events or sequences of X events. * * Copyright (c) 1989-1994 The Regents of the University of California. * Copyright (c) 1994-1996 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: @(#) tkBind.c 1.133 97/07/01 17:59:53 */#include "tkPort.h"#include "tkInt.h"/* * File structure: * * Structure definitions and static variables. * * Init/Free this package. * * Tcl "bind" command (actually located in tkCmds.c). * "bind" command implementation. * "bind" implementation helpers. * * Tcl "event" command. * "event" command implementation. * "event" implementation helpers. * * Package-specific common helpers. * * Non-package-specific helpers. *//* * The following union is used to hold the detail information from an * XEvent (including Tk's XVirtualEvent extension). */typedef union { KeySym keySym; /* KeySym that corresponds to xkey.keycode. */ int button; /* Button that was pressed (xbutton.button). */ Tk_Uid name; /* Tk_Uid of virtual event. */ ClientData clientData; /* Used when type of Detail is unknown, and to * ensure that all bytes of Detail are initialized * when this structure is used in a hash key. */} Detail;/* * The structure below represents a binding table. A binding table * represents a domain in which event bindings may occur. It includes * a space of objects relative to which events occur (usually windows, * but not always), a history of recent events in the domain, and * a set of mappings that associate particular Tcl commands with sequences * of events in the domain. Multiple binding tables may exist at once, * either because there are multiple applications open, or because there * are multiple domains within an application with separate event * bindings for each (for example, each canvas widget has a separate * binding table for associating events with the items in the canvas). * * Note: it is probably a bad idea to reduce EVENT_BUFFER_SIZE much * below 30. To see this, consider a triple mouse button click while * the Shift key is down (and auto-repeating). There may be as many * as 3 auto-repeat events after each mouse button press or release * (see the first large comment block within Tk_BindEvent for more on * this), for a total of 20 events to cover the three button presses * and two intervening releases. If you reduce EVENT_BUFFER_SIZE too * much, shift multi-clicks will be lost. * */#define EVENT_BUFFER_SIZE 30typedef struct BindingTable { XEvent eventRing[EVENT_BUFFER_SIZE];/* Circular queue of recent events * (higher indices are for more recent * events). */ Detail detailRing[EVENT_BUFFER_SIZE];/* "Detail" information (keySym, * button, Tk_Uid, or 0) for each * entry in eventRing. */ int curEvent; /* Index in eventRing of most recent * event. Newer events have higher * indices. */ Tcl_HashTable patternTable; /* Used to map from an event to a * list of patterns that may match that * event. Keys are PatternTableKey * structs, values are (PatSeq *). */ Tcl_HashTable objectTable; /* Used to map from an object to a * list of patterns associated with * that object. Keys are ClientData, * values are (PatSeq *). */ Tcl_Interp *interp; /* Interpreter in which commands are * executed. */} BindingTable;/* * The following structure represents virtual event table. A virtual event * table provides a way to map from platform-specific physical events such * as button clicks or key presses to virtual events such as <<Paste>>, * <<Close>>, or <<ScrollWindow>>. * * A virtual event is usually never part of the event stream, but instead is * synthesized inline by matching low-level events. However, a virtual * event may be generated by platform-specific code or by Tcl scripts. In * that case, no lookup of the virtual event will need to be done using * this table, because the virtual event is actually in the event stream. */typedef struct VirtualEventTable { Tcl_HashTable patternTable; /* Used to map from a physical event to * a list of patterns that may match that * event. Keys are PatternTableKey * structs, values are (PatSeq *). */ Tcl_HashTable nameTable; /* Used to map a virtual event name to * the array of physical events that can * trigger it. Keys are the Tk_Uid names * of the virtual events, values are * PhysicalsOwned structs. */} VirtualEventTable;/* * The following structure is used as a key in a patternTable for both * binding tables and a virtual event tables. * * In a binding table, the object field corresponds to the binding tag * for the widget whose bindings are being accessed. * * In a virtual event table, the object field is always NULL. Virtual * events are a global definiton and are not tied to a particular * binding tag. * * The same key is used for both types of pattern tables so that the * helper functions that traverse and match patterns will work for both * binding tables and virtual event tables. */typedef struct PatternTableKey { ClientData object; /* For binding table, identifies the binding * tag of the object (or class of objects) * relative to which the event occurred. * For virtual event table, always NULL. */ int type; /* Type of event (from X). */ Detail detail; /* Additional information, such as keysym, * button, Tk_Uid, or 0 if nothing * additional. */} PatternTableKey;/* * The following structure defines a pattern, which is matched against X * events as part of the process of converting X events into Tcl commands. */typedef struct Pattern { int eventType; /* Type of X event, e.g. ButtonPress. */ int needMods; /* Mask of modifiers that must be * present (0 means no modifiers are * required). */ Detail detail; /* Additional information that must * match event. Normally this is 0, * meaning no additional information * must match. For KeyPress and * KeyRelease events, a keySym may * be specified to select a * particular keystroke (0 means any * keystrokes). For button events, * specifies a particular button (0 * means any buttons are OK). For virtual * events, specifies the Tk_Uid of the * virtual event name (never 0). */} Pattern;/* * The following structure defines a pattern sequence, which consists of one * or more patterns. In order to trigger, a pattern sequence must match * the most recent X events (first pattern to most recent event, next * pattern to next event, and so on). It is used as the hash value in a * patternTable for both binding tables and virtual event tables. * * In a binding table, it is the sequence of physical events that make up * a binding for an object. * * In a virtual event table, it is the sequence of physical events that * define a virtual event. * * The same structure is used for both types of pattern tables so that the * helper functions that traverse and match patterns will work for both * binding tables and virtual event tables. */typedef struct PatSeq { int numPats; /* Number of patterns in sequence (usually * 1). */ TkBindEvalProc *eventProc; /* The procedure that will be invoked on * the clientData when this pattern sequence * matches. */ TkBindFreeProc *freeProc; /* The procedure that will be invoked to * release the clientData when this pattern * sequence is freed. */ ClientData clientData; /* Arbitray data passed to eventProc and * freeProc when sequence matches. */ int flags; /* Miscellaneous flag values; see below for * definitions. */ int refCount; /* Number of times that this binding is in * the midst of executing. If greater than 1, * then a recursive invocation is happening. * Only when this is zero can the binding * actually be freed. */ struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences * that have the same initial pattern. NULL * means end of list. */ Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the * initial pattern. This is the head of the * list of which nextSeqPtr forms a part. */ struct VirtualOwners *voPtr;/* In a binding table, always NULL. In a * virtual event table, identifies the array * of virtual events that can be triggered by * this event. */ struct PatSeq *nextObjPtr; /* In a binding table, next in list of all * pattern sequences for the same object (NULL * for end of list). Needed to implement * Tk_DeleteAllBindings. In a virtual event * table, always NULL. */ Pattern pats[1]; /* Array of "numPats" patterns. Only one * element is declared here but in actuality * enough space will be allocated for "numPats" * patterns. To match, pats[0] must match * event n, pats[1] must match event n-1, etc. */} PatSeq;/* * Flag values for PatSeq structures: * * PAT_NEARBY 1 means that all of the events matching * this sequence must occur with nearby X * and Y mouse coordinates and close in time. * This is typically used to restrict multiple * button presses. * MARKED_DELETED 1 means that this binding has been marked as deleted * and removed from the binding table, but its memory * could not be released because it was already queued for * execution. When the binding is actually about to be * executed, this flag will be checked and the binding * skipped if set. */#define PAT_NEARBY 0x1#define MARKED_DELETED 0x2/* * Constants that define how close together two events must be * in milliseconds or pixels to meet the PAT_NEARBY constraint: */#define NEARBY_PIXELS 5#define NEARBY_MS 500/* * The following structure keeps track of all the virtual events that are * associated with a particular physical event. It is pointed to by the * voPtr field in a PatSeq in the patternTable of a virtual event table. */typedef struct VirtualOwners { int numOwners; /* Number of virtual events to trigger. */ Tcl_HashEntry *owners[1]; /* Array of pointers to entries in * nameTable. Enough space will * actually be allocated for numOwners * hash entries. */} VirtualOwners;/* * The following structure is used in the nameTable of a virtual event * table to associate a virtual event with all the physical events that can * trigger it. */typedef struct PhysicalsOwned { int numOwned; /* Number of physical events owned. */ PatSeq *patSeqs[1]; /* Array of pointers to physical event * patterns. Enough space will actually * be allocated to hold numOwned. */} PhysicalsOwned;/* * One of the following structures exists for each interpreter. This * structure keeps track of the current display and screen in the * interpreter, so that a script can be invoked whenever the display/screen * changes (the script does things like point tkPriv at a display-specific * structure). */typedef struct { TkDisplay *curDispPtr; /* Display for last binding command invoked * in this application. */ int curScreenIndex; /* Index of screen for last binding command. */ int bindingDepth; /* Number of active instances of Tk_BindEvent * in this application. */} ScreenInfo;/* * The following structure is used to keep track of all the C bindings that * are awaiting invocation and whether the window they refer to has been * destroyed. If the window is destroyed, then all pending callbacks for * that window will be cancelled. The Tcl bindings will still all be * invoked, however. */typedef struct PendingBinding { struct PendingBinding *nextPtr; /* Next in chain of pending bindings, in * case a recursive binding evaluation is in * progress. */ Tk_Window tkwin; /* The window that the following bindings * depend upon. */ int deleted; /* Set to non-zero by window cleanup code * if tkwin is deleted. */ PatSeq *matchArray[5]; /* Array of pending C bindings. The actual * size of this depends on how many C bindings * matched the event passed to Tk_BindEvent. * THIS FIELD MUST BE THE LAST IN THE * STRUCTURE. */} PendingBinding;/* * The following structure keeps track of all the information local to * the binding package on a per interpreter basis. */typedef struct BindInfo { VirtualEventTable virtualEventTable; /* The virtual events that exist in this * interpreter. */ ScreenInfo screenInfo; /* Keeps track of the current display and * screen, so it can be restored after * a binding has executed. */ PendingBinding *pendingList;/* The list of pending C bindings, kept in * case a C or Tcl binding causes the target * window to be deleted. */} BindInfo; /* * In X11R4 and earlier versions, XStringToKeysym is ridiculously * slow. The data structure and hash table below, along with the * code that uses them, implement a fast mapping from strings to * keysyms. In X11R5 and later releases XStringToKeysym is plenty * fast so this stuff isn't needed. The #define REDO_KEYSYM_LOOKUP * is normally undefined, so that XStringToKeysym gets used. It * can be set in the Makefile to enable the use of the hash table * below. */#ifdef REDO_KEYSYM_LOOKUPtypedef struct { char *name; /* Name of keysym. */ KeySym value; /* Numeric identifier for keysym. */} KeySymInfo;static KeySymInfo keyArray[] = {#ifndef lint#include "ks_names.h"#endif {(char *) NULL, 0}};static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */#endif /* REDO_KEYSYM_LOOKUP *//* * Set to non-zero when the package-wide static variables have been * initialized. */static int initialized = 0;/* * A hash table is kept to map from the string names of event * modifiers to information about those modifiers. The structure * for storing this information, and the hash table built at * initialization time, are defined below. */typedef struct { char *name; /* Name of modifier. */ int mask; /* Button/modifier mask value, * such as Button1Mask. */ int flags; /* Various flags; see below for * definitions. */} ModInfo;/* * Flags for ModInfo structures: * * DOUBLE - Non-zero means duplicate this event, * e.g. for double-clicks. * TRIPLE - Non-zero means triplicate this event, * e.g. for triple-clicks. */#define DOUBLE 1#define TRIPLE 2/* * The following special modifier mask bits are defined, to indicate * logical modifiers such as Meta and Alt that may float among the * actual modifier bits. */#define META_MASK (AnyModifier<<1)#define ALT_MASK (AnyModifier<<2)static ModInfo modArray[] = { {"Control", ControlMask, 0}, {"Shift", ShiftMask, 0},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -