JDK-6465038 : On MToolkit, cannot input any character on multi window environment
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6,6u2
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux,solaris_2.5.1
  • CPU: x86,sparc
  • Submitted: 2006-08-29
  • Updated: 2011-01-19
  • Resolved: 2007-06-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u4 b01Fixed 7Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
OPERATING SYSTEM(S):
Red Hat Enterprise Linux 3 Update 8

FULL JDK VERSION(S):
  java version "1.6.0-rc"
  Java(TM) SE Runtime Environment (build 1.6.0-rc-b96)
  Java HotSpot(TM) Client VM (build 1.6.0-rc-b96, mixed mode)


DESCRIPTION:
On Motf AWT(MToolkit), I cannot input any character on multi window environment.
It seems focus related problem.
It's not related locale or XIM server.

Test instruction is as follows:
1. Compile and run following program
2. One of window may have input focus, type some characters
3. Move input focus to the other window by using mouse, type some characters but nothing happen
4. Move back input focus to the first window by using mouse, type some characters but also nothing happened

==============================================================
import java.awt.*;
import javax.swing.*;

class MultiFrame {
  MultiFrame(int x, int y) {
    JFrame frame = new JFrame("FrameTest");
    Container c = frame.getContentPane();
    c.setLayout(new GridLayout(1,0));
    c.add(new JTextArea());
    frame.setSize(200,100);
    frame.setLocation(x,y);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    System.setProperty("awt.toolkit","sun.awt.motif.MToolkit");
    MultiFrame f1 = new MultiFrame(0,0);
    MultiFrame f2 = new MultiFrame(200,0);
  }
}

Comments
EVALUATION Finally I found out the following. In awt_TopLevel::shellEH handler when we process FocusOut we call the following functions: XmProcessTraversal(shell, XmTRAVERSE_CURRENT); XtSetKeyboardFocus(shell, NULL); The expected result of these calls is not clear. Suppose that it was meant to zero Xm/Xt focus. Not sure that it's correct to reset focus in such a way (the 'shell' itself is not focusable at all, at least it shouldn't be focused). In the context of that code we already clear focus as appropriate. The point is that only removing these two lines fixes the problem. This code was added in 1.4.2 and it didn't cause problems till the proxy mechanism has been implemented. I.e. it conflicts with our proxy XSetInputFocus settings as I supposed above. Originally this change was an addition to the fix for 4510221. I checked the test case provided for that CR and it worked fine without these two lines of code. So, I feel free to remove them. Additionally I considered it useful to still add a code that would restore focus on an appropriate widget in case we detect that focus value is wrong (on receiving FocusIn in awt_TopLevel::shellEH).
16-03-2007

SUGGESTED FIX src/solaris/native/sun/awt/awt_Component.c src/solaris/native/sun/awt/awt_TopLevel.c ------- awt_Component.c ------- *** /tmp/sccs.usaade Thu Sep 7 21:19:04 2006 --- awt_Component.c Thu Sep 7 20:57:16 2006 *************** *** 1506,1526 **** ret = (jlong)XtWindow(cdata->widget); AWT_FLUSH_UNLOCK(); return ret; } ! /* ! * Class: sun_awt_motif_MComponentPeer ! * Method: restore_Focus ! * Signature: ()V ! */ ! JNIEXPORT void JNICALL Java_sun_awt_motif_MComponentPeer_restoreFocus ! (JNIEnv *env, jobject this) ! { jobject focus_peer; - AWT_LOCK(); focus_peer = awt_canvas_getFocusOwnerPeer(); if (!JNU_IsNull(env, focus_peer)) { struct ComponentData *bdata; Boolean result; --- 1506,1522 ---- ret = (jlong)XtWindow(cdata->widget); AWT_FLUSH_UNLOCK(); return ret; } ! void restoreFocus(JNIEnv *env) { jobject focus_peer; + if (env == NULL) { + env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + } + focus_peer = awt_canvas_getFocusOwnerPeer(); if (!JNU_IsNull(env, focus_peer)) { struct ComponentData *bdata; Boolean result; *************** *** 1534,1543 **** --- 1530,1552 ---- XtSetKeyboardFocus(getShellWidget(widgetToFocus), widgetToFocus); } } } (*env)->DeleteLocalRef(env, focus_peer); + } + + /* + * Class: sun_awt_motif_MComponentPeer + * Method: restore_Focus + * Signature: ()V + */ + JNIEXPORT void JNICALL Java_sun_awt_motif_MComponentPeer_restoreFocus + (JNIEnv *env, jobject this) + { + AWT_LOCK(); + + restoreFocus(env); AWT_UNLOCK(); } JNIEXPORT jboolean JNICALL ------- awt_TopLevel.c ------- *** /tmp/sccs.Uda4Ce Thu Sep 7 21:24:35 2006 --- awt_TopLevel.c Thu Sep 7 21:24:20 2006 *************** *** 1104,1117 **** switch (event->xany.type) { case FocusOut: // Will be handled by proxy automaticall since he is focus owner break; ! case FocusIn: ! // Forward focus event to the proxy ! XSetInputFocus(awt_display, XtWindow(wdata->focusProxy), RevertToParent, CurrentTime); ! break; } } /** * Fix for Alt-Tab problem. --- 1104,1127 ---- switch (event->xany.type) { case FocusOut: // Will be handled by proxy automaticall since he is focus owner break; ! case FocusIn: ! { ! extern void restoreFocus(JNIEnv *env); ! // Forward focus event to the proxy ! XSetInputFocus(awt_display, XtWindow(wdata->focusProxy), RevertToParent, CurrentTime); ! /* ! * Fix for 6465038. ! * After setting focus via XSetInputFocus() call we have to set it in ! * Motif (Xt) terms. This shouldn't prevent the focus proxy from ! * receiving focus events, that is our aim. ! */ ! restoreFocus(NULL); ! break; ! } } } /** * Fix for Alt-Tab problem.
07-09-2006

EVALUATION The bug is indeed is a regression of 4931668 "Need to implement server side support for XEmbed". In that huge fix, among other changes, there was proxy focus implementation. When a toplevel widget gets focus it is forwarded to a focus proxy widget tied to the toplevel. This is done by means of calling XSetInputFocus() Xlib method. The point is that in the context of Motif this is intolerable. Here's what Motif's doc says about that: You cannot call generic X functions like XSetInputFocus() to force a widget to take input focus or you will undermine Motif's attempt at monitoring and controlling the input policy on its own. So, Motif's focus policy gets broken by that call, and when the proxy widget gets key event, the event is dispatched to the widget Motif treats as the focus owner. Thus, the fix is to set focus in Motif's terms along with forwarding it to the focus proxy widget via XSetInputFocus(). This can be done with help of MComponentPeer.restoreFocus() native method (as pointed in the previous evaluation note). This method does exactly what we need.
07-09-2006

EVALUATION On setting initial focus to the first window awt_Toplevel.shellEH() redirecting keyboard focus with XtSetKeyboardFocus() to NULL(None?) so XtDispatchEvent works fine. Then, on transfering focus to the second window shellEH again nullifying that. When I'm resizing the window and it become responsive again I may see that awt_Component.restoreFocus() is setting keyboard focus. Seem this step does workarounds the problem. Though I'm not verifyed the values. Suppose we should call awt_Component.requestFocus that addressing to XtSetKeyboardFocus(shell, w);
07-09-2006

WORK AROUND Resize frame to get it responsible back.
07-09-2006

EVALUATION might be a regression of 4931668.
01-09-2006

EVALUATION I found that the problem first arised in Mustang b35 and has been reproducible to present time. I discovered the following. After switching to another frame in the testcase, when I'm typing I see that the key event appears in the event loop, then it gets dispatched (via XtDispatchEvent, see awt_MToolkit::processOneEvent) but the event handler doesn't get called (see canvas::awt_canvas_handleEvent). What's the reason?
01-09-2006

EVALUATION The issue is reproducible with JDK6.0 MToolkit enabled.
01-09-2006

EVALUATION Not reproducible with XAWT. Not reproducible with JDK5.0_u07.
30-08-2006