6863566: Java should support the freedesktop.org startup notification specification
authoranthony
Fri, 20 Nov 2009 19:11:47 +0300
changeset 4361 66c14524f39c
parent 4267 3dee4217d3dc
child 4362 ad915ad8792f
6863566: Java should support the freedesktop.org startup notification specification Summary: The startup notification gets removed as soon as a Java top-level window is shown Reviewed-by: anthony, art, dcherepanov Contributed-by: Damjan Jovanovic <damjan.jov@gmail.com>
jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Mon Nov 16 18:13:15 2009 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Fri Nov 20 19:11:47 2009 +0300
@@ -35,12 +35,19 @@
 import java.awt.peer.ComponentPeer;
 import java.awt.peer.WindowPeer;
 
+import java.io.UnsupportedEncodingException;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 import java.util.Vector;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import sun.util.logging.PlatformLogger;
 
 import sun.awt.AWTAccessor;
@@ -90,6 +97,8 @@
     private boolean mustControlStackPosition = false; // Am override-redirect not on top
     private XEventDispatcher rootPropertyEventDispatcher = null;
 
+    private static final AtomicBoolean isStartupNotificationRemoved = new AtomicBoolean();
+
     /*
      * Focus related flags
      */
@@ -1183,7 +1192,77 @@
         }
     }
 
+    private void removeStartupNotification() {
+        if (isStartupNotificationRemoved.getAndSet(true)) {
+            return;
+        }
+
+        final String desktopStartupId = AccessController.doPrivileged(new PrivilegedAction<String>() {
+            public String run() {
+                return XToolkit.getEnv("DESKTOP_STARTUP_ID");
+            }
+        });
+        if (desktopStartupId == null) {
+            return;
+        }
+
+        final StringBuilder messageBuilder = new StringBuilder("remove: ID=");
+        messageBuilder.append('"');
+        for (int i = 0; i < desktopStartupId.length(); i++) {
+            if (desktopStartupId.charAt(i) == '"' || desktopStartupId.charAt(i) == '\\') {
+                messageBuilder.append('\\');
+            }
+            messageBuilder.append(desktopStartupId.charAt(i));
+        }
+        messageBuilder.append('"');
+        messageBuilder.append('\0');
+        final byte[] message;
+        try {
+            message = messageBuilder.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException cannotHappen) {
+            return;
+        }
+
+        XClientMessageEvent req = null;
+
+        XToolkit.awtLock();
+        try {
+            final XAtom netStartupInfoBeginAtom = XAtom.get("_NET_STARTUP_INFO_BEGIN");
+            final XAtom netStartupInfoAtom = XAtom.get("_NET_STARTUP_INFO");
+
+            req = new XClientMessageEvent();
+            req.set_type(XConstants.ClientMessage);
+            req.set_window(getWindow());
+            req.set_message_type(netStartupInfoBeginAtom.getAtom());
+            req.set_format(8);
+
+            for (int pos = 0; pos < message.length; pos += 20) {
+                final int msglen = Math.min(message.length - pos, 20);
+                int i = 0;
+                for (; i < msglen; i++) {
+                    XlibWrapper.unsafe.putByte(req.get_data() + i, message[pos + i]);
+                }
+                for (; i < 20; i++) {
+                    XlibWrapper.unsafe.putByte(req.get_data() + i, (byte)0);
+                }
+                XlibWrapper.XSendEvent(XToolkit.getDisplay(),
+                    XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()),
+                    false,
+                    XConstants.PropertyChangeMask,
+                    req.pData);
+                req.set_message_type(netStartupInfoAtom.getAtom());
+            }
+        } finally {
+            XToolkit.awtUnlock();
+            if (req != null) {
+                req.dispose();
+            }
+        }
+    }
+
     public void handleMapNotifyEvent(XEvent xev) {
+        removeStartupNotification();
+
         // See 6480534.
         isUnhiding |= isWMStateNetHidden();