JDK-6779066 : Untrusted window cannot receive input focus by clicking its taskbar button after deiconification
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6u12
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,solaris
  • CPU: generic,sparc
  • Submitted: 2008-12-02
  • Updated: 2011-01-19
  • Resolved: 2008-12-19
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
6u12 b03Fixed
Related Reports
Duplicate :  
Relates :  
Description
With the fix for 6777277 there was introduced a minor side effect: if the user iconifies an untrusted Java window and then deiconifies it using the taskbar button, the window does not receive the input focus when running on Metacity window manager. Subsequent clicks on the taskbar do not give the focus either. The user has to click the Java window itself in order to give the focus.

Note: this issue is not reproducible on Compiz and KDE. It affects Gnome/Metacity only.

Comments
SUGGESTED FIX --- old/src/solaris/classes/sun/awt/X11/XWarningWindow.java 2008-12-04 19:07:27.000000000 +0300 +++ new/src/solaris/classes/sun/awt/X11/XWarningWindow.java 2008-12-04 19:07:27.000000000 +0300 @@ -246,6 +246,54 @@ return true; } + /** Send a synthetic UnmapNotify in order to withdraw the window. + */ + private void withdraw() { + XEvent req = new XEvent(); + try { + long root; + XToolkit.awtLock(); + try { + root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()); + } + finally { + XToolkit.awtUnlock(); + } + + req.set_type(UnmapNotify); + + XUnmapEvent umev = req.get_xunmap(); + + umev.set_event(root); + umev.set_window(getWindow()); + umev.set_from_configure(false); + + XToolkit.awtLock(); + try { + XlibWrapper.XSendEvent(XToolkit.getDisplay(), + root, + false, + XlibWrapper.SubstructureRedirectMask | XlibWrapper.SubstructureNotifyMask, + req.pData); + } + finally { + XToolkit.awtUnlock(); + } + } finally { + req.dispose(); + } + } + + @Override + protected void stateChanged(long time, int oldState, int newState) { + if (newState == XlibWrapper.IconicState) { + withdraw(); + + // To update the local copy of the 'visible' flag in XBaseWindow + super.xSetVisible(false); + } + } + @Override protected void setMouseAbove(boolean above) { super.setMouseAbove(above); @@ -271,34 +319,6 @@ } } - private XAtom XA_WM_CHANGE_STATE = XAtom.get("WM_CHANGE_STATE"); - - private void deiconify() { - XClientMessageEvent req = new XClientMessageEvent(); - try { - req.set_type((int)XlibWrapper.ClientMessage); - req.set_window(getWindow()); - req.set_message_type(XA_WM_CHANGE_STATE.getAtom()); - req.set_format(32); - req.set_data(0, (int)XlibWrapper.NormalState); - req.set_data(1, 0); - req.set_data(2, 0); - XToolkit.awtLock(); - try { - XlibWrapper.XSendEvent(XToolkit.getDisplay(), - XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()), - false, - XlibWrapper.SubstructureRedirectMask | XlibWrapper.SubstructureNotifyMask, - req.pData); - } - finally { - XToolkit.awtUnlock(); - } - } finally { - req.dispose(); - } - } - @Override public void xSetVisible(boolean visible) { super.xSetVisible(visible); @@ -306,10 +326,6 @@ // The _NET_WM_STATE_SKIP_TASKBAR got reset upon hiding/showing, // so we request it every time whenever we change the visibility. requestNoTaskbar(); - - // This is a "reverse" operation of XIconifyWindow() in case the - // waring window was iconified by the window manager. - deiconify(); } private final Runnable hidingTask = new Runnable() { --- old/src/solaris/classes/sun/awt/X11/XWindow.java 2008-12-04 19:07:27.000000000 +0300 +++ new/src/solaris/classes/sun/awt/X11/XWindow.java 2008-12-04 19:07:27.000000000 +0300 @@ -78,6 +78,9 @@ protected static XAtom wm_protocols; protected static XAtom wm_delete_window; protected static XAtom wm_take_focus; + + private boolean stateChanged; // Indicates whether the value on savedState is valid + private int savedState; // Holds last known state of the top-level window XWindowAttributesData winAttr; @@ -204,6 +207,7 @@ XToolkit.awtUnlock(); } winAttr = new XWindowAttributesData(); + savedState = WithdrawnState; } void postInit(XCreateWindowParams params) { @@ -1139,6 +1143,55 @@ } + /* + * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are + * unreliable, since mapping changes can happen for a virtual desktop + * switch or MacOS style shading that became quite popular under X as + * well. Yes, it probably should not be this way, as it violates + * ICCCM, but reality is that quite a lot of window managers abuse + * mapping state. + */ + int getWMState() { + if (stateChanged) { + stateChanged = false; + WindowPropertyGetter getter = + new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false, + XWM.XA_WM_STATE); + try { + int status = getter.execute(); + if (status != XlibWrapper.Success || getter.getData() == 0) { + return savedState = XlibWrapper.WithdrawnState; + } + + if (getter.getActualType() != XWM.XA_WM_STATE.getAtom() && getter.getActualFormat() != 32) { + return savedState = XlibWrapper.WithdrawnState; + } + savedState = (int)Native.getCard32(getter.getData()); + } finally { + getter.dispose(); + } + } + return savedState; + } + + /** + * Override this methods to get notifications when top-level window state changes. The state is + * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState + */ + protected void stateChanged(long time, int oldState, int newState) { + } + + @Override + public void handlePropertyNotify(XEvent xev) { + super.handlePropertyNotify(xev); + XPropertyEvent ev = xev.get_xproperty(); + if (ev.get_atom() == XWM.XA_WM_STATE.getAtom()) { + // State has changed, invalidate saved value + stateChanged = true; + stateChanged(ev.get_time(), savedState, getWMState()); + } + } + public void reshape(Rectangle bounds) { reshape(bounds.x, bounds.y, bounds.width, bounds.height); } --- old/src/solaris/classes/sun/awt/X11/XWindowPeer.java 2008-12-04 19:07:27.000000000 +0300 +++ new/src/solaris/classes/sun/awt/X11/XWindowPeer.java 2008-12-04 19:07:27.000000000 +0300 @@ -52,8 +52,6 @@ protected XWindowPeer prevTransientFor, nextTransientFor; private boolean grab = false; // Whether to do a grab during showing - private boolean stateChanged; // Indicates whether the value on savedState is valid - private int savedState; // Holds last known state of the top-level window private boolean mustControlStackPosition = false; // Am override-redirect not on top private XEventDispatcher rootPropertyEventDispatcher = null; private boolean firstMapped = true; // Is the top-level mapped (shown) for the first time. @@ -99,7 +97,6 @@ eventMask |= VisibilityChangeMask; params.put(EVENT_MASK, eventMask); - savedState = WithdrawnState; XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE"); windows.add(this); @@ -1073,11 +1070,7 @@ public void handlePropertyNotify(XEvent xev) { super.handlePropertyNotify(xev); XPropertyEvent ev = xev.get_xproperty(); - if (ev.get_atom() == XWM.XA_WM_STATE.getAtom()) { - // State has changed, invalidate saved value - stateChanged = true; - stateChanged(ev.get_time(), savedState, getWMState()); - } else if (ev.get_atom() == XAtom.get("_KDE_NET_WM_FRAME_STRUT").getAtom() || ev.get_atom() == XAtom.get("_NET_WM_EXTENTS").getAtom()) { + if (ev.get_atom() == XAtom.get("_KDE_NET_WM_FRAME_STRUT").getAtom() || ev.get_atom() == XAtom.get("_NET_WM_EXTENTS").getAtom()) { getWMSetInsets(XAtom.get(ev.get_atom())); } } @@ -1120,6 +1113,7 @@ * Override this methods to get notifications when top-level window state changes. The state is * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState */ + @Override protected void stateChanged(long time, int oldState, int newState) { // Fix for 6401700, 6412803 // If this window is modal blocked, it is put into the transient_for @@ -1137,38 +1131,6 @@ updateSecurityWarningVisibility(); } - - /* - * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are - * unreliable, since mapping changes can happen for a virtual desktop - * switch or MacOS style shading that became quite popular under X as - * well. Yes, it probably should not be this way, as it violates - * ICCCM, but reality is that quite a lot of window managers abuse - * mapping state. - */ - int getWMState() { - if (stateChanged) { - stateChanged = false; - WindowPropertyGetter getter = - new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false, - XWM.XA_WM_STATE); - try { - int status = getter.execute(); - if (status != XlibWrapper.Success || getter.getData() == 0) { - return savedState = XlibWrapper.WithdrawnState; - } - - if (getter.getActualType() != XWM.XA_WM_STATE.getAtom() && getter.getActualFormat() != 32) { - return savedState = XlibWrapper.WithdrawnState; - } - savedState = (int)Native.getCard32(getter.getData()); - } finally { - getter.dispose(); - } - } - return savedState; - } - boolean isWithdrawn() { return getWMState() == XlibWrapper.WithdrawnState; }
04-12-2008

EVALUATION This effect was observed due to special processing of the transient windows by the window manager. Since the security warning is a trasnsient window for the main application window, it got iconified upon iconifying the main window. And Metacity ignored any subsequent unmap requests for the security window. When the user restored the window, the window manager automatically showed the security warning and tried to give it the input focus. Since the window is unfocusable, the window manager left the input focus on whatever window was active before deiconification process started. To resolve the issue we have to handle the state change property change notification and when the security warning window gets iconified we must send a synthetoc UnmapNotify for that window in order to turn it into Withdrawn state manually. This restores the reasonable behavior of the security warning.
04-12-2008