tkUnixFocus.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkUnixFocus.c --
  3.  *
  4.  * This file contains platform specific procedures that manage
  5.  * focus for Tk.
  6.  *
  7.  * Copyright (c) 1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkUnixFocus.c,v 1.3 1999/04/16 01:51:46 stanton Exp $
  13.  */
  14. #include "tkInt.h"
  15. #include "tkPort.h"
  16. #include "tkUnixInt.h"
  17. /*
  18.  *----------------------------------------------------------------------
  19.  *
  20.  * TkpChangeFocus --
  21.  *
  22.  * This procedure is invoked to move the official X focus from
  23.  * one window to another.
  24.  *
  25.  * Results:
  26.  * The return value is the serial number of the command that
  27.  * changed the focus.  It may be needed by the caller to filter
  28.  * out focus change events that were queued before the command.
  29.  * If the procedure doesn't actually change the focus then
  30.  * it returns 0.
  31.  *
  32.  * Side effects:
  33.  * The official X focus window changes;  the application's focus
  34.  * window isn't changed by this procedure.
  35.  *
  36.  *----------------------------------------------------------------------
  37.  */
  38. int
  39. TkpChangeFocus(winPtr, force)
  40.     TkWindow *winPtr; /* Window that is to receive the X focus. */
  41.     int force; /* Non-zero means claim the focus even
  42.  * if it didn't originally belong to
  43.  * topLevelPtr's application. */
  44. {
  45.     TkDisplay *dispPtr = winPtr->dispPtr;
  46.     Tk_ErrorHandler errHandler;
  47.     Window window, root, parent, *children; 
  48.     unsigned int numChildren, serial; 
  49.     TkWindow *winPtr2;
  50.     int dummy;
  51.     /*
  52.      * Don't set the X focus to a window that's marked
  53.      * override-redirect.  This is a hack to avoid problems with menus
  54.      * under olvwm: if we move the focus then the focus can get lost
  55.      * during keyboard traversal.  Fortunately, we don't really need to
  56.      * move the focus for menus: events will still find their way to the
  57.      * focus window, and menus aren't decorated anyway so the window
  58.      * manager doesn't need to hear about the focus change in order to
  59.      * redecorate the menu.
  60.      */
  61.     serial = 0;
  62.     if (winPtr->atts.override_redirect) {
  63. return serial;
  64.     }
  65.     /*
  66.      * Check to make sure that the focus is still in one of the windows
  67.      * of this application or one of their descendants.  Furthermore,
  68.      * grab the server to make sure that the focus doesn't change in the
  69.      * middle of this operation.
  70.      */
  71.     XGrabServer(dispPtr->display);
  72.     if (!force) {
  73. /*
  74.  * Find the focus window, then see if it or one of its ancestors
  75.  * is a window in our application (it's possible that the focus
  76.  * window is in an embedded application, which may or may not be
  77.  * in the same process.
  78.  */
  79. XGetInputFocus(dispPtr->display, &window, &dummy);
  80. while (1) {
  81.     winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, window);
  82.     if ((winPtr2 != NULL) && (winPtr2->mainPtr == winPtr->mainPtr)) {
  83. break;
  84.     }
  85.     if ((window == PointerRoot) || (window == None)) {
  86. goto done;
  87.     }
  88.     XQueryTree(dispPtr->display, window, &root, &parent, &children,
  89.     &numChildren);
  90.     if (children != NULL) {
  91. XFree((void *) children);
  92.     }
  93.     if (parent == root) {
  94. goto done;
  95.     }
  96.     window = parent;
  97. }
  98.     }
  99.     /*
  100.      * Tell X to change the focus.  Ignore errors that occur when changing
  101.      * the focus:  it is still possible that the window we're focussing
  102.      * to could have gotten unmapped, which will generate an error.
  103.      */
  104.     errHandler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1,
  105.     (Tk_ErrorProc *) NULL, (ClientData) NULL);
  106.     if (winPtr->window == None) {
  107. panic("ChangeXFocus got null X window");
  108.     }
  109.     XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,
  110.     CurrentTime);
  111.     Tk_DeleteErrorHandler(errHandler);
  112.     /*
  113.      * Remember the current serial number for the X server and issue
  114.      * a dummy server request.  This marks the position at which we
  115.      * changed the focus, so we can distinguish FocusIn and FocusOut
  116.      * events on either side of the mark.
  117.      */
  118.     serial = NextRequest(winPtr->display);
  119.     XNoOp(winPtr->display);
  120.     done:
  121.     XUngrabServer(dispPtr->display);
  122.     /*
  123.      * After ungrabbing the server, it's important to flush the output
  124.      * immediately so that the server sees the ungrab command.  Otherwise
  125.      * we might do something else that needs to communicate with the
  126.      * server (such as invoking a subprocess that needs to do I/O to
  127.      * the screen); if the ungrab command is still sitting in our
  128.      * output buffer, we could deadlock.
  129.      */
  130.     XFlush(dispPtr->display);
  131.     return serial;
  132. }