changeset 1974:1e1487c04864

6773985: OutOfMemory (PermGen space) under Linux / Firefox when switching bw. applets Summary: XEmbedClientHelper is uninstalled when its embedded frame is disposed. Reviewed-by: dcherepanov, ant
author art
date Fri, 19 Dec 2008 16:04:04 +0300
parents 1c56524d207d
children b8dae32335f2
files jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java
diffstat 2 files changed, 70 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java	Wed Nov 26 16:25:16 2008 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java	Fri Dec 19 16:04:04 2008 +0300
@@ -31,6 +31,9 @@
 import java.awt.Component;
 import java.awt.Container;
 
+import sun.awt.X11GraphicsConfig;
+import sun.awt.X11GraphicsDevice;
+
 /**
  * Helper class implementing XEmbed protocol handling routines(client side)
  * Window which wants to participate in a protocol should create an instance,
@@ -39,20 +42,34 @@
 public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher {
     private static final Logger xembedLog = Logger.getLogger("sun.awt.X11.xembed.XEmbedClientHelper");
 
-    private XEmbeddedFramePeer embedded;
+    private XEmbeddedFramePeer embedded; // XEmbed client
+    private long server; // XEmbed server
+
     private boolean active;
-    private long server;
     private boolean applicationActive;
 
     XEmbedClientHelper() {
         super();
     }
 
-    void install(XEmbeddedFramePeer embedded) {
-        this.embedded = embedded;
+    void setClient(XEmbeddedFramePeer client) {
+        if (xembedLog.isLoggable(Level.FINE)) {
+            xembedLog.fine("XEmbed client: " + client);
+        }
+        if (embedded != null) {
+            XToolkit.removeEventDispatcher(embedded.getWindow(), this);
+            active = false;
+        }
+        embedded = client;
+        if (embedded != null) {
+            XToolkit.addEventDispatcher(embedded.getWindow(), this);
+        }
+    }
 
-        if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine("Installing xembedder on " + embedded);
-        XToolkit.addEventDispatcher(embedded.getWindow(), this);
+    void install() {
+        if (xembedLog.isLoggable(Level.FINE)) {
+            xembedLog.fine("Installing xembedder on " + embedded);
+        }
         long[] info = new long[] { XEMBED_VERSION, XEMBED_MAPPED };
         long data = Native.card32ToData(info);
         try {
@@ -155,7 +172,24 @@
     }
     public void handleReparentNotify(XEvent xev) {
         XReparentEvent re = xev.get_xreparent();
-        server = re.get_parent();
+        long newParent = re.get_parent();
+        if (active) {
+            // unregister accelerators, etc. for old parent
+            embedded.notifyStopped();
+            // check if newParent is a root window
+            X11GraphicsConfig gc = (X11GraphicsConfig)embedded.getGraphicsConfiguration();
+            X11GraphicsDevice gd = (X11GraphicsDevice)gc.getDevice();
+            if ((newParent == XlibUtil.getRootWindow(gd.getScreen())) ||
+                (newParent == XToolkit.getDefaultRootWindow()))
+            {
+                // reparenting to root means XEmbed termination
+                active = false;
+            } else {
+                // continue XEmbed with a new parent
+                server = newParent;
+                embedded.notifyStarted();
+            }
+        }
     }
     boolean requestFocus() {
         if (active && embedded.focusAllowedFor()) {
@@ -201,12 +235,16 @@
     }
 
     void registerAccelerator(AWTKeyStroke stroke, int id) {
-        long sym = getX11KeySym(stroke);
-        long mods = getX11Mods(stroke);
-        sendMessage(server, XEMBED_REGISTER_ACCELERATOR, id, sym, mods);
+        if (active) {
+            long sym = getX11KeySym(stroke);
+            long mods = getX11Mods(stroke);
+            sendMessage(server, XEMBED_REGISTER_ACCELERATOR, id, sym, mods);
+        }
     }
     void unregisterAccelerator(int id) {
-        sendMessage(server, XEMBED_UNREGISTER_ACCELERATOR, id, 0, 0);
+        if (active) {
+            sendMessage(server, XEMBED_UNREGISTER_ACCELERATOR, id, 0, 0);
+        }
     }
 
     long getX11KeySym(AWTKeyStroke stroke) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java	Wed Nov 26 16:25:16 2008 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java	Fri Dec 19 16:04:04 2008 +0300
@@ -63,7 +63,10 @@
     void postInit(XCreateWindowParams params) {
         super.postInit(params);
         if (embedder != null) {
-            embedder.install(this);
+            // install X11 event dispatcher
+            embedder.setClient(this);
+            // reparent to XEmbed server
+            embedder.install();
         } else if (getParentWindowHandle() != 0) {
             XToolkit.awtLock();
             try {
@@ -77,6 +80,15 @@
         }
     }
 
+    @Override
+    public void dispose() {
+        if (embedder != null) {
+            // uninstall X11 event dispatcher
+            embedder.setClient(null);
+        }
+        super.dispose();
+    }
+
     public void updateMinimumSize() {
     }
 
@@ -249,6 +261,14 @@
         // XEmbed.
         updateDropTarget();
     }
+    void notifyStopped() {
+        if (embedder != null && embedder.isActive()) {
+            for (int i = strokes.size() - 1; i >= 0; i--) {
+                embedder.unregisterAccelerator(i);
+            }
+        }
+    }
+
     long getFocusTargetWindow() {
         return getWindow();
     }