From a69cdcd35ad1655d620b4b27ac365668e3bf2199 Mon Sep 17 00:00:00 2001 From: serb Date: Sun, 26 Apr 2020 19:36:04 -0700 Subject: [PATCH] 8238575: DragSourceEvent.getLocation() returns wrong value on HiDPI screens (Windows) Reviewed-by: prr --- .../native/libawt/windows/awt_DnDDS.cpp | 55 +++++++++------ .../windows/native/libawt/windows/awt_DnDDS.h | 18 ++--- .../native/libawt/windows/awt_DnDDT.cpp | 2 +- .../dnd/Button2DragTest/Button2DragTest.java | 70 +++++++++++++------ test/jdk/sun/awt/dnd/8024061/bug8024061.java | 32 +++++---- 5 files changed, 112 insertions(+), 65 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp index 4432634e97..2c2d9dca7c 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, 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 @@ -282,7 +282,7 @@ void AwtDragSource::_DoDragDrop(void* param) { call_dSCddfinished(env, peer, res == DRAGDROP_S_DROP && effects != DROPEFFECT_NONE, convertDROPEFFECTToActions(effects), - dragSource->m_dragPoint.x, dragSource->m_dragPoint.y); + dragSource->m_dragPoint); env->DeleteLocalRef(peer); @@ -645,8 +645,7 @@ HRESULT __stdcall AwtDragSource::QueryContinueDrag(BOOL fEscapeKeyPressed, DWOR if ( (dragPoint.x != m_dragPoint.x || dragPoint.y != m_dragPoint.y) && m_lastmods == modifiers) {//cannot move before cursor change - call_dSCmouseMoved(env, m_peer, - m_actions, modifiers, dragPoint.x, dragPoint.y); + call_dSCmouseMoved(env, m_peer, m_actions, modifiers, dragPoint); JNU_CHECK_EXCEPTION_RETURN(env, E_UNEXPECTED); m_dragPoint = dragPoint; } @@ -658,8 +657,7 @@ HRESULT __stdcall AwtDragSource::QueryContinueDrag(BOOL fEscapeKeyPressed, DWOR } else if ((modifiers & JAVA_BUTTON_MASK) != (m_initmods & JAVA_BUTTON_MASK)) { return DRAGDROP_S_CANCEL; } else if (m_lastmods != modifiers) { - call_dSCchanged(env, m_peer, - m_actions, modifiers, dragPoint.x, dragPoint.y); + call_dSCchanged(env, m_peer, m_actions, modifiers, dragPoint); m_bRestoreNodropCustomCursor = TRUE; } @@ -722,13 +720,13 @@ HRESULT __stdcall AwtDragSource::GiveFeedback(DWORD dwEffect) { if (invalid) { // Don't call dragExit if dragEnter and dragOver haven't been called. if (!m_enterpending) { - call_dSCexit(env, m_peer, curs.x, curs.y); + call_dSCexit(env, m_peer, curs); } m_droptarget = (HWND)NULL; m_enterpending = TRUE; } else if (m_droptarget != NULL) { (*(m_enterpending ? call_dSCenter : call_dSCmotion)) - (env, m_peer, m_actions, modifiers, curs.x, curs.y); + (env, m_peer, m_actions, modifiers, curs); m_enterpending = FALSE; } @@ -1172,14 +1170,26 @@ HRESULT __stdcall AwtDragSource::GetProcessId(FORMATETC __RPC_FAR *pFormatEtc, S return S_OK; } +static void ScaleDown(POINT &pt) { + HMONITOR monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); + int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice *device = devices->GetDevice(screen); + if (device) { + pt.x = device->ScaleDownX(pt.x); + pt.y = device->ScaleDownY(pt.y); + } +} + DECLARE_JAVA_CLASS(dSCClazz, "sun/awt/windows/WDragSourceContextPeer") void AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, - jint modifiers, jint x, jint y) { + jint modifiers, POINT pt) { + ScaleDown(pt); DECLARE_VOID_JAVA_METHOD(dSCenter, dSCClazz, "dragEnter", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); - env->CallVoidMethod(self, dSCenter, targetActions, modifiers, x, y); + env->CallVoidMethod(self, dSCenter, targetActions, modifiers, pt.x, pt.y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); @@ -1188,10 +1198,11 @@ AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, void AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, - jint modifiers, jint x, jint y) { + jint modifiers, POINT pt) { + ScaleDown(pt); DECLARE_VOID_JAVA_METHOD(dSCmotion, dSCClazz, "dragMotion", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); - env->CallVoidMethod(self, dSCmotion, targetActions, modifiers, x, y); + env->CallVoidMethod(self, dSCmotion, targetActions, modifiers, pt.x, pt.y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); @@ -1200,11 +1211,12 @@ AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, void AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, - jint modifiers, jint x, jint y) { + jint modifiers, POINT pt) { + ScaleDown(pt); DECLARE_VOID_JAVA_METHOD(dSCchanged, dSCClazz, "operationChanged", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); - env->CallVoidMethod(self, dSCchanged, targetActions, modifiers, x, y); + env->CallVoidMethod(self, dSCchanged, targetActions, modifiers, pt.x, pt.y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); @@ -1212,10 +1224,11 @@ AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, } void -AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, jint x, jint y) { +AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, POINT pt) { + ScaleDown(pt); DECLARE_VOID_JAVA_METHOD(dSCexit, dSCClazz, "dragExit", "(II)V"); DASSERT(!JNU_IsNull(env, self)); - env->CallVoidMethod(self, dSCexit, x, y); + env->CallVoidMethod(self, dSCexit, pt.x, pt.y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); @@ -1224,10 +1237,11 @@ AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, jint x, jint y) { void AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, - jint operations, jint x, jint y) { + jint operations, POINT pt) { + ScaleDown(pt); DECLARE_VOID_JAVA_METHOD(dSCddfinished, dSCClazz, "dragDropFinished", "(ZIII)V"); DASSERT(!JNU_IsNull(env, self)); - env->CallVoidMethod(self, dSCddfinished, success, operations, x, y); + env->CallVoidMethod(self, dSCddfinished, success, operations, pt.x, pt.y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); @@ -1236,11 +1250,12 @@ AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, void AwtDragSource::call_dSCmouseMoved(JNIEnv* env, jobject self, jint targetActions, - jint modifiers, jint x, jint y) { + jint modifiers, POINT pt) { + ScaleDown(pt); DECLARE_VOID_JAVA_METHOD(dSCmouseMoved, dSCClazz, "dragMouseMoved", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); - env->CallVoidMethod(self, dSCmouseMoved, targetActions, modifiers, x, y); + env->CallVoidMethod(self, dSCmouseMoved, targetActions, modifiers, pt.x, pt.y); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.h b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.h index 0abdc2d676..1549ca6421 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, 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 @@ -127,20 +127,20 @@ class AwtDragSource : virtual public IDropSource, virtual public IDataObject { static int __cdecl _compar(const void *, const void *); static void call_dSCenter(JNIEnv* env, jobject self, jint targetActions, - jint modifiers, jint x, jint y); + jint modifiers, POINT pt); static void call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, jint modifiers, - jint x, jint y); + POINT pt); static void call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, jint modifiers, - jint x, jint y); + POINT pt); static void call_dSCmouseMoved(JNIEnv* env, jobject self, jint targetActions, jint modifiers, - jint x, jint y); - static void call_dSCexit(JNIEnv* env, jobject self, jint x, jint y); + POINT pt); + static void call_dSCexit(JNIEnv* env, jobject self, POINT pt); static void call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, jint operations, - jint x, jint y); + POINT pt); protected: class ADSIEnumFormatEtc : public virtual IEnumFORMATETC { @@ -254,8 +254,8 @@ class AwtDragSource : virtual public IDropSource, virtual public IDataObject { jobject m_transferable; jobject m_formatMap; - POINT m_dragPoint; - POINT m_dropPoint; + POINT m_dragPoint; // device space (pixels) + POINT m_dropPoint; // device space (pixels) BOOL m_fNC; BOOL m_bRestoreNodropCustomCursor;//CR 6480706 - MS Bug on hold diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp index 908b459111..343ff8cdd4 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDT.cpp @@ -127,7 +127,7 @@ ULONG __stdcall AwtDropTarget::Release() { return (ULONG)refs; } -void ScaleDown(POINT &cp, HWND m_window) { +static void ScaleDown(POINT &cp, HWND m_window) { int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(m_window); Devices::InstanceAccess devices; AwtWin32GraphicsDevice* device = devices->GetDevice(screen); diff --git a/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java b/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java index df5041d381..9400f854da 100644 --- a/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java +++ b/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, 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 @@ -21,7 +21,11 @@ * questions. */ +import java.awt.Color; import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Robot; import java.awt.datatransfer.StringSelection; @@ -29,8 +33,9 @@ import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; -import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetAdapter; @@ -42,7 +47,7 @@ import test.java.awt.regtesthelpers.Util; /** * @test * @key headful - * @bug 4955110 + * @bug 4955110 8238575 * @summary tests that DragSourceDragEvent.getDropAction() accords to its new * spec (does not depend on the user drop action) * @library ../../regtesthelpers @@ -53,26 +58,56 @@ import test.java.awt.regtesthelpers.Util; public final class Button2DragTest { private volatile boolean dropSuccess; + private volatile boolean locationValid = true; private static Frame frame; public static void main(final String[] args) { - Button2DragTest test = new Button2DragTest(); - try { - test.run(); - } finally { - if (frame != null) { + var lge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + for (GraphicsDevice device : lge.getScreenDevices()) { + Button2DragTest test = new Button2DragTest(); + frame = new Frame(device.getDefaultConfiguration()); + try { + test.run(); + } finally { frame.dispose(); } } } public void run() { - frame = new Frame(); + final DragSourceListener dragSourceListener = new DragSourceListener() { + private void checkLocation(DragSourceEvent dsde) { + if (!frame.getBounds().contains(dsde.getLocation())) { + System.err.println("Expected in" + frame.getBounds()); + System.err.println("Actual" + dsde.getLocation()); + locationValid = false; + } + } + + @Override + public void dragEnter(DragSourceDragEvent dsde) { + checkLocation(dsde); + } + + @Override + public void dragOver(DragSourceDragEvent dsde) { + checkLocation(dsde); + } - final DragSourceListener dragSourceListener = new DragSourceAdapter() { - public void dragDropEnd(DragSourceDropEvent e) { - dropSuccess = e.getDropSuccess(); + @Override + public void dropActionChanged(DragSourceDragEvent dsde) { + checkLocation(dsde); + } + + @Override + public void dragExit(DragSourceEvent dse) { + checkLocation(dse); + } + + public void dragDropEnd(DragSourceDropEvent dsde) { + checkLocation(dsde); + dropSuccess = dsde.getDropSuccess(); System.err.println("Drop was successful: " + dropSuccess); } }; @@ -93,11 +128,9 @@ public final class Button2DragTest { }; new DropTarget(frame, dropTargetListener); - //What would normally go into main() will probably go here. - //Use System.out.println for diagnostic messages that you want - //to read after the test is done. + frame.setBackground(Color.GREEN); frame.setUndecorated(true); - frame.setBounds(100, 100, 200, 200); + frame.setSize(200, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); @@ -115,11 +148,8 @@ public final class Button2DragTest { Util.waitForIdle(robot); robot.delay(500); - if (dropSuccess) { - System.err.println("test passed"); - } else { + if (!dropSuccess || !locationValid) { throw new RuntimeException("test failed: drop was not successful"); } } - } diff --git a/test/jdk/sun/awt/dnd/8024061/bug8024061.java b/test/jdk/sun/awt/dnd/8024061/bug8024061.java index 0a9528acaf..3cd5f6e1ff 100644 --- a/test/jdk/sun/awt/dnd/8024061/bug8024061.java +++ b/test/jdk/sun/awt/dnd/8024061/bug8024061.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, 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 @@ -27,11 +27,17 @@ * @bug 8024061 * @summary Checks that no exception is thrown if dragGestureRecognized * takes a while to complete. - * @library ../../../../lib/testlibrary - * @build jdk.testlibrary.OSInfo - * @run main bug8024061 */ -import java.awt.*; + +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.Robot; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; @@ -55,8 +61,10 @@ import java.lang.reflect.InvocationTargetException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import javax.swing.*; -import jdk.testlibrary.OSInfo; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; /** @@ -108,19 +116,13 @@ public class bug8024061 { frame.pack(); + frame.setLocationRelativeTo(null); DropObject drop = new DropObject(); drop.place(panel1, new Point(10, 10)); frame.setVisible(true); } public static void main(String[] args) throws AWTException, InvocationTargetException, InterruptedException { - OSInfo.OSType type = OSInfo.getOSType(); - if (type != OSInfo.OSType.LINUX && type != OSInfo.OSType.SOLARIS) { - System.out.println("This test is for Linux and Solaris only... " + - "skipping!"); - return; - } - final bug8024061[] dnd = {null}; SwingUtilities.invokeAndWait(new Runnable() { @Override @@ -167,7 +169,7 @@ public class bug8024061 { throw new RuntimeException("Timed out waiting for dragEnter()"); } } finally { - SwingUtilities.invokeLater(frame::dispose); + SwingUtilities.invokeAndWait(frame::dispose); } } -- GitLab