--- a/jdk/src/share/classes/javax/swing/BufferStrategyPaintManager.java Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/src/share/classes/javax/swing/BufferStrategyPaintManager.java Wed Oct 12 12:25:03 2011 -0700
@@ -24,20 +24,17 @@
*/
package javax.swing;
-import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.reflect.*;
import java.lang.ref.WeakReference;
-import java.security.AccessController;
import java.util.*;
import com.sun.java.swing.SwingUtilities3;
import sun.awt.SubRegionShowable;
import sun.java2d.SunGraphics2D;
-import sun.security.action.GetPropertyAction;
import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
import sun.awt.SunToolkit;
import sun.util.logging.PlatformLogger;
@@ -120,10 +117,6 @@
*/
private JComponent rootJ;
/**
- * Parent Applet/Window for the current paint/copyArea
- */
- private Container root;
- /**
* Location of component being painted relative to root.
*/
private int xOffset;
@@ -278,7 +271,9 @@
public boolean paint(JComponent paintingComponent,
JComponent bufferComponent, Graphics g,
int x, int y, int w, int h) {
- if (prepare(paintingComponent, true, x, y, w, h)) {
+ Container root = fetchRoot(paintingComponent);
+
+ if (prepare(paintingComponent, root, true, x, y, w, h)) {
if ((g instanceof SunGraphics2D) &&
((SunGraphics2D)g).getDestination() == root) {
// BufferStrategy may have already constrained the Graphics. To
@@ -319,7 +314,9 @@
//
// If the buffer isn't in sync there is no point in doing a copyArea,
// it has garbage.
- if (prepare(c, false, 0, 0, 0, 0) && bufferInfo.isInSync()) {
+ Container root = fetchRoot(c);
+
+ if (prepare(c, root, false, 0, 0, 0, 0) && bufferInfo.isInSync()) {
if (clip) {
Rectangle cBounds = c.getVisibleRect();
int relX = xOffset + x;
@@ -500,14 +497,14 @@
*
* @return true if should use buffering per window in painting.
*/
- private boolean prepare(JComponent c, boolean isPaint, int x, int y,
+ private boolean prepare(JComponent c, Container root, boolean isPaint, int x, int y,
int w, int h) {
if (bsg != null) {
bsg.dispose();
bsg = null;
}
bufferStrategy = null;
- if (fetchRoot(c)) {
+ if (root != null) {
boolean contentsLost = false;
BufferInfo bufferInfo = getBufferInfo(root);
if (bufferInfo == null) {
@@ -567,10 +564,10 @@
return false;
}
- private boolean fetchRoot(JComponent c) {
+ private Container fetchRoot(JComponent c) {
boolean encounteredHW = false;
rootJ = c;
- root = c;
+ Container root = c;
xOffset = yOffset = 0;
while (root != null &&
(!(root instanceof Window) &&
@@ -597,7 +594,7 @@
// heavyweights. If we didn't do this when we
// went to show the descendants of the nested hw
// you would see nothing, so, we bail out here.
- return false;
+ return null;
}
}
}
@@ -613,11 +610,11 @@
// bit tricky with Swing. This gives a good approximation
// of the various ways to turn on double buffering for
// components.
- return true;
+ return root;
}
}
// Don't do true double buffering.
- return false;
+ return null;
}
/**
--- a/jdk/src/solaris/native/sun/awt/splashscreen/splashscreen_sys.c Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/src/solaris/native/sun/awt/splashscreen/splashscreen_sys.c Wed Oct 12 12:25:03 2011 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -334,6 +334,7 @@
XDestroyImage(ximage);
SplashRemoveDecoration(splash);
XMapWindow(splash->display, splash->window);
+ XFlush(splash->display);
}
void SplashReconfigureNow(Splash * splash) {
--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Wed Oct 12 12:25:03 2011 -0700
@@ -615,6 +615,14 @@
_dispose();
}
+ public void disposeLater() {
+ postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() {
+ public void run() {
+ dispose();
+ }
+ }));
+ }
+
public synchronized void setForeground(Color c) {
foreground = c;
_setForeground(c.getRGB());
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Oct 12 12:25:03 2011 -0700
@@ -183,6 +183,7 @@
jmethodID AwtComponent::getLocationOnScreenMID;
jmethodID AwtComponent::replaceSurfaceDataMID;
jmethodID AwtComponent::replaceSurfaceDataLaterMID;
+jmethodID AwtComponent::disposeLaterMID;
HKL AwtComponent::m_hkl = ::GetKeyboardLayout(0);
LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0));
@@ -246,6 +247,7 @@
m_hCursorCache = NULL;
m_bSubclassed = FALSE;
+ m_bPauseDestroy = FALSE;
m_MessagesProcessing = 0;
m_wheelRotationAmount = 0;
@@ -319,6 +321,12 @@
m_brushBackground = NULL;
}
+ if (m_bPauseDestroy) {
+ // AwtComponent::WmNcDestroy could be released now
+ m_bPauseDestroy = FALSE;
+ m_hwnd = NULL;
+ }
+
// The component instance is deleted using AwtObject::Dispose() method
AwtObject::Dispose();
}
@@ -1377,6 +1385,7 @@
case WM_CREATE: mr = WmCreate(); break;
case WM_CLOSE: mr = WmClose(); break;
case WM_DESTROY: mr = WmDestroy(); break;
+ case WM_NCDESTROY: mr = WmNcDestroy(); break;
case WM_ERASEBKGND:
mr = WmEraseBkgnd((HDC)wParam, *(BOOL*)&retValue); break;
@@ -1965,10 +1974,24 @@
*/
MsgRouting AwtComponent::WmDestroy()
{
- // fix for 6259348: we should enter the SyncCall critical section before
- // disposing the native object, that is value 1 of lParam is intended for
- if(m_peerObject != NULL) { // is not being terminating
- AwtToolkit::GetInstance().SendMessage(WM_AWT_DISPOSE, (WPARAM)m_peerObject, (LPARAM)1);
+ return mrConsume;
+}
+
+/*
+ * This message should only be received when a window is destroyed by
+ * Windows, and not Java. It is sent only after child windows were destroyed.
+ */
+MsgRouting AwtComponent::WmNcDestroy()
+{
+ if (m_peerObject != NULL) { // is not being terminating
+ // Stay in this handler until AwtComponent::Dispose is called.
+ m_bPauseDestroy = TRUE;
+
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+ // Post invocation event for WObjectPeer.dispose to EDT
+ env->CallVoidMethod(m_peerObject, AwtComponent::disposeLaterMID);
+ // Wait until AwtComponent::Dispose is called
+ AwtToolkit::GetInstance().PumpToDestroy(this);
}
return mrConsume;
@@ -6300,6 +6323,7 @@
env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
AwtComponent::replaceSurfaceDataLaterMID =
env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
+ AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
DASSERT(AwtComponent::xID);
DASSERT(AwtComponent::yID);
@@ -6318,6 +6342,8 @@
DASSERT(AwtComponent::getLocationOnScreenMID);
DASSERT(AwtComponent::replaceSurfaceDataMID);
DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
+ DASSERT(AwtComponent::disposeLaterMID);
+
CATCH_BAD_ALLOC;
}
--- a/jdk/src/windows/native/sun/windows/awt_Component.h Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h Wed Oct 12 12:25:03 2011 -0700
@@ -119,6 +119,7 @@
static jmethodID getLocationOnScreenMID;
static jmethodID replaceSurfaceDataMID;
static jmethodID replaceSurfaceDataLaterMID;
+ static jmethodID disposeLaterMID;
static const UINT WmAwtIsComponent;
static jint * masks; //InputEvent mask array
@@ -490,6 +491,7 @@
virtual MsgRouting WmCreate() {return mrDoDefault;}
virtual MsgRouting WmClose() {return mrDoDefault;}
virtual MsgRouting WmDestroy();
+ virtual MsgRouting WmNcDestroy();
virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
{
@@ -711,6 +713,10 @@
return m_MessagesProcessing == 0;
}
+ BOOL IsDestroyPaused() const {
+ return m_bPauseDestroy;
+ }
+
protected:
static AwtComponent* GetComponentImpl(HWND hWnd);
@@ -752,6 +758,7 @@
UINT m_mouseButtonClickAllowed;
BOOL m_bSubclassed;
+ BOOL m_bPauseDestroy;
COLORREF m_colorForeground;
COLORREF m_colorBackground;
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Wed Oct 12 12:25:03 2011 -0700
@@ -733,26 +733,13 @@
return 0;
}
case WM_AWT_DISPOSE: {
- BOOL canDispose = TRUE;
- CriticalSection &syncCS = AwtToolkit::GetInstance().GetSyncCS();
- int shouldEnterCriticalSection = (int)lParam;
- if (shouldEnterCriticalSection == 1) {
- canDispose = syncCS.TryEnter();
- }
- if (canDispose) {
- if(wParam != NULL) {
- jobject self = (jobject)wParam;
- AwtObject *o = (AwtObject *) JNI_GET_PDATA(self);
- env->DeleteGlobalRef(self);
- if(o != NULL && theAwtObjectList.Remove(o)) {
- o->Dispose();
- }
- if (shouldEnterCriticalSection) {
- syncCS.Leave();
- }
+ if(wParam != NULL) {
+ jobject self = (jobject)wParam;
+ AwtObject *o = (AwtObject *) JNI_GET_PDATA(self);
+ env->DeleteGlobalRef(self);
+ if(o != NULL && theAwtObjectList.Remove(o)) {
+ o->Dispose();
}
- } else {
- AwtToolkit::GetInstance().PostMessage(WM_AWT_DISPOSE, wParam, lParam);
}
return 0;
}
@@ -1340,25 +1327,46 @@
while (!m_breakMessageLoop && (*lpPeekMessageFunc)(msg)) {
foundOne = TRUE;
- if (msg.message == WM_QUIT) {
- m_breakMessageLoop = TRUE;
- m_messageLoopResult = static_cast<UINT>(msg.wParam);
- if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
- ::PostQuitMessage(static_cast<int>(msg.wParam)); // make sure all loops exit
- break;
- }
- else if (msg.message != WM_NULL) {
- /*
- * The AWT in standalone mode (that is, dynamically loaded from the
- * Java VM) doesn't have any translation tables to worry about, so
- * TranslateAccelerator isn't called.
- */
-
- ::TranslateMessage(&msg);
- ::DispatchMessage(&msg);
+ ProcessMsg(msg);
+ }
+ return foundOne;
+}
+
+void AwtToolkit::PumpToDestroy(class AwtComponent* p)
+{
+ MSG msg;
+
+ DASSERT(AwtToolkit::PrimaryIdleFunc != NULL);
+ DASSERT(AwtToolkit::CommonPeekMessageFunc != NULL);
+
+ while (p->IsDestroyPaused() && !m_breakMessageLoop) {
+
+ PrimaryIdleFunc();
+
+ while (p->IsDestroyPaused() && !m_breakMessageLoop && CommonPeekMessageFunc(msg)) {
+ ProcessMsg(msg);
}
}
- return foundOne;
+}
+
+void AwtToolkit::ProcessMsg(MSG& msg)
+{
+ if (msg.message == WM_QUIT) {
+ m_breakMessageLoop = TRUE;
+ m_messageLoopResult = static_cast<UINT>(msg.wParam);
+ if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
+ ::PostQuitMessage(static_cast<int>(msg.wParam)); // make sure all loops exit
+ }
+ else if (msg.message != WM_NULL) {
+ /*
+ * The AWT in standalone mode (that is, dynamically loaded from the
+ * Java VM) doesn't have any translation tables to worry about, so
+ * TranslateAccelerator isn't called.
+ */
+
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
}
VOID CALLBACK
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h Wed Oct 12 12:25:03 2011 -0700
@@ -305,6 +305,8 @@
UINT MessageLoop(IDLEPROC lpIdleFunc, PEEKMESSAGEPROC lpPeekMessageFunc);
BOOL PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc);
+ void PumpToDestroy(class AwtComponent* p);
+ void ProcessMsg(MSG& msg);
BOOL PreProcessMsg(MSG& msg);
BOOL PreProcessMouseMsg(class AwtComponent* p, MSG& msg);
BOOL PreProcessKeyMsg(class AwtComponent* p, MSG& msg);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JColorChooser/Test6827032.java Wed Oct 12 12:25:03 2011 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6827032
+ * @summary Color chooser with drag enabled shouldn't throw NPE
+ * @author Peter Zhelezniakov
+ * @library ../regtesthelpers
+ */
+
+import sun.awt.SunToolkit;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.*;
+import javax.swing.plaf.nimbus.NimbusLookAndFeel;
+
+
+public class Test6827032 {
+
+ private static volatile Point point;
+ private static JColorChooser cc;
+
+ public static void main(String[] args) throws Exception {
+ UIManager.setLookAndFeel(new NimbusLookAndFeel());
+
+ Robot robot = new Robot();
+ robot.setAutoDelay(50);
+
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ createAndShowGUI();
+ }
+ });
+
+ toolkit.realSync();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ Component previewPanel = Util.findSubComponent(cc, "javax.swing.colorchooser.DefaultPreviewPanel");
+ point = previewPanel.getLocationOnScreen();
+ }
+ });
+
+ point.translate(5, 5);
+
+ robot.mouseMove(point.x, point.y);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ }
+
+
+ private static void createAndShowGUI() {
+ JFrame frame = new JFrame(Test6827032.class.getName());
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ cc = new JColorChooser();
+ cc.setDragEnabled(true);
+ frame.add(cc);
+ frame.pack();
+ frame.setVisible(true);
+ }
+}
--- a/jdk/test/javax/swing/regtesthelpers/Util.java Wed Jul 05 17:52:45 2017 +0200
+++ b/jdk/test/javax/swing/regtesthelpers/Util.java Wed Oct 12 12:25:03 2011 -0700
@@ -116,4 +116,28 @@
System.out.println("Got OOME");
}
+
+ /**
+ * Find a sub component by class name.
+ * Always run this method on the EDT thread
+ */
+ public static Component findSubComponent(Component parent, String className) {
+ String parentClassName = parent.getClass().getName();
+
+ if (parentClassName.contains(className)) {
+ return parent;
+ }
+
+ if (parent instanceof Container) {
+ for (Component child : ((Container) parent).getComponents()) {
+ Component subComponent = findSubComponent(child, className);
+
+ if (subComponent != null) {
+ return subComponent;
+ }
+ }
+ }
+
+ return null;
+ }
}