--- old/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java 2015-08-10 14:59:05.000000000 +0300 +++ new/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java 2015-08-10 14:59:05.000000000 +0300 @@ -746,7 +746,7 @@ */ @Override public void notifyMouseEvent(int id, long when, int button, - int x, int y, int screenX, int screenY, + int x, int y, int absX, int absY, int modifiers, int clickCount, boolean popupTrigger, byte[] bdata) { @@ -763,7 +763,7 @@ this); Component target = lastMouseEventPeer.getTarget(); postMouseExitedEvent(target, when, modifiers, lp, - screenX, screenY, clickCount, popupTrigger, button); + absX, absY, clickCount, popupTrigger, button); } // Sometimes we may get MOUSE_EXITED after lastCommonMouseEventPeer is switched @@ -781,7 +781,7 @@ Point lp = targetPeer.windowToLocal(x, y, this); Component target = targetPeer.getTarget(); postMouseEnteredEvent(target, when, modifiers, lp, - screenX, screenY, clickCount, popupTrigger, button); + absX, absY, clickCount, popupTrigger, button); } lastCommonMouseEventPeer = targetPeer; lastMouseEventPeer = targetPeer; @@ -798,12 +798,12 @@ // implemented in CPlatformEmbeddedFrame class if (topmostWindowPeer == this || topmostWindowPeer == null) { generateMouseEnterExitEventsForComponents(when, button, x, y, - screenX, screenY, modifiers, clickCount, popupTrigger, + absX, absY, modifiers, clickCount, popupTrigger, targetPeer); } else { LWComponentPeer topmostTargetPeer = topmostWindowPeer.findPeerAt(r.x + x, r.y + y); topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y, - screenX, screenY, modifiers, clickCount, popupTrigger, + absX, absY, modifiers, clickCount, popupTrigger, topmostTargetPeer); } @@ -874,7 +874,7 @@ if (targetPeer.isEnabled()) { MouseEvent event = new MouseEvent(targetPeer.getTarget(), id, when, modifiers, lp.x, lp.y, - screenX, screenY, clickCount, + absX, absY, clickCount, popupTrigger, button); postEvent(event); } @@ -885,7 +885,7 @@ postEvent(new MouseEvent(targetPeer.getTarget(), MouseEvent.MOUSE_CLICKED, when, modifiers, - lp.x, lp.y, screenX, screenY, + lp.x, lp.y, absX, absY, clickCount, popupTrigger, button)); } mouseClickButtons &= ~eventButtonMask; @@ -948,10 +948,10 @@ } @Override - public void notifyMouseWheelEvent(long when, int x, int y, int modifiers, - int scrollType, int scrollAmount, - int wheelRotation, double preciseWheelRotation, - byte[] bdata) + public void notifyMouseWheelEvent(long when, int x, int y, int absX, + int absY, int modifiers, int scrollType, + int scrollAmount, int wheelRotation, + double preciseWheelRotation, byte[] bdata) { // TODO: could we just use the last mouse event target here? Rectangle r = getBounds(); @@ -963,12 +963,11 @@ Point lp = targetPeer.windowToLocal(x, y, this); // TODO: fill "bdata" member of AWTEvent - // TODO: screenX/screenY postEvent(new MouseWheelEvent(targetPeer.getTarget(), MouseEvent.MOUSE_WHEEL, when, modifiers, lp.x, lp.y, - 0, 0, /* screenX, Y */ + absX, absY, /* absX, absY */ 0 /* clickCount */, false /* popupTrigger */, scrollType, scrollAmount, wheelRotation, preciseWheelRotation)); --- old/src/java.desktop/macosx/classes/sun/lwawt/PlatformEventNotifier.java 2015-08-10 14:59:05.000000000 +0300 +++ new/src/java.desktop/macosx/classes/sun/lwawt/PlatformEventNotifier.java 2015-08-10 14:59:05.000000000 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -49,14 +49,14 @@ * point of the client area is (insets.top, insets.left). */ void notifyMouseEvent(int id, long when, int button, - int x, int y, int screenX, int screenY, + int x, int y, int absX, int absY, int modifiers, int clickCount, boolean popupTrigger, byte[] bdata); - void notifyMouseWheelEvent(long when, int x, int y, int modifiers, - int scrollType, int scrollAmount, - int wheelRotation, double preciseWheelRotation, - byte[] bdata); + void notifyMouseWheelEvent(long when, int x, int y, final int absX, + final int absY, int modifiers, int scrollType, + int scrollAmount, int wheelRotation, + double preciseWheelRotation, byte[] bdata); /* * Called by the delegate when a key is pressed. */ --- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java 2015-08-10 14:59:06.000000000 +0300 +++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java 2015-08-10 14:59:06.000000000 +0300 @@ -75,8 +75,8 @@ int x = (int)pluginX; int y = (int)pluginY; Point locationOnScreen = getLocationOnScreen(); - int screenX = locationOnScreen.x + x; - int screenY = locationOnScreen.y + y; + int absX = locationOnScreen.x + x; + int absY = locationOnScreen.y + y; if (eventType == CocoaConstants.NPCocoaEventMouseEntered) { CCursorManager.nativeSetAllowsCursorSetInBackground(true); @@ -85,15 +85,19 @@ } responder.handleMouseEvent(eventType, modifierFlags, buttonNumber, - clickCount, x, y, screenX, screenY); + clickCount, x, y, absX, absY); } public void handleScrollEvent(double pluginX, double pluginY, int modifierFlags, double deltaX, double deltaY, double deltaZ) { int x = (int)pluginX; int y = (int)pluginY; + Point locationOnScreen = getLocationOnScreen(); + int absX = locationOnScreen.x + x; + int absY = locationOnScreen.y + y; - responder.handleScrollEvent(x, y, modifierFlags, deltaX, deltaY); + responder.handleScrollEvent(x, y, absX, absY, modifierFlags, deltaX, + deltaY); } public void handleKeyEvent(int eventType, int modifierFlags, String characters, --- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java 2015-08-10 14:59:06.000000000 +0300 +++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java 2015-08-10 14:59:06.000000000 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -54,8 +54,7 @@ * Handles mouse events. */ void handleMouseEvent(int eventType, int modifierFlags, int buttonNumber, - int clickCount, int x, int y, int absoluteX, - int absoluteY) { + int clickCount, int x, int y, int absX, int absY) { final SunToolkit tk = (SunToolkit)Toolkit.getDefaultToolkit(); if ((buttonNumber > 2 && !tk.areExtraMouseButtonsEnabled()) || buttonNumber > tk.getNumberOfButtons() - 1) { @@ -81,14 +80,15 @@ boolean jpopupTrigger = NSEvent.isPopupTrigger(jmodifiers); eventNotifier.notifyMouseEvent(jeventType, System.currentTimeMillis(), jbuttonNumber, - x, y, absoluteX, absoluteY, jmodifiers, jclickCount, + x, y, absX, absY, jmodifiers, jclickCount, jpopupTrigger, null); } /** * Handles scroll events. */ - void handleScrollEvent(final int x, final int y, final int modifierFlags, + void handleScrollEvent(final int x, final int y, final int absX, + final int absY, final int modifierFlags, final double deltaX, final double deltaY) { final int buttonNumber = CocoaConstants.kCGMouseButtonCenter; int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber, @@ -97,18 +97,19 @@ // Vertical scroll. if (!isShift && deltaY != 0.0) { - dispatchScrollEvent(x, y, jmodifiers, deltaY); + dispatchScrollEvent(x, y, absX, absY, jmodifiers, deltaY); } // Horizontal scroll or shirt+vertical scroll. final double delta = isShift && deltaY != 0.0 ? deltaY : deltaX; if (delta != 0.0) { jmodifiers |= InputEvent.SHIFT_DOWN_MASK; - dispatchScrollEvent(x, y, jmodifiers, delta); + dispatchScrollEvent(x, y, absX, absY, jmodifiers, delta); } } - private void dispatchScrollEvent(final int x, final int y, - final int modifiers, final double delta) { + private void dispatchScrollEvent(final int x, final int y, final int absX, + final int absY, final int modifiers, + final double delta) { final long when = System.currentTimeMillis(); final int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL; final int scrollAmount = 1; @@ -118,8 +119,9 @@ wheelRotation = signum; } // invert the wheelRotation for the peer - eventNotifier.notifyMouseWheelEvent(when, x, y, modifiers, scrollType, - scrollAmount, -wheelRotation, -delta, null); + eventNotifier.notifyMouseWheelEvent(when, x, y, absX, absY, modifiers, + scrollType, scrollAmount, + -wheelRotation, -delta, null); } /** --- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java 2015-08-10 14:59:07.000000000 +0300 +++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java 2015-08-10 14:59:07.000000000 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -186,16 +186,19 @@ } - private void deliverMouseEvent(NSEvent event) { + private void deliverMouseEvent(final NSEvent event) { int x = event.getX(); int y = getBounds().height - event.getY(); + int absX = event.getAbsX(); + int absY = event.getAbsY(); if (event.getType() == CocoaConstants.NSScrollWheel) { - responder.handleScrollEvent(x, y, event.getModifierFlags(), + responder.handleScrollEvent(x, y, absX, absY, event.getModifierFlags(), event.getScrollDeltaX(), event.getScrollDeltaY()); } else { responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(), - event.getClickCount(), x, y, event.getAbsX(), event.getAbsY()); + event.getClickCount(), x, y, + absX, absY); } } --- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java 2015-08-10 14:59:08.000000000 +0300 +++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java 2015-08-10 14:59:07.000000000 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -173,7 +173,7 @@ @Override public void notifyMouseEvent(int id, long when, int button, int x, int y, - int screenX, int screenY, int modifiers, + int absX, int absY, int modifiers, int clickCount, boolean popupTrigger, byte[] bdata) { LWWindowPeer peer = ownerPeer.get(); @@ -239,9 +239,10 @@ } @Override - public void notifyMouseWheelEvent(long when, int x, int y, int modifiers, - int scrollType, int scrollAmount, - int wheelRotation, double preciseWheelRotation, + public void notifyMouseWheelEvent(long when, int x, int y, int absX, + int absY, int modifiers, int scrollType, + int scrollAmount, int wheelRotation, + double preciseWheelRotation, byte[] bdata) { } --- old/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp 2015-08-10 14:59:08.000000000 +0300 +++ new/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp 2015-08-10 14:59:08.000000000 +0300 @@ -4954,6 +4954,10 @@ return; } jobject target = GetTarget(env); + DWORD curMousePos = ::GetMessagePos(); + int xAbs = GET_X_LPARAM(curMousePos); + int yAbs = GET_Y_LPARAM(curMousePos); + DTRACE_PRINTLN("creating MWE in JNI"); jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls, @@ -4961,7 +4965,7 @@ target, id, when, modifiers, x+insets.left, y+insets.top, - 0, 0, + xAbs, yAbs, clickCount, popupTrigger, scrollType, scrollAmount, roundedWheelRotation, preciseWheelRotation); --- /dev/null 2015-08-10 14:59:09.000000000 +0300 +++ new/test/java/awt/Mouse/MouseWheelAbsXY/MouseWheelAbsXY.java 2015-08-10 14:59:09.000000000 +0300 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.awt.AWTException; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Robot; +import java.awt.Window; +import java.awt.event.InputEvent; + +import static java.awt.GraphicsEnvironment.*; + +/** + * @test + * @bug 6778087 + */ +public final class MouseWheelAbsXY { + + private static boolean done; + private static int wheelX; + private static int wheelY; + private static int mouseX; + private static int mouseY; + + public static void main(final String[] args) throws AWTException { + GraphicsEnvironment ge = getLocalGraphicsEnvironment(); + GraphicsDevice[] sds = ge.getScreenDevices(); + for (GraphicsDevice gd : sds) { + test(gd.getDefaultConfiguration()); + } + } + + private static void test(GraphicsConfiguration gc) throws AWTException { + final Window frame = new Frame(gc); + try { + frame.addMouseWheelListener(e -> { + wheelX = e.getXOnScreen(); + wheelY = e.getYOnScreen(); + done = true; + }); + frame.setSize(300, 300); + frame.setVisible(true); + + final Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.setAutoWaitForIdle(true); + mouseX = frame.getX() + frame.getWidth() / 2; + mouseY = frame.getY() + frame.getHeight() / 2; + + robot.mouseMove(mouseX, mouseY); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseWheel(10); + + validate(); + } finally { + frame.dispose(); + } + } + + private static void validate() { + if (!done || wheelX != mouseX || wheelY != mouseY) { + System.err.println("Expected X: " + mouseX); + System.err.println("Expected Y: " + mouseY); + System.err.println("Actual X: " + wheelX); + System.err.println("Actual Y: " + wheelY); + throw new RuntimeException("Test failed"); + } + } +}