JDK-6777277 : PIT : security warning window is created on the taskbar & closing it will exit jvm
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6u12
  • Priority: P1
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_10
  • CPU: x86
  • Submitted: 2008-11-27
  • Updated: 2011-01-19
  • Resolved: 2008-12-03
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 b02Fixed
Related Reports
Relates :  
Description
I have a dialog, which has come controls. I invoke a shaped frame. Security icon can be seen on both dialog & on frame. I click on frame window which is there on the taskbar.  The shaped windows gets minimized. Then i click on the desktop, so that dailog security icon can disappear. Now i move the mouse pointer on the dialog. I can see a security warning window by title 'Warning window' is created on the taskbar.  I right click on the newly created warning windows & close it by selecting the menuitem 'Close'. Now the whole application exits. 

I have attached the screen shot .

Step to reproduce:-
------------------
1) Run the attached jar file.
java -jar -Djava.security.manager ToplevelFactory.jar
2) select 'frame' , Oval shape & click on 'Show toplevel' button. 
3) You can see a 'Oval shaped frame'.
4) click on the frame window which is created on the taskbar.
5) Click some where on the desktop. so that security warning can disappear from the dialog.
6) Move the mouse pointer on the dialog. Observe that an extra window with title 'Warning window'  is created on the window list.
7) Right click on the 'Warning window' window on the taskbar & select the close button.
Observe that application exits. If you see the same then the bug is reproduced.

I tested this on 6u12 b02 pit build , Solaris 10 & solaris 11, Gnome window manager.

Comments
EVALUATION The suggested fix resolves the P1 issue. However it introduces a minor (P3) issue: an untrusted Java window cannot be given the input focus when deiconifying it by clicking its taskbar button. The user must explicitly click the Java window on the screen in order to give it the input focus. This issue will be covered under a separate CR.
02-12-2008

SUGGESTED FIX --- old/src/solaris/classes/sun/awt/X11/XNETProtocol.java 2008-12-02 18:20:43.000000000 +0300 +++ new/src/solaris/classes/sun/awt/X11/XNETProtocol.java 2008-12-02 18:20:43.000000000 +0300 @@ -153,6 +153,32 @@ return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol(); } + public void requestState(XWindow window, XAtom state, boolean isAdd) { + XClientMessageEvent req = new XClientMessageEvent(); + try { + req.set_type((int)XlibWrapper.ClientMessage); + req.set_window(window.getWindow()); + req.set_message_type(XA_NET_WM_STATE.getAtom()); + req.set_format(32); + req.set_data(0, isAdd ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE); + req.set_data(1, state.getAtom()); + log.log(Level.FINE, "Setting _NET_STATE atom {0} on {1} for {2}", new Object[] {state, window, Boolean.valueOf(isAdd)}); + XToolkit.awtLock(); + try { + XlibWrapper.XSendEvent(XToolkit.getDisplay(), + XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()), + false, + XlibWrapper.SubstructureRedirectMask | XlibWrapper.SubstructureNotifyMask, + req.pData); + } + finally { + XToolkit.awtUnlock(); + } + } finally { + req.dispose(); + } + } + /** * Helper function to set/reset one state in NET_WM_STATE * If window is showing then it uses ClientMessage, otherwise adjusts NET_WM_STATE list @@ -165,29 +191,7 @@ new Object[] {Boolean.valueOf(window.isWithdrawn()), Boolean.valueOf(window.isVisible()), Boolean.valueOf(window.isMapped()), Boolean.valueOf(window.isShowing())}); if (window.isShowing()) { - XClientMessageEvent req = new XClientMessageEvent(); - try { - req.set_type((int)XlibWrapper.ClientMessage); - req.set_window(window.getWindow()); - req.set_message_type(XA_NET_WM_STATE.getAtom()); - req.set_format(32); - req.set_data(0, (!set) ? _NET_WM_STATE_REMOVE : _NET_WM_STATE_ADD); - req.set_data(1, state.getAtom()); - log.log(Level.FINE, "Setting _NET_STATE atom {0} on {1} for {2}", new Object[] {state, window, Boolean.valueOf(set)}); - XToolkit.awtLock(); - try { - XlibWrapper.XSendEvent(XToolkit.getDisplay(), - XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()), - false, - XlibWrapper.SubstructureRedirectMask | XlibWrapper.SubstructureNotifyMask, - req.pData); - } - finally { - XToolkit.awtUnlock(); - } - } finally { - req.dispose(); - } + requestState(window, state, set); } else { XAtomList net_wm_state = window.getNETWMState(); log.log(Level.FINE, "Current state on {0} is {1}", new Object[] {window, net_wm_state}); @@ -227,6 +231,7 @@ XAtom XA_NET_WM_STATE_MODAL = XAtom.get("_NET_WM_STATE_MODAL"); XAtom XA_NET_WM_STATE_FULLSCREEN = XAtom.get("_NET_WM_STATE_FULLSCREEN"); XAtom XA_NET_WM_STATE_BELOW = XAtom.get("_NET_WM_STATE_BELOW"); + XAtom XA_NET_WM_STATE_SKIP_TASKBAR = XAtom.get("_NET_WM_STATE_SKIP_TASKBAR"); XAtom XA_NET_WM_WINDOW_TYPE = XAtom.get("_NET_WM_WINDOW_TYPE"); XAtom XA_NET_WM_WINDOW_TYPE_DIALOG = XAtom.get("_NET_WM_WINDOW_TYPE_DIALOG"); --- old/src/solaris/classes/sun/awt/X11/XWarningWindow.java 2008-12-02 18:20:44.000000000 +0300 +++ new/src/solaris/classes/sun/awt/X11/XWarningWindow.java 2008-12-02 18:20:44.000000000 +0300 @@ -122,12 +122,19 @@ this.ownerPeer = new WeakReference<XWindowPeer>(ownerPeer); } + private void requestNoTaskbar() { + XNETProtocol netProtocol = XWM.getWM().getNETProtocol(); + if (netProtocol != null) { + netProtocol.requestState(this, netProtocol.XA_NET_WM_STATE_SKIP_TASKBAR, true); + } + } + @Override void postInit(XCreateWindowParams params) { super.postInit(params); XToolkit.awtLock(); try { - XWM.setMotifDecor(this, false, 0, MWM_FUNC_ALL); + XWM.setMotifDecor(this, false, 0, 0); XWM.setOLDecor(this, false, 0); long parentWindow = ((Long)params.get(OWNER)).longValue(); XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), @@ -137,11 +144,13 @@ ico.getWidth(), ico.getHeight(), ico.getIntData()); XWMHints hints = getWMHints(); - hints.set_flags(hints.get_flags() | (int)XlibWrapper.InputHint); + hints.set_flags(hints.get_flags() | (int)XlibWrapper.InputHint | (int)XlibWrapper.StateHint); hints.set_input(false); + hints.set_initial_state(XlibWrapper.NormalState); XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData); initWMProtocols(); + requestNoTaskbar(); } finally { XToolkit.awtUnlock(); } @@ -262,29 +271,47 @@ } } - @Override - public void xSetVisible(boolean visible) { - if (visible) { - super.xSetVisible(visible); + 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.XSetTransientFor(XToolkit.getDisplay(), - getWindow(), parentWindow); - } finally { - XToolkit.awtUnlock(); + XlibWrapper.XSendEvent(XToolkit.getDisplay(), + XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()), + false, + XlibWrapper.SubstructureRedirectMask | XlibWrapper.SubstructureNotifyMask, + req.pData); } - } else { - XToolkit.awtLock(); - try { - XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), - getWindow(), 0); - } finally { + finally { XToolkit.awtUnlock(); } - super.xSetVisible(visible); + } finally { + req.dispose(); } } + @Override + public void xSetVisible(boolean visible) { + super.xSetVisible(visible); + + // 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() { public void run() { xSetVisible(false); @@ -293,15 +320,18 @@ private final Runnable showingTask = new Runnable() { public void run() { - if (!isVisible()) { - xSetVisible(true); - updateWarningWindowBounds(); - } - repaint(); - if (currentIcon > 0) { - currentIcon--; - XToolkit.schedule(showingTask, showingDelay); - } + new Thread() { + public void run() { + if (!isVisible()) { + xSetVisible(true); + updateWarningWindowBounds(); + } + repaint(); + if (currentIcon > 0) { + currentIcon--; + XToolkit.schedule(showingTask, showingDelay); + } + }}.start(); } };
02-12-2008

EVALUATION Requesting the _NET_WM_STATE_SKIP_TASKBAR window state on each showing/hiding of the security warning does eliminate the button from the task bar. However, after restoring the shaped frame, the warning icon does not come back. The reason is: the icon somehow remains in the IconicState which makes it hidden.
28-11-2008

EVALUATION The window manager somehow iconifies the security warning window (most probably because of the WM_TRANSIENT_FOR hint), and this causes the icon to appear on the taskbar. It seems that we delete the TRANSIENT_FOR hint too late which causes the icon to stay in iconic state afterwards.
28-11-2008