pms@ARBORTEXT.COM (Pat Sherry) (08/17/90)
The attached test program shows what I think is a bug in XtSetKeyboardFocus(). It seems to me that the call XtSetKeyboardFocus(widget, None) does not clear the cached per display focus widget with the result that events are still delivered to the widget which was set in a previous call to XtSetKeyboardFocus(). Run this test program and type some characters with the pointer positioned anywhere in the box but outside of the text widget. The keypress events are delivered to the text widget as expected. Press the Escape key which is supposed to revert the focus from the text widget to the box. Subsequent keypresses should not be delivered to the text widget but should result in the message "KeyPress in box" printed on stderr. Instead the keypress events still go to the text widget. If you move the pointer out of the application shell and back into the box, then the cached focus widget is cleared and events will be dispatched to the box. If I apply the following patch to $(TOP)/lib/Xt/Keyboard.c (X11R4, patch level 14), then the program works as I would expect. Is this really a bug or am I misinterpreting the documentation? Pat Sherry pms@arbortext.com ArborText, Inc My patch to XtSetKeyboardFocus(): *** /usr/src/local/X11R4/src/mit/lib/Xt/Keyboard.c Mon Apr 23 23:26:04 1990 --- Keyboard.c Thu Aug 16 16:42:35 1990 *************** *** 770,775 **** --- 770,777 ---- _XtHandleFocus, (XtPointer)pwi); pwi->haveFocus = FALSE; } + if (pdi->focusWidget == oldDesc) + pdi->focusWidget = NULL; } if (descendant) { ----------------------------------------- #include <stdio.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Xaw/AsciiText.h> #include <X11/Xaw/Command.h> #include <X11/Xaw/Box.h> static void Quit(), KeyPressed(), Focus(), UnFocus(); String fallback_resources[] = { "*input: True", "*Text*width: 400", "*Text*editType: edit", "*Text*translations: #override <Key>Escape: UnFocus()", "*quit.label: Quit", "*focus.label: Set Focus", "*box.translations: <Key>: KeyPressed()", NULL, }; main(argc, argv) int argc; char **argv; { static void Syntax(); XtAppContext app_con; Widget toplevel, box, quit, focus, text; Arg args[5]; static char buffer[100]; static XtActionsRec actionTable[] = { { "KeyPressed", KeyPressed }, { "UnFocus", UnFocus } }; toplevel = XtAppInitialize(&app_con, "XFocus", NULL, 0, &argc, argv, fallback_resources, NULL, 0); box = XtCreateManagedWidget("box", boxWidgetClass, toplevel, NULL, 0); quit = XtCreateManagedWidget("quit", commandWidgetClass, box, NULL, 0); focus = XtCreateManagedWidget("focus", commandWidgetClass, box, NULL, 0); XtSetArg(args[0], XtNuseStringInPlace, True); XtSetArg(args[1], XtNstring, buffer); XtSetArg(args[2], XtNlength, sizeof(buffer)); text = XtCreateManagedWidget("text", asciiTextWidgetClass, box, args, 3); XtAppAddActions(app_con, actionTable, XtNumber(actionTable)); XtAddCallback(quit, XtNcallback, Quit, (XtPointer) NULL); XtAddCallback(focus, XtNcallback, Focus, (XtPointer) text); XtSetKeyboardFocus(box, text); XtRealizeWidget(toplevel); XtAppMainLoop(app_con); } static void Quit(w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { exit(0); } static void Focus(w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { XtSetKeyboardFocus(XtParent(w), (Widget)client_data); } static void UnFocus(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { XtSetKeyboardFocus(XtParent(w), None); } static void KeyPressed(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { fprintf(stderr, "KeyPress in box\n"); }
swick@ATHENA.MIT.EDU (Ralph Swick) (08/24/90)
It seems to me that the call XtSetKeyboardFocus(widget, None) does not clear the cached per display focus widget with the result that events are still delivered to the widget which was set in a previous call to XtSetKeyboardFocus(). Your analysis is correct. The fix will be included in the next public patch (in a few days).