tkUnixFocus.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
- /*
- * tkUnixFocus.c --
- *
- * This file contains platform specific procedures that manage
- * focus for Tk.
- *
- * Copyright (c) 1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * RCS: @(#) $Id: tkUnixFocus.c,v 1.3 1999/04/16 01:51:46 stanton Exp $
- */
- #include "tkInt.h"
- #include "tkPort.h"
- #include "tkUnixInt.h"
- /*
- *----------------------------------------------------------------------
- *
- * TkpChangeFocus --
- *
- * This procedure is invoked to move the official X focus from
- * one window to another.
- *
- * Results:
- * The return value is the serial number of the command that
- * changed the focus. It may be needed by the caller to filter
- * out focus change events that were queued before the command.
- * If the procedure doesn't actually change the focus then
- * it returns 0.
- *
- * Side effects:
- * The official X focus window changes; the application's focus
- * window isn't changed by this procedure.
- *
- *----------------------------------------------------------------------
- */
- int
- TkpChangeFocus(winPtr, force)
- TkWindow *winPtr; /* Window that is to receive the X focus. */
- int force; /* Non-zero means claim the focus even
- * if it didn't originally belong to
- * topLevelPtr's application. */
- {
- TkDisplay *dispPtr = winPtr->dispPtr;
- Tk_ErrorHandler errHandler;
- Window window, root, parent, *children;
- unsigned int numChildren, serial;
- TkWindow *winPtr2;
- int dummy;
- /*
- * Don't set the X focus to a window that's marked
- * override-redirect. This is a hack to avoid problems with menus
- * under olvwm: if we move the focus then the focus can get lost
- * during keyboard traversal. Fortunately, we don't really need to
- * move the focus for menus: events will still find their way to the
- * focus window, and menus aren't decorated anyway so the window
- * manager doesn't need to hear about the focus change in order to
- * redecorate the menu.
- */
- serial = 0;
- if (winPtr->atts.override_redirect) {
- return serial;
- }
- /*
- * Check to make sure that the focus is still in one of the windows
- * of this application or one of their descendants. Furthermore,
- * grab the server to make sure that the focus doesn't change in the
- * middle of this operation.
- */
- XGrabServer(dispPtr->display);
- if (!force) {
- /*
- * Find the focus window, then see if it or one of its ancestors
- * is a window in our application (it's possible that the focus
- * window is in an embedded application, which may or may not be
- * in the same process.
- */
- XGetInputFocus(dispPtr->display, &window, &dummy);
- while (1) {
- winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, window);
- if ((winPtr2 != NULL) && (winPtr2->mainPtr == winPtr->mainPtr)) {
- break;
- }
- if ((window == PointerRoot) || (window == None)) {
- goto done;
- }
- XQueryTree(dispPtr->display, window, &root, &parent, &children,
- &numChildren);
- if (children != NULL) {
- XFree((void *) children);
- }
- if (parent == root) {
- goto done;
- }
- window = parent;
- }
- }
- /*
- * Tell X to change the focus. Ignore errors that occur when changing
- * the focus: it is still possible that the window we're focussing
- * to could have gotten unmapped, which will generate an error.
- */
- errHandler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1,
- (Tk_ErrorProc *) NULL, (ClientData) NULL);
- if (winPtr->window == None) {
- panic("ChangeXFocus got null X window");
- }
- XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,
- CurrentTime);
- Tk_DeleteErrorHandler(errHandler);
- /*
- * Remember the current serial number for the X server and issue
- * a dummy server request. This marks the position at which we
- * changed the focus, so we can distinguish FocusIn and FocusOut
- * events on either side of the mark.
- */
- serial = NextRequest(winPtr->display);
- XNoOp(winPtr->display);
- done:
- XUngrabServer(dispPtr->display);
- /*
- * After ungrabbing the server, it's important to flush the output
- * immediately so that the server sees the ungrab command. Otherwise
- * we might do something else that needs to communicate with the
- * server (such as invoking a subprocess that needs to do I/O to
- * the screen); if the ungrab command is still sitting in our
- * output buffer, we could deadlock.
- */
- XFlush(dispPtr->display);
- return serial;
- }