diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-12-25 17:48:54 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-12-25 17:48:54 (GMT) |
commit | 8eb0f61e2e27ef6594eee8bcf68d574fb087fe66 (patch) | |
tree | fc0f3692516c8c3e8090df20223d342a1b64df93 /tk8.6/unix/tkUnixFocus.c | |
parent | 5f5fd2864a3193a8d5da12fcb92ba7379084c286 (diff) | |
download | blt-8eb0f61e2e27ef6594eee8bcf68d574fb087fe66.zip blt-8eb0f61e2e27ef6594eee8bcf68d574fb087fe66.tar.gz blt-8eb0f61e2e27ef6594eee8bcf68d574fb087fe66.tar.bz2 |
update tcl/tk
Diffstat (limited to 'tk8.6/unix/tkUnixFocus.c')
-rw-r--r-- | tk8.6/unix/tkUnixFocus.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/tk8.6/unix/tkUnixFocus.c b/tk8.6/unix/tkUnixFocus.c new file mode 100644 index 0000000..0767618 --- /dev/null +++ b/tk8.6/unix/tkUnixFocus.c @@ -0,0 +1,149 @@ +/* + * tkUnixFocus.c -- + * + * This file contains platform specific functions 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. + */ + +#include "tkUnixInt.h" + + +/* + *---------------------------------------------------------------------- + * + * TkpChangeFocus -- + * + * This function 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 function 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 function. + * + *---------------------------------------------------------------------- + */ + +int +TkpChangeFocus( + 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, NULL,NULL); + if (winPtr->window == None) { + Tcl_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; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |