changeset 1056:ae27b7949714

6809227: poor performance on Panel.Add() method in jdk6 Reviewed-by: art, anthony
author dcherepanov
date Wed, 04 Mar 2009 13:05:56 +0300
parents a2082e850247
children e7205c5dd3b7
files make/sun/xawt/mapfile-vers src/share/classes/java/awt/Component.java src/share/classes/java/awt/Container.java src/share/classes/java/awt/peer/ComponentPeer.java src/share/classes/java/awt/peer/ContainerPeer.java src/share/classes/sun/awt/NullComponentPeer.java src/solaris/classes/sun/awt/X11/XComponentPeer.java src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java src/solaris/classes/sun/awt/X11/XlibWrapper.java src/solaris/native/sun/xawt/XlibWrapper.c src/windows/classes/sun/awt/windows/WComponentPeer.java src/windows/classes/sun/awt/windows/WFileDialogPeer.java src/windows/classes/sun/awt/windows/WPrintDialogPeer.java src/windows/classes/sun/awt/windows/WScrollPanePeer.java src/windows/native/sun/windows/awt_Component.cpp src/windows/native/sun/windows/awt_Component.h src/windows/native/sun/windows/awt_Panel.cpp src/windows/native/sun/windows/awt_Panel.h
diffstat 18 files changed, 141 insertions(+), 234 deletions(-) [+]
line wrap: on
line diff
--- a/make/sun/xawt/mapfile-vers	Tue Mar 03 13:54:47 2009 +0300
+++ b/make/sun/xawt/mapfile-vers	Wed Mar 04 13:05:56 2009 +0300
@@ -93,6 +93,7 @@
         Java_sun_awt_X11_XlibWrapper_XGetWMHints;
         Java_sun_awt_X11_XlibWrapper_XShapeQueryExtension;
         Java_sun_awt_X11_XlibWrapper_SetRectangularShape;
+        Java_sun_awt_X11_XlibWrapper_SetZOrder;
         Java_sun_awt_X11_XToolkit_initIDs;
         Java_sun_awt_X11_XWindow_getNativeColor;
         Java_sun_awt_X11_XWindow_getWMInsets;
--- a/src/share/classes/java/awt/Component.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/share/classes/java/awt/Component.java	Wed Mar 04 13:05:56 2009 +0300
@@ -6656,23 +6656,7 @@
 
 
             // Update stacking order
-            if (parent != null && parent.peer != null) {
-                ContainerPeer parentContPeer = (ContainerPeer) parent.peer;
-                // if our parent is lightweight and we are not
-                // we should call restack on nearest heavyweight
-                // container.
-                if (parentContPeer instanceof LightweightPeer
-                    && ! (peer instanceof LightweightPeer))
-                {
-                    Container hwParent = getNativeContainer();
-                    if (hwParent != null && hwParent.peer != null) {
-                        parentContPeer = (ContainerPeer) hwParent.peer;
-                    }
-                }
-                if (parentContPeer.isRestackSupported()) {
-                    parentContPeer.restack();
-                }
-            }
+            peer.setZOrder(getHWPeerAboveMe());
 
             if (!isAddNotifyComplete) {
                 mixOnShowing();
@@ -9546,6 +9530,27 @@
         return nextAbove < 0 ? -1 : nextAbove;
     }
 
+    final ComponentPeer getHWPeerAboveMe() {
+        checkTreeLock();
+
+        Container cont = getContainer();
+        int indexAbove = getSiblingIndexAbove();
+
+        while (cont != null) {
+            for (int i = indexAbove; i > -1; i--) {
+                Component comp = cont.getComponent(i);
+                if (comp != null && comp.isDisplayable() && !comp.isLightweight()) {
+                    return comp.getPeer();
+                }
+            }
+
+            indexAbove = cont.getSiblingIndexAbove();
+            cont = cont.getContainer();
+        }
+
+        return null;
+    }
+
     final int getSiblingIndexBelow() {
         checkTreeLock();
         Container parent = getContainer();
--- a/src/share/classes/java/awt/Container.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/share/classes/java/awt/Container.java	Wed Mar 04 13:05:56 2009 +0300
@@ -649,10 +649,7 @@
             // each HW descendant independently.
             return !comp.peer.isReparentSupported();
         } else {
-            // if container didn't change we still might need to recreate component's window as
-            // changes to zorder should be reflected in native window stacking order and it might
-            // not be supported by the platform. This is important only for heavyweight child
-            return !((ContainerPeer)(newNativeContainer.peer)).isRestackSupported();
+            return false;
         }
     }
 
@@ -809,11 +806,6 @@
         if (peer != null) {
             if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
                 comp.addNotify();
-                // New created peer creates component on top of the stacking order
-                Container newNativeContainer = getHeavyweightContainer();
-                if (((ContainerPeer)newNativeContainer.getPeer()).isRestackSupported()) {
-                    ((ContainerPeer)newNativeContainer.getPeer()).restack();
-                }
             } else { // Both container and child have peers, it means child peer should be reparented.
                 // In both cases we need to reparent native widgets.
                 Container newNativeContainer = getHeavyweightContainer();
@@ -822,13 +814,8 @@
                     // Native container changed - need to reparent native widgets
                     newNativeContainer.reparentChild(comp);
                 }
-                // If component still has a peer and it is either container or heavyweight
-                // and restack is supported we have to restack native windows since order might have changed
-                if ((!comp.isLightweight() || (comp instanceof Container))
-                    && ((ContainerPeer)newNativeContainer.getPeer()).isRestackSupported())
-                {
-                    ((ContainerPeer)newNativeContainer.getPeer()).restack();
-                }
+                comp.peer.setZOrder(comp.getHWPeerAboveMe());
+
                 if (!comp.isLightweight() && isLightweight()) {
                     // If component is heavyweight and one of the containers is lightweight
                     // the location of the component should be fixed.
@@ -2607,13 +2594,6 @@
             for (int i = 0; i < component.size(); i++) {
                 component.get(i).addNotify();
             }
-            // Update stacking order if native platform allows
-            ContainerPeer cpeer = (ContainerPeer)peer;
-            if (cpeer.isRestackSupported()) {
-                cpeer.restack();
-            }
-
-
         }
     }
 
--- a/src/share/classes/java/awt/peer/ComponentPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/share/classes/java/awt/peer/ComponentPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -540,6 +540,12 @@
     void applyShape(Region shape);
 
     /**
+     * Lowers this component at the bottom of the above HW peer. If the above parameter
+     * is null then the method places this component at the top of the Z-order.
+     */
+    void setZOrder(ComponentPeer above);
+
+    /**
      * Updates internal data structures related to the component's GC.
      *
      * @since 1.7
--- a/src/share/classes/java/awt/peer/ContainerPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/share/classes/java/awt/peer/ContainerPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -76,21 +76,4 @@
      * @see Container#validateTree()
      */
     void endLayout();
-
-    /**
-     * Restacks native windows - children of this native window - according to
-     * Java container order.
-     *
-     * @since 1.5
-     */
-    void restack();
-
-    /**
-     * Indicates availability of restacking operation in this container.
-     *
-     * @return Returns true if restack is supported, false otherwise
-     *
-     * @since 1.5
-     */
-    boolean isRestackSupported();
 }
--- a/src/share/classes/sun/awt/NullComponentPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/share/classes/sun/awt/NullComponentPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -278,19 +278,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /**
-     * @see java.awt.peer.ContainerPeer#restack
-     */
-    public void restack() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @see java.awt.peer.ContainerPeer#isRestackSupported
-     */
-    public boolean isRestackSupported() {
-        return false;
-    }
     public void layout() {
     }
 
@@ -306,6 +293,13 @@
     public void applyShape(Region shape) {
     }
 
+    /**
+     * Lowers this component at the bottom of the above HW peer. If the above parameter
+     * is null then the method places this component at the top of the Z-order.
+     */
+    public void setZOrder(ComponentPeer above) {
+    }
+
     public void updateGraphicsData(GraphicsConfiguration gc) {}
 
     public GraphicsConfiguration getAppropriateGraphicsConfiguration(
--- a/src/solaris/classes/sun/awt/X11/XComponentPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XComponentPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -1415,59 +1415,21 @@
         }
     }
 
-    public void restack() {
-        synchronized(target.getTreeLock()) {
-            // Build the list of X windows in the window corresponding to this container
-            // This list is already in correct Java stacking order
-            Container cont = (Container)target;
-            Vector order = new Vector(cont.getComponentCount());
-            HashSet set = new HashSet();
+    /**
+     * Lowers this component at the bottom of the above HW peer. If the above parameter
+     * is null then the method places this component at the top of the Z-order.
+     */
+    public void setZOrder(ComponentPeer above) {
+        long aboveWindow = (above != null) ? ((XComponentPeer)above).getWindow() : 0;
 
-            addTree(order, set, cont);
-
-            XToolkit.awtLock();
-            try {
-                // Get the current list of X window in X window. Some of the windows
-                // might be only native
-                XQueryTree qt = new XQueryTree(getContentWindow());
-                try {
-                    if (qt.execute() != 0) {
-                        if (qt.get_nchildren() != 0) {
-                            long pchildren = qt.get_children();
-                            int j = 0; // index to insert
-                            for (int i = 0; i < qt.get_nchildren(); i++) {
-                                Long w = Long.valueOf(Native.getLong(pchildren, i));
-                                if (!set.contains(w)) {
-                                    set.add(w);
-                                    order.add(j++, w);
-                                }
-                            }
-                        }
-                    }
-
-                    if (order.size() != 0) {
-                        // Create native array of the windows
-                        long windows = Native.allocateLongArray(order.size());
-                        Native.putLong(windows, order);
-
-                        // Restack native window according to the new order
-                        XlibWrapper.XRestackWindows(XToolkit.getDisplay(), windows, order.size());
-
-                        XlibWrapper.unsafe.freeMemory(windows);
-                    }
-                } finally {
-                    qt.dispose();
-                }
-            } finally {
-                XToolkit.awtUnlock();
-            }
+        XToolkit.awtLock();
+        try{
+            XlibWrapper.SetZOrder(XToolkit.getDisplay(), getWindow(), aboveWindow);
+        }finally{
+            XToolkit.awtUnlock();
         }
     }
 
-    public boolean isRestackSupported() {
-        return true;
-    }
-
     private void addTree(Collection order, Set set, Container cont) {
         for (int i = 0; i < cont.getComponentCount(); i++) {
             Component comp = cont.getComponent(i);
--- a/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -380,5 +380,8 @@
     public void applyShape(Region shape) {
     }
 
+    public void setZOrder(ComponentPeer above) {
+    }
+
     public void updateGraphicsData(GraphicsConfiguration gc) {}
 }
--- a/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Wed Mar 04 13:05:56 2009 +0300
@@ -533,6 +533,7 @@
     static native void SetRectangularShape(long display, long window,
             int lox, int loy, int hix, int hiy,
             sun.java2d.pipe.Region region);
+    static native void SetZOrder(long display, long window, long above);
 
 /* Global memory area used for X lib parameter passing */
 
--- a/src/solaris/native/sun/xawt/XlibWrapper.c	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/solaris/native/sun/xawt/XlibWrapper.c	Wed Mar 04 13:05:56 2009 +0300
@@ -1945,3 +1945,31 @@
                 ShapeBounding, 0, 0, None, ShapeSet);
     }
 }
+
+/*
+ * Class:     XlibWrapper
+ * Method:    SetZOrder
+ */
+
+JNIEXPORT void JNICALL
+Java_sun_awt_X11_XlibWrapper_SetZOrder
+(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong above)
+{
+    AWT_CHECK_HAVE_LOCK();
+
+    XWindowChanges wc;
+    wc.sibling = (Window)jlong_to_ptr(above);
+
+    unsigned int value_mask = CWStackMode;
+
+    if (above == 0) {
+        wc.stack_mode = Above;
+    } else {
+        wc.stack_mode = Below;
+        value_mask |= CWSibling;
+    }
+
+    XConfigureWindow((Display *)jlong_to_ptr(display),
+                     (Window)jlong_to_ptr(window),
+                     value_mask, &wc );
+}
--- a/src/windows/classes/sun/awt/windows/WComponentPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WComponentPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -941,4 +941,15 @@
         }
     }
 
+    /**
+     * Lowers this component at the bottom of the above component. If the above parameter
+     * is null then the method places this component at the top of the Z-order.
+     */
+    public void setZOrder(ComponentPeer above) {
+        long aboveHWND = (above != null) ? ((WComponentPeer)above).getHWnd() : 0;
+
+        setZOrder(aboveHWND);
+    }
+
+    private native void setZOrder(long above);
 }
--- a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -231,20 +231,6 @@
      */
     private static native void initIDs();
 
-    /**
-     * WFileDialogPeer doesn't have native pData so we don't do restack on it
-     * @see java.awt.peer.ContainerPeer#restack
-     */
-    public void restack() {
-    }
-
-    /**
-     * @see java.awt.peer.ContainerPeer#isRestackSupported
-     */
-    public boolean isRestackSupported() {
-        return false;
-    }
-
     // The effects are not supported for system dialogs.
     public void applyShape(sun.java2d.pipe.Region shape) {}
     public void setOpacity(float opacity) {}
--- a/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -143,20 +143,6 @@
      */
     private static native void initIDs();
 
-    /**
-     * WPrintDialogPeer doesn't have native pData so we don't do restack on it
-     * @see java.awt.peer.ContainerPeer#restack
-     */
-    public void restack() {
-    }
-
-    /**
-     * @see java.awt.peer.ContainerPeer#isRestackSupported
-     */
-    public boolean isRestackSupported() {
-        return false;
-    }
-
     // The effects are not supported for system dialogs.
     public void applyShape(sun.java2d.pipe.Region shape) {}
     public void setOpacity(float opacity) {}
--- a/src/windows/classes/sun/awt/windows/WScrollPanePeer.java	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/classes/sun/awt/windows/WScrollPanePeer.java	Wed Mar 04 13:05:56 2009 +0300
@@ -269,10 +269,4 @@
         }
     }
 
-    /**
-     * @see java.awt.peer.ContainerPeer#restack
-     */
-    public void restack() {
-        // Since ScrollPane can only have one child its restacking does nothing.
-    }
 }
--- a/src/windows/native/sun/windows/awt_Component.cpp	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/native/sun/windows/awt_Component.cpp	Wed Mar 04 13:05:56 2009 +0300
@@ -149,6 +149,11 @@
     jobject window;
     RECT *insets;
 };
+// Struct for _SetZOrder function
+struct SetZOrderStruct {
+    jobject component;
+    jlong above;
+};
 /************************************************************************/
 
 //////////////////////////////////////////////////////////////////////////
@@ -6170,6 +6175,33 @@
     delete data;
 }
 
+void AwtComponent::_SetZOrder(void *param) {
+    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+    SetZOrderStruct *data = (SetZOrderStruct *)param;
+    jobject self = data->component;
+    HWND above = HWND_TOP;
+    if (data->above != 0) {
+        above = reinterpret_cast<HWND>(data->above);
+    }
+
+    AwtComponent *c = NULL;
+
+    PDATA pData;
+    JNI_CHECK_PEER_GOTO(self, ret);
+
+    c = (AwtComponent *)pData;
+    if (::IsWindow(c->GetHWnd())) {
+        ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0,
+                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
+    }
+
+ret:
+    env->DeleteGlobalRef(self);
+
+    delete data;
+}
+
 void AwtComponent::PostUngrabEvent() {
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
     jobject target = GetTarget(env);
@@ -6896,6 +6928,21 @@
     CATCH_BAD_ALLOC;
 }
 
+JNIEXPORT void JNICALL
+Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above)
+{
+    TRY;
+
+    SetZOrderStruct * data = new SetZOrderStruct;
+    data->component = env->NewGlobalRef(self);
+    data->above = above;
+
+    AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data);
+    // global refs and data are deleted in _SetLower
+
+    CATCH_BAD_ALLOC;
+}
+
 } /* extern "C" */
 
 
--- a/src/windows/native/sun/windows/awt_Component.h	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/native/sun/windows/awt_Component.h	Wed Mar 04 13:05:56 2009 +0300
@@ -680,6 +680,7 @@
     static jintArray _CreatePrintedPixels(void *param);
     static jboolean _NativeHandlesWheelScrolling(void *param);
     static void _SetRectangularShape(void *param);
+    static void _SetZOrder(void *param);
 
     static HWND sm_focusOwner;
     static HWND sm_focusedWindow;
--- a/src/windows/native/sun/windows/awt_Panel.cpp	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/native/sun/windows/awt_Panel.cpp	Wed Mar 04 13:05:56 2009 +0300
@@ -34,70 +34,6 @@
 
 jfieldID AwtPanel::insets_ID;
 
-static char* AWTPANEL_RESTACK_MSG_1 = "Peers array is null";
-static char* AWTPANEL_RESTACK_MSG_2 = "Peer null in JNI";
-static char* AWTPANEL_RESTACK_MSG_3 = "Native resources unavailable";
-static char* AWTPANEL_RESTACK_MSG_4 = "Child peer is null";
-
-void* AwtPanel::Restack(void * param) {
-    TRY;
-
-    JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
-    jobjectArray peers = (jobjectArray)param;
-
-    int peerCount = env->GetArrayLength(peers);
-    if (peerCount < 1) {
-        env->DeleteGlobalRef(peers);
-        return AWTPANEL_RESTACK_MSG_1;
-    }
-
-    jobject self = env->GetObjectArrayElement(peers, 0);
-    // It's entirely possible that our native resources have been destroyed
-    // before our java peer - if we're dispose()d, for instance.
-    // Alert caller w/ IllegalComponentStateException.
-    if (self == NULL) {
-        env->DeleteGlobalRef(peers);
-        return AWTPANEL_RESTACK_MSG_2;
-    }
-    PDATA pData = JNI_GET_PDATA(self);
-    if (pData == NULL) {
-        env->DeleteGlobalRef(peers);
-        env->DeleteLocalRef(self);
-        return AWTPANEL_RESTACK_MSG_3;
-    }
-
-    AwtPanel* panel = (AwtPanel*)pData;
-
-    HWND prevWindow = 0;
-
-    for (int i = 1; i < peerCount; i++) {
-        jobject peer = env->GetObjectArrayElement(peers, i);
-        if (peer == NULL) {
-            // Nonsense
-            env->DeleteGlobalRef(peers);
-            env->DeleteLocalRef(self);
-            return  AWTPANEL_RESTACK_MSG_4;
-        }
-        PDATA child_pData = JNI_GET_PDATA(peer);
-        if (child_pData == NULL) {
-            env->DeleteLocalRef(peer);
-            env->DeleteGlobalRef(peers);
-            env->DeleteLocalRef(self);
-            return AWTPANEL_RESTACK_MSG_3;
-        }
-        AwtComponent* child_comp = (AwtComponent*)child_pData;
-        ::SetWindowPos(child_comp->GetHWnd(), prevWindow, 0, 0, 0, 0,
-                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
-        prevWindow = child_comp->GetHWnd();
-        env->DeleteLocalRef(peer);
-    }
-    env->DeleteGlobalRef(peers);
-    env->DeleteLocalRef(self);
-
-    CATCH_BAD_ALLOC_RET("Allocation error");
-    return NULL;
-}
-
 /************************************************************************
  * AwtPanel native methods
  */
@@ -116,18 +52,4 @@
     CATCH_BAD_ALLOC;
 }
 
-JNIEXPORT void JNICALL
-Java_sun_awt_windows_WPanelPeer_pRestack(JNIEnv *env, jobject self, jobjectArray peers) {
-
-    TRY;
-
-    const char * error = (const char*)AwtToolkit::GetInstance().InvokeFunction(AwtPanel::Restack, env->NewGlobalRef(peers));
-    if (error != NULL) {
-        JNU_ThrowByName(env, "java/awt/IllegalComponentStateException", error);
-    }
-
-    CATCH_BAD_ALLOC;
-}
-
-
 } /* extern "C" */
--- a/src/windows/native/sun/windows/awt_Panel.h	Tue Mar 03 13:54:47 2009 +0300
+++ b/src/windows/native/sun/windows/awt_Panel.h	Wed Mar 04 13:05:56 2009 +0300
@@ -35,11 +35,8 @@
 
 class AwtPanel {
 public:
-    static void* Restack(void * param);
-
     /* java.awt.Panel field ids */
     static jfieldID insets_ID;
-
 };
 
 #endif // AWT_PANEL_H