aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpchelko <none@none>2013-10-02 11:32:56 +0400
committerpchelko <none@none>2013-10-02 11:32:56 +0400
commit8af3b1fad9c4c9b966d7941cf562fc7f10396ede (patch)
treee2ed4f80c05e06bd51cc9c79a1f05d43d05417b8
parentc539e36308ac61475df89e02c1d88091e203c51c (diff)
8024163: [macosx] NullPointerException at javax.swing.TransferHandler$DropHandler.handleDrag since jdk8b93, 7u40b28
Reviewed-by: anthony, serb
-rw-r--r--src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java71
-rw-r--r--src/macosx/native/sun/awt/CDropTarget.m5
-rw-r--r--test/java/awt/dnd/DropTargetEnterExitTest/ExtraDragEnterTest.java133
-rw-r--r--test/java/awt/dnd/DropTargetEnterExitTest/MissedDragExitTest.java128
4 files changed, 314 insertions, 23 deletions
diff --git a/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java b/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java
index ad6171fe6..4c71a2249 100644
--- a/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java
+++ b/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java
@@ -26,6 +26,7 @@
package sun.lwawt.macosx;
import java.awt.*;
+import java.awt.dnd.DropTarget;
import sun.awt.dnd.SunDropTargetContextPeer;
import sun.awt.dnd.SunDropTargetEvent;
@@ -38,7 +39,7 @@ final class CDropTargetContextPeer extends SunDropTargetContextPeer {
private long fNativeDropTransfer = 0;
private long fNativeDataAvailable = 0;
private Object fNativeData = null;
- private boolean insideTarget = true;
+ private DropTarget insideTarget = null;
Object awtLockAccess = new Object();
@@ -88,26 +89,19 @@ final class CDropTargetContextPeer extends SunDropTargetContextPeer {
return fNativeData;
}
- // We need to take care of dragExit message because for some reason it is not being
- // generated for lightweight components
+ // We need to take care of dragEnter and dragExit messages because
+ // native system generates them only for heavyweights
@Override
protected void processMotionMessage(SunDropTargetEvent event, boolean operationChanged) {
- Component eventSource = (Component)event.getComponent();
- Point screenPoint = event.getPoint();
- SwingUtilities.convertPointToScreen(screenPoint, eventSource);
- Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x,
- eventSource.getLocationOnScreen().y,
- eventSource.getWidth(), eventSource.getHeight());
- if(insideTarget) {
- if(!screenBounds.contains(screenPoint)) {
+ boolean eventInsideTarget = isEventInsideTarget(event);
+ if (event.getComponent().getDropTarget() == insideTarget) {
+ if (!eventInsideTarget) {
processExitMessage(event);
- insideTarget = false;
return;
}
} else {
- if(screenBounds.contains(screenPoint)) {
+ if (eventInsideTarget) {
processEnterMessage(event);
- insideTarget = true;
} else {
return;
}
@@ -115,19 +109,54 @@ final class CDropTargetContextPeer extends SunDropTargetContextPeer {
super.processMotionMessage(event, operationChanged);
}
+ /**
+ * Could be called when DnD enters a heavyweight or synthesized in processMotionMessage
+ */
+ @Override
+ protected void processEnterMessage(SunDropTargetEvent event) {
+ Component c = event.getComponent();
+ DropTarget dt = event.getComponent().getDropTarget();
+ if (isEventInsideTarget(event)
+ && dt != insideTarget
+ && c.isShowing()
+ && dt != null
+ && dt.isActive()) {
+ insideTarget = dt;
+ super.processEnterMessage(event);
+ }
+ }
+
+ /**
+ * Could be called when DnD exits a heavyweight or synthesized in processMotionMessage
+ */
+ @Override
+ protected void processExitMessage(SunDropTargetEvent event) {
+ if (event.getComponent().getDropTarget() == insideTarget) {
+ insideTarget = null;
+ super.processExitMessage(event);
+ }
+ }
+
@Override
protected void processDropMessage(SunDropTargetEvent event) {
- Component eventSource = (Component)event.getComponent();
- Point screenPoint = event.getPoint();
- SwingUtilities.convertPointToScreen(screenPoint, eventSource);
- Rectangle screenBounds = new Rectangle(eventSource.getLocationOnScreen().x,
- eventSource.getLocationOnScreen().y,
- eventSource.getWidth(), eventSource.getHeight());
- if(screenBounds.contains(screenPoint)) {
+ if (isEventInsideTarget(event)) {
super.processDropMessage(event);
+ insideTarget = null;
}
}
+ private boolean isEventInsideTarget(SunDropTargetEvent event) {
+ Component eventSource = event.getComponent();
+ Point screenPoint = event.getPoint();
+ SwingUtilities.convertPointToScreen(screenPoint, eventSource);
+ Point locationOnScreen = eventSource.getLocationOnScreen();
+ Rectangle screenBounds = new Rectangle(locationOnScreen.x,
+ locationOnScreen.y,
+ eventSource.getWidth(),
+ eventSource.getHeight());
+ return screenBounds.contains(screenPoint);
+ }
+
@Override
protected int postDropTargetEvent(Component component, int x, int y, int dropAction,
int actions, long[] formats, long nativeCtxt, int eventID,
diff --git a/src/macosx/native/sun/awt/CDropTarget.m b/src/macosx/native/sun/awt/CDropTarget.m
index 260bbdec8..a1c47f8ad 100644
--- a/src/macosx/native/sun/awt/CDropTarget.m
+++ b/src/macosx/native/sun/awt/CDropTarget.m
@@ -477,6 +477,8 @@ extern JNFClassInfo jc_CDropTargetContextPeer;
sDraggingExited = FALSE;
sDraggingLocation = [sender draggingLocation];
NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
+ javaLocation.y = fView.window.frame.size.height - javaLocation.y;
+
DLog5(@"+ dragEnter: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);
////////// BEGIN Calculate the current drag actions //////////
@@ -570,8 +572,7 @@ extern JNFClassInfo jc_CDropTargetContextPeer;
// Should we notify Java things have changed?
if (sDraggingError == FALSE && notifyJava) {
NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
- // For some reason even after the convertPoint drag events come with the y coordinate reverted
- javaLocation.y = fView.window.frame.size.height - javaLocation.y;
+ javaLocation.y = fView.window.frame.size.height - javaLocation.y;
//DLog5(@" : dragMoved: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);
jlongArray formats = sDraggingFormats;
diff --git a/test/java/awt/dnd/DropTargetEnterExitTest/ExtraDragEnterTest.java b/test/java/awt/dnd/DropTargetEnterExitTest/ExtraDragEnterTest.java
new file mode 100644
index 000000000..16d938f98
--- /dev/null
+++ b/test/java/awt/dnd/DropTargetEnterExitTest/ExtraDragEnterTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013, 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 8024163
+ * @summary Checks the dragEnter event is correctly generated
+ * @library ../../regtesthelpers
+ * @build Util
+ * @compile ExtraDragEnterTest.java
+ * @run main/othervm ExtraDragEnterTest
+ * @author Petr Pchelko
+ */
+
+import test.java.awt.regtesthelpers.Util;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.StringSelection;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.event.InputEvent;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class ExtraDragEnterTest {
+
+ private static final int FRAME_SIZE = 100;
+ private static final int FRAME_LOCATION = 100;
+
+ private static AtomicInteger dragEnterCalled = new AtomicInteger(0);
+
+ private static volatile Panel mainPanel;
+ private static volatile Frame f;
+
+ private static void initAndShowUI() {
+ f = new Frame("Test frame");
+ f.setBounds(FRAME_LOCATION,FRAME_LOCATION,FRAME_SIZE,FRAME_SIZE);
+ mainPanel = new Panel();
+ mainPanel.setBounds(0, 0, FRAME_SIZE, FRAME_SIZE);
+ mainPanel.setBackground(Color.black);
+ mainPanel.setLayout(new GridLayout(2, 1));
+
+ final DraggablePanel dragSource = new DraggablePanel();
+ dragSource.setBackground(Color.yellow);
+ dragSource.setDropTarget(null);
+ mainPanel.add(dragSource);
+
+ Panel dropTarget = new Panel();
+ dropTarget.setBackground(Color.red);
+ DropTarget dt = new DropTarget(dropTarget, new DropTargetAdapter() {
+ @Override public void drop(DropTargetDropEvent dtde) { }
+
+ @Override
+ public void dragEnter(DropTargetDragEvent dtde) {
+ dragEnterCalled.incrementAndGet();
+ }
+ });
+ dropTarget.setDropTarget(dt);
+ mainPanel.add(dropTarget);
+
+ f.add(mainPanel);
+ f.setVisible(true);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ try {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ initAndShowUI();
+ }
+ });
+
+ Robot r = new Robot();
+ Util.waitForIdle(r);
+ Point leftCorner = new Point(mainPanel.getLocationOnScreen());
+ leftCorner.translate(5, 5);
+ Point rightCorner = new Point(mainPanel.getLocationOnScreen());
+ rightCorner.translate(mainPanel.getWidth(), mainPanel.getHeight());
+ rightCorner.translate(-5, -5);
+ Util.drag(r, leftCorner, rightCorner, InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(r);
+
+ int called = dragEnterCalled.get();
+ if (called != 1) {
+ throw new RuntimeException("Failed. Drag enter called " + called + " times. Expected 1" );
+ }
+ } finally {
+ if (f != null) {
+ f.dispose();
+ }
+ }
+ }
+
+ private static class DraggablePanel extends Panel implements DragGestureListener {
+
+ public DraggablePanel() {
+ (new DragSource()).createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, this);
+ }
+
+ @Override
+ public void dragGestureRecognized(DragGestureEvent dge) {
+ dge.startDrag(Cursor.getDefaultCursor(), new StringSelection("test"));
+ }
+ }
+}
diff --git a/test/java/awt/dnd/DropTargetEnterExitTest/MissedDragExitTest.java b/test/java/awt/dnd/DropTargetEnterExitTest/MissedDragExitTest.java
new file mode 100644
index 000000000..3863667c8
--- /dev/null
+++ b/test/java/awt/dnd/DropTargetEnterExitTest/MissedDragExitTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2013, 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 8024163
+ * @summary Checks that dragExit is generated when the new DropTarget is created under the drag
+ * @library ../../regtesthelpers
+ * @build Util
+ * @compile MissedDragExitTest.java
+ * @run main/othervm MissedDragExitTest
+ * @author Petr Pchelko
+ */
+
+import test.java.awt.regtesthelpers.Util;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.StringSelection;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.event.InputEvent;
+
+public class MissedDragExitTest {
+
+ private static final int FRAME_SIZE = 100;
+ private static final int FRAME_LOCATION = 100;
+
+ private static volatile boolean dragExitCalled = false;
+
+ private static volatile Frame f;
+
+ private static void initAndShowUI() {
+ f = new Frame("Test frame");
+ f.setBounds(FRAME_LOCATION,FRAME_LOCATION,FRAME_SIZE,FRAME_SIZE);
+
+ final DraggablePanel dragSource = new DraggablePanel();
+ dragSource.setBackground(Color.yellow);
+ DropTarget dt = new DropTarget(dragSource, new DropTargetAdapter() {
+ @Override public void drop(DropTargetDropEvent dtde) { }
+
+ @Override
+ public void dragExit(DropTargetEvent dte) {
+ dragExitCalled = true;
+ }
+
+ @Override
+ public void dragOver(DropTargetDragEvent dtde) {
+ Panel newDropTarget = new Panel();
+ newDropTarget.setDropTarget(new DropTarget());
+ newDropTarget.setBackground(Color.red);
+ newDropTarget.setBounds(0, 0, FRAME_SIZE, FRAME_SIZE);
+ dragSource.add(newDropTarget);
+ }
+ });
+ dragSource.setDropTarget(dt);
+ f.add(dragSource);
+
+ f.setVisible(true);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ try {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ initAndShowUI();
+ }
+ });
+
+ Robot r = new Robot();
+ Util.waitForIdle(r);
+ Util.drag(r,
+ new Point(FRAME_LOCATION + FRAME_SIZE / 3, FRAME_LOCATION + FRAME_SIZE / 3),
+ new Point(FRAME_LOCATION + FRAME_SIZE / 3 * 2, FRAME_LOCATION + FRAME_SIZE / 3 * 2),
+ InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(r);
+
+ if (!dragExitCalled) {
+ throw new RuntimeException("Failed. Drag exit was not called" );
+ }
+ } finally {
+ if (f != null) {
+ f.dispose();
+ }
+ }
+ }
+
+ private static class DraggablePanel extends Panel implements DragGestureListener {
+
+ public DraggablePanel() {
+ (new DragSource()).createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, this);
+ }
+
+ @Override
+ public void dragGestureRecognized(DragGestureEvent dge) {
+ dge.startDrag(Cursor.getDefaultCursor(), new StringSelection("test"));
+ }
+ }
+}