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).
|
|
|
WORK AROUND
Resize frame to get it responsible back.
|
|
|
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);
|
|
|
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.
|
|
|
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.
|
|
|
EVALUATION
The issue is reproducible with JDK6.0 MToolkit enabled.
|
|
|
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?
|
|
|
EVALUATION
might be a regression of 4931668.
|
|
|
EVALUATION
Not reproducible with XAWT.
Not reproducible with JDK5.0_u07.
|
|
|
|