JDK-6785058 : Parent dn't get the focus after dialog is closed if security warning is applied
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6u12
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_10
  • CPU: sparc
  • Submitted: 2008-12-15
  • Updated: 2011-01-19
  • Resolved: 2009-05-15
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
6u14 b01Fixed 7Fixed
Related Reports
Relates :  
Description
I have a frame which contains a button. Pressing on the button shows a dialog. When i press the escape key on the dialog , the dialog gets closed but parent is not getting the focus. This happens only if program is started with -Djava.security.manager. It works fine if security option is not applied.   This works fine even in 6u10 with the security option, but fails from 6u10 b01 & b02 promoted build. Hence its a regression.  

Step to reproduce:-
-------------------
1) Run the attached porogram.
java  -Djava.security.manager WindowTest
2) Click the button on the frame. A dialog is seen. 
3)Press 'Escape' key, Dialog gets closed. But Observe that focus is not on the button of the frame. If you see the same , then the bug is reproduced.

Comments
SUGGESTED FIX The webrev: http://sa.sfbay.sun.com/projects/awt_data/6u14/6785058 ------- XWarningWindow.java ------- *** /tmp/sccs.RCNaYH Tue Jan 20 16:20:23 2009 --- XWarningWindow.java Tue Jan 20 14:04:03 2009 *************** *** 360,385 **** }}.start(); } }; public void setSecurityWarningVisible(boolean visible) { if (visible) { XToolkit.remove(hidingTask); XToolkit.remove(showingTask); if (isVisible()) { currentIcon = 0; } else { currentIcon = 3; } ! XToolkit.schedule(showingTask, 1); } else { XToolkit.remove(showingTask); XToolkit.remove(hidingTask); if (!isVisible()) { return; } ! XToolkit.schedule(hidingTask, hidingDelay); } } - - } --- 360,395 ---- }}.start(); } }; public void setSecurityWarningVisible(boolean visible) { + setSecurityWarningVisible(visible, true); + } + + public void setSecurityWarningVisible(boolean visible, boolean doSchedule) { if (visible) { XToolkit.remove(hidingTask); XToolkit.remove(showingTask); if (isVisible()) { currentIcon = 0; } else { currentIcon = 3; } ! if (doSchedule) { ! XToolkit.schedule(showingTask, 1); ! } else { ! showingTask.run(); ! } } else { XToolkit.remove(showingTask); XToolkit.remove(hidingTask); if (!isVisible()) { return; } ! if (doSchedule) { ! XToolkit.schedule(hidingTask, hidingDelay); ! } else { ! hidingTask.run(); ! } } } } ------- XWindowPeer.java ------- *** /tmp/sccs.TCtP7S Tue Jan 20 16:20:23 2009 --- XWindowPeer.java Tue Jan 20 16:14:58 2009 *************** *** 956,965 **** --- 956,968 ---- } public void setVisible(boolean vis) { updateFocusability(); promoteDefaultPosition(); + if (!vis && warningWindow != null) { + warningWindow.setSecurityWarningVisible(false, false); + } super.setVisible(vis); // method called somewhere in parent does not generate configure-notify // event for override-redirect. // Ergo, no reshape and bugs like 5085647 in case setBounds was // called before setVisible. *************** *** 1017,1026 **** --- 1020,1033 ---- boolean show = false; int state = getWMState(); + if (!isVisible()) { + return; // The warning window should already be hidden. + } + // getWMState() always returns 0 (Withdrawn) for simple windows. Hence // we ignore the state for such windows. if (isVisible() && (state == NormalState || isSimpleWindow())) { if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == getTarget())
22-01-2009

EVALUATION The solution is to reorder the sequence of disposing (unmapping) a toplevel and its warning icon. The warning icon should be disposed first and then the toplevel. This works around the Metacity issue and makes our behavior even more consistent with respect to User Experience.
20-01-2009

EVALUATION A bug filed against Metacity: http://bugzilla.gnome.org/show_bug.cgi?id=567851
15-01-2009

EVALUATION The testcase reproduces the problem even without the transient property being set. So, "transient" doesn't matter.
15-01-2009

EVALUATION I've found that the undecorated style of the warning icon window somehow affects Metacity behavior. Not setting the warning icon undecorated makes the problem disappear. And here's a native testcase that 100% reproduces the issue with Metacity 2.16.0: ---------------------------------------------------------------- #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> Display *display; int screen_num; Window create_window(char *name, Window parent, int x, int y, int width, int height) { XSizeHints sh; XWMHints wmh; Window win = XCreateSimpleWindow(display, parent, x, y, width, height, 2, // border width BlackPixel(display, screen_num), WhitePixel(display, screen_num)); XStoreName(display, win, name); XSelectInput(display, win, FocusChangeMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask ); sh.width = width; sh.height = height; sh.x = x; sh.y = y; sh.flags = USPosition | USSize; XSetWMNormalHints(display, win, &sh); wmh.input = False; wmh.flags = InputHint; XSetWMHints(display, win, &wmh); return win; } int main(int argc, char **argv) { Atom protocols[1]; Atom XA_WM_TAKE_FOCUS; Window root; Window win[2], window; XEvent ev; char *win_name; char *display_name = NULL; if ((display = XOpenDisplay(display_name)) == NULL) { fprintf(stderr, "Couldn't open %s\n", XDisplayName(display_name)); return -1; } screen_num = DefaultScreen(display); root = RootWindow(display, screen_num); win[0] = create_window("Frame 0", root, 100, 100, 200, 100); win[1] = create_window("Frame 1", root, 200, 200, 200, 100); win[2] = create_window("Transient", root, 450, 200, 50, 50); protocols[0] = XA_WM_TAKE_FOCUS = XInternAtom(display, "WM_TAKE_FOCUS", True); XSetWMProtocols(display, win[0], protocols, 1); XSetWMProtocols(display, win[1], protocols, 1); XSetWMProtocols(display, win[2], NULL, 0); typedef long CARD32; typedef struct _mwmhints { CARD32 flags; CARD32 functions; CARD32 decorations; CARD32 inputMode; CARD32 status; } MWMHints; long MWM_HINTS_DECORATIONS = (1 << 1); long PROP_MWM_HINTS_ELEMENTS = 5; MWMHints mwmhints; Atom XA_MOTIF_WM_HINTS = XInternAtom(display, "_MOTIF_WM_HINTS", False); memset(&mwmhints, 0, sizeof(mwmhints)); mwmhints.flags = MWM_HINTS_DECORATIONS; mwmhints.decorations = 0; XChangeProperty(display, win[2], XA_MOTIF_WM_HINTS, XA_MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS); XSetTransientForHint(display, win[2], win[1]); XMapWindow(display, win[0]); XFlush(display); XSync(display, False); while (1) { XNextEvent(display, &ev); window = ev.xany.window; XFetchName(display, window, &win_name); if (win_name != 0) fprintf(stderr, "event on %s: ", win_name); switch(ev.xany.type) { case ClientMessage: fprintf(stderr, "ClientMessage\n"); if (ev.xclient.data.l[0] == XA_WM_TAKE_FOCUS) { fprintf(stderr, " WM_TAKE_FOCUS\n"); XSetInputFocus(display, window, RevertToPointerRoot, CurrentTime); } break; case FocusIn: fprintf(stderr, "FocusIn\n"); break; case FocusOut: fprintf(stderr, "FocusOut\n"); break; case ButtonPress: fprintf(stderr, "ButtonPress\n"); if (window == win[0]) { XMapWindow(display, win[1]); XMapWindow(display, win[2]); XSetTransientForHint(display, win[2], win[1]); } else if (window == win[1]) { XUnmapWindow(display, win[1]); } case UnmapNotify: fprintf(stderr, "UnmapNotify\n"); if (window == win[1]) { XSetTransientForHint(display, win[2], 0); XUnmapWindow(display, win[2]); } default: fprintf(stderr, "%d\n", ev.xany.type); } } return 0; } ---------------------------------------------------------------- To compile it (native.c): $ gcc native.c -lX11 -o native By the way, the problem doesn't appear on KWM with this testcase.
14-01-2009

EVALUATION The bug can be reproduced from time to time. What I see is that the parent frame doesn't get WM_TAKE_FOCUS when its owned modal dialog is closed. It's the WM that should send us that event. By the way, I can't reproduce the bug with KWM, only with Metacity. So, this looks like a "special behavior" of the latter. Obviously, the warning icon window (that is transient for the modal dialog) somehow affects the WM's behavior. We should try to create a native app that would emulate the bug. Then report it against Metacity. Also, we may consider possibility of requesting activation manually as a workaround.
13-01-2009