summaryrefslogtreecommitdiffstats
path: root/tk8.6/unix/tkUnixFocus.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2018-12-25 17:48:54 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2018-12-25 17:48:54 (GMT)
commit8eb0f61e2e27ef6594eee8bcf68d574fb087fe66 (patch)
treefc0f3692516c8c3e8090df20223d342a1b64df93 /tk8.6/unix/tkUnixFocus.c
parent5f5fd2864a3193a8d5da12fcb92ba7379084c286 (diff)
downloadblt-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.c149
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:
+ */