4 * This file contains platform specific functions that manage focus for
7 * Copyright (c) 1997 Sun Microsystems, Inc.
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 #include "tkUnixInt.h"
17 *----------------------------------------------------------------------
21 * This function is invoked to move the official X focus from one window
25 * The return value is the serial number of the command that changed the
26 * focus. It may be needed by the caller to filter out focus change
27 * events that were queued before the command. If the function doesn't
28 * actually change the focus then it returns 0.
31 * The official X focus window changes; the application's focus window
32 * isn't changed by this function.
34 *----------------------------------------------------------------------
39 TkWindow *winPtr, /* Window that is to receive the X focus. */
40 int force) /* Non-zero means claim the focus even if it
41 * didn't originally belong to topLevelPtr's
44 TkDisplay *dispPtr = winPtr->dispPtr;
45 Tk_ErrorHandler errHandler;
46 Window window, root, parent, *children;
47 unsigned int numChildren, serial;
52 * Don't set the X focus to a window that's marked override-redirect.
53 * This is a hack to avoid problems with menus under olvwm: if we move
54 * the focus then the focus can get lost during keyboard traversal.
55 * Fortunately, we don't really need to move the focus for menus: events
56 * will still find their way to the focus window, and menus aren't
57 * decorated anyway so the window manager doesn't need to hear about the
58 * focus change in order to redecorate the menu.
62 if (winPtr->atts.override_redirect) {
67 * Check to make sure that the focus is still in one of the windows of
68 * this application or one of their descendants. Furthermore, grab the
69 * server to make sure that the focus doesn't change in the middle of this
73 XGrabServer(dispPtr->display);
76 * Find the focus window, then see if it or one of its ancestors is a
77 * window in our application (it's possible that the focus window is
78 * in an embedded application, which may or may not be in the same
82 XGetInputFocus(dispPtr->display, &window, &dummy);
84 winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, window);
85 if ((winPtr2 != NULL) && (winPtr2->mainPtr == winPtr->mainPtr)) {
88 if ((window == PointerRoot) || (window == None)) {
91 XQueryTree(dispPtr->display, window, &root, &parent, &children,
93 if (children != NULL) {
94 XFree((void *) children);
104 * Tell X to change the focus. Ignore errors that occur when changing the
105 * focus: it is still possible that the window we're focussing to could
106 * have gotten unmapped, which will generate an error.
109 errHandler = Tk_CreateErrorHandler(dispPtr->display, -1,-1,-1, NULL,NULL);
110 if (winPtr->window == None) {
111 Tcl_Panic("ChangeXFocus got null X window");
113 XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,
115 Tk_DeleteErrorHandler(errHandler);
118 * Remember the current serial number for the X server and issue a dummy
119 * server request. This marks the position at which we changed the focus,
120 * so we can distinguish FocusIn and FocusOut events on either side of the
124 serial = NextRequest(winPtr->display);
125 XNoOp(winPtr->display);
128 XUngrabServer(dispPtr->display);
131 * After ungrabbing the server, it's important to flush the output
132 * immediately so that the server sees the ungrab command. Otherwise we
133 * might do something else that needs to communicate with the server (such
134 * as invoking a subprocess that needs to do I/O to the screen); if the
135 * ungrab command is still sitting in our output buffer, we could
139 XFlush(dispPtr->display);