📄 tkfocus.c
字号:
* this toplevel. We take the focus implicitly (probably no * window manager) */ if ((eventPtr->xfocus.detail == NotifyVirtual) || (eventPtr->xfocus.detail == NotifyNonlinearVirtual) || (eventPtr->xfocus.detail == NotifyPointerRoot) || (eventPtr->xfocus.detail == NotifyInferior)) { return retValue; } } else if (eventPtr->type == FocusOut) { /* * Skip FocusOut events that cause confusion. * NotifyPointer - the pointer is in us or a child, and we are losing * focus because of an XSetInputFocus. Other focus events * will set our state properly. * NotifyPointerRoot - should never happen because this is sent * to the root window. * NotifyInferior - focus leaving us for an embedded child. We * retain a notion of focus when an embedded child has focus. * * Interesting events are: * NotifyAncestor - focus is going to root. * NotifyNonlinear - focus is going to another branch, probably * another toplevel. * NotifyVirtual, NotifyNonlinearVirtual - focus is passing through, * and we need to make sure we track this. */ if ((eventPtr->xfocus.detail == NotifyPointer) || (eventPtr->xfocus.detail == NotifyPointerRoot) || (eventPtr->xfocus.detail == NotifyInferior)) { return retValue; } } else { retValue = 1; if (eventPtr->xcrossing.detail == NotifyInferior) { return retValue; } } /* * If winPtr isn't a top-level window than just ignore the event. */ winPtr = TkWmFocusToplevel(winPtr); if (winPtr == NULL) { return retValue; } /* * If there is a grab in effect and this window is outside the * grabbed tree, then ignore the event. */ if (TkGrabState(winPtr) == TK_GRAB_EXCLUDED) { return retValue; } /* * It is possible that there were outstanding FocusIn and FocusOut * events on their way to us at the time the focus was changed * internally with the "focus" command. If so, these events could * potentially cause us to lose the focus (switch it to the window * of the last FocusIn event) even though the focus change occurred * after those events. The following code detects this and ignores * the stale events. * * Note: the focusSerial is only generated by TkpChangeFocus, * whereas in Tk 4.2 there was always a nop marker generated. */ delta = eventPtr->xfocus.serial - displayFocusPtr->focusSerial; if (delta < 0) { return retValue; } /* * Find the ToplevelFocusInfo structure for the window, and make a new one * if there isn't one already. */ for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; tlFocusPtr = tlFocusPtr->nextPtr) { if (tlFocusPtr->topLevelPtr == winPtr) { break; } } if (tlFocusPtr == NULL) { tlFocusPtr = (ToplevelFocusInfo *) ckalloc(sizeof(ToplevelFocusInfo)); tlFocusPtr->topLevelPtr = tlFocusPtr->focusWinPtr = winPtr; tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr; winPtr->mainPtr->tlFocusPtr = tlFocusPtr; } newFocusPtr = tlFocusPtr->focusWinPtr; if (eventPtr->type == FocusIn) { GenerateFocusEvents(displayFocusPtr->focusWinPtr, newFocusPtr); displayFocusPtr->focusWinPtr = newFocusPtr; dispPtr->focusPtr = newFocusPtr; /* * NotifyPointer gets set when the focus has been set to the root window * but we have the pointer. We'll treat this like an implicit * focus in event so that upon Leave events we release focus. */ if (!(winPtr->flags & TK_EMBEDDED)) { if (eventPtr->xfocus.detail == NotifyPointer) { dispPtr->implicitWinPtr = winPtr; } else { dispPtr->implicitWinPtr = NULL; } } } else if (eventPtr->type == FocusOut) { GenerateFocusEvents(displayFocusPtr->focusWinPtr, (TkWindow *) NULL); /* * Reset dispPtr->focusPtr, but only if it currently is the same * as this application's focusWinPtr: this check is needed to * handle embedded applications in the same process. */ if (dispPtr->focusPtr == displayFocusPtr->focusWinPtr) { dispPtr->focusPtr = NULL; } displayFocusPtr->focusWinPtr = NULL; } else if (eventPtr->type == EnterNotify) { /* * If there is no window manager, or if the window manager isn't * moving the focus around (e.g. the disgusting "NoTitleFocus" * option has been selected in twm), then we won't get FocusIn * or FocusOut events. Instead, the "focus" field will be set * in an Enter event to indicate that we've already got the focus * when the mouse enters the window (even though we didn't get * a FocusIn event). Watch for this and grab the focus when it * happens. Note: if this is an embedded application then don't * accept the focus implicitly like this; the container * application will give us the focus explicitly if it wants us * to have it. */ if (eventPtr->xcrossing.focus && (displayFocusPtr->focusWinPtr == NULL) && !(winPtr->flags & TK_EMBEDDED)) { if (tclFocusDebug) { printf("Focussed implicitly on %s\n", newFocusPtr->pathName); } GenerateFocusEvents(displayFocusPtr->focusWinPtr, newFocusPtr); displayFocusPtr->focusWinPtr = newFocusPtr; dispPtr->implicitWinPtr = winPtr; dispPtr->focusPtr = newFocusPtr; } } else if (eventPtr->type == LeaveNotify) { /* * If the pointer just left a window for which we automatically * claimed the focus on enter, move the focus back to the root * window, where it was before we claimed it above. Note: * dispPtr->implicitWinPtr may not be the same as * displayFocusPtr->focusWinPtr (e.g. because the "focus" * command was used to redirect the focus after it arrived at * dispPtr->implicitWinPtr)!! In addition, we generate events * because the window manager won't give us a FocusOut event when * we focus on the root. */ if ((dispPtr->implicitWinPtr != NULL) && !(winPtr->flags & TK_EMBEDDED)) { if (tclFocusDebug) { printf("Defocussed implicit Async\n"); } GenerateFocusEvents(displayFocusPtr->focusWinPtr, (TkWindow *) NULL); XSetInputFocus(dispPtr->display, PointerRoot, RevertToPointerRoot, CurrentTime); displayFocusPtr->focusWinPtr = NULL; dispPtr->implicitWinPtr = NULL; } } return retValue;}/* *---------------------------------------------------------------------- * * SetFocus -- * * This procedure is invoked to change the focus window for a * given display in a given application. * * Results: * None. * * Side effects: * Event handlers may be invoked to process the change of * focus. * *---------------------------------------------------------------------- */static voidSetFocus(winPtr, force) TkWindow *winPtr; /* Window that is to be the new focus for * its display and application. */ int force; /* If non-zero, set the X focus to this * window even if the application doesn't * currently have the X focus. */{ ToplevelFocusInfo *tlFocusPtr; DisplayFocusInfo *displayFocusPtr; TkWindow *topLevelPtr; int allMapped, serial; displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); if (winPtr == displayFocusPtr->focusWinPtr) { return; } /* * Find the top-level window for winPtr, then find (or create) * a record for the top-level. Also see whether winPtr and all its * ancestors are mapped. */ allMapped = 1; for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) { if (topLevelPtr == NULL) { /* * The window is being deleted. No point in worrying about * giving it the focus. */ return; } if (!(topLevelPtr->flags & TK_MAPPED)) { allMapped = 0; } if (topLevelPtr->flags & TK_TOP_LEVEL) { break; } } /* * If the new focus window isn't mapped, then we can't focus on it * (X will generate an error, for example). Instead, create an * event handler that will set the focus to this window once it gets * mapped. At the same time, delete any old handler that might be * around; it's no longer relevant. */ if (displayFocusPtr->focusOnMapPtr != NULL) { Tk_DeleteEventHandler( (Tk_Window) displayFocusPtr->focusOnMapPtr, StructureNotifyMask, FocusMapProc, (ClientData) displayFocusPtr->focusOnMapPtr); displayFocusPtr->focusOnMapPtr = NULL; } if (!allMapped) { Tk_CreateEventHandler((Tk_Window) winPtr, VisibilityChangeMask, FocusMapProc, (ClientData) winPtr); displayFocusPtr->focusOnMapPtr = winPtr; displayFocusPtr->forceFocus = force; return; } for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; tlFocusPtr = tlFocusPtr->nextPtr) { if (tlFocusPtr->topLevelPtr == topLevelPtr) { break; } } if (tlFocusPtr == NULL) { tlFocusPtr = (ToplevelFocusInfo *) ckalloc(sizeof(ToplevelFocusInfo)); tlFocusPtr->topLevelPtr = topLevelPtr; tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr; winPtr->mainPtr->tlFocusPtr = tlFocusPtr; } tlFocusPtr->focusWinPtr = winPtr; /* * Reset the window system's focus window and generate focus events, * with two special cases: * * 1. If the application is embedded and doesn't currently have the * focus, don't set the focus directly. Instead, see if the * embedding code can claim the focus from the enclosing * container. * 2. Otherwise, if the application doesn't currently have the * focus, don't change the window system's focus unless it was * already in this application or "force" was specified. */ /* since the tcl/tk code doesn't yet set the focus for embedded applications * we'll have to set it manually in the application code.....so we need to bypass * this check on Windows. KH */#ifndef WIN32 if ((topLevelPtr->flags & TK_EMBEDDED) && (displayFocusPtr->focusWinPtr == NULL)) { TkpClaimFocus(topLevelPtr, force); } else #endif if ((displayFocusPtr->focusWinPtr != NULL) || force) { /* * Generate events to shift focus between Tk windows. * We do this regardless of what TkpChangeFocus does with * the real X focus so that Tk widgets track focus commands * when there is no window manager. GenerateFocusEvents will * set up a serial number marker so we discard focus events * that are triggered by the ChangeFocus. */ serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force); if (serial != 0) { displayFocusPtr->focusSerial = serial; } GenerateFocusEvents(displayFocusPtr->focusWinPtr, winPtr); displayFocusPtr->focusWinPtr = winPtr; winPtr->dispPtr->focusPtr = winPtr; }}/* *---------------------------------------------------------------------- * * TkGetFocusWin -- * * Given a window, this procedure returns the current focus * window for its application and display. * * Results: * The return value is a pointer to the window that currently * has the input focus for the specified application and * display, or NULL if none.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -