United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6465038 On MToolkit, cannot input any character on multi window environment
JDK-6465038 : On MToolkit, cannot input any character on multi window environment

Details
Type:
Bug
Submit Date:
2006-08-29
Status:
Resolved
Updated Date:
2011-01-19
Project Name:
JDK
Resolved Date:
2007-06-30
Component:
client-libs
OS:
solaris_2.5.1,linux
Sub-Component:
java.awt
CPU:
x86,sparc
Priority:
P4
Resolution:
Fixed
Affected Versions:
6,6u2
Fixed Versions:
6u4 (b01)

Related Reports
Backport:
Duplicate:
Relates:
Relates:
Relates:
Relates:
Relates:

Sub Tasks

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

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

The issue is reproducible with JDK6.0 MToolkit enabled.
                                     
2006-09-01
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?
                                     
2006-09-01
EVALUATION

might be a regression of 4931668.
                                     
2006-09-01
WORK AROUND

Resize frame to get it responsible back.
                                     
2006-09-07
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);
                                     
2006-09-07
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.
                                     
2006-09-07
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.
                                     
2006-09-07
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).
                                     
2007-03-16



Hardware and Software, Engineered to Work Together