changeset 10024:75f70aa755e1

8161282: FXCanvas does not forward horizontal mouse scroll events to the embedded scene Reviewed-by: azvegint, kcr Contributed-by: alexander@nyssen.org
author azvegint
date Wed, 07 Sep 2016 14:15:39 +0300
parents 519565d94187
children f8f085f758b8
files modules/javafx.graphics/src/main/java/com/sun/javafx/embed/AbstractEvents.java modules/javafx.graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java modules/javafx.swing/src/main/java/javafx/embed/swing/SwingEvents.java modules/javafx.swt/src/main/java/javafx/embed/swt/FXCanvas.java modules/javafx.swt/src/main/java/javafx/embed/swt/SWTEvents.java tests/manual/swt/FXCanvasMouseWheelEventsTest.java
diffstat 8 files changed, 187 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/AbstractEvents.java	Tue Sep 06 15:08:30 2016 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/AbstractEvents.java	Wed Sep 07 14:15:39 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, 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
@@ -48,7 +48,8 @@
     public final static int MOUSEEVENT_EXITED = 4;
     public final static int MOUSEEVENT_MOVED = 5;
     public final static int MOUSEEVENT_DRAGGED = 6;
-    public final static int MOUSEEVENT_WHEEL = 7;
+    public final static int MOUSEEVENT_VERTICAL_WHEEL = 7;
+    public final static int MOUSEEVENT_HORIZONTAL_WHEEL = 8;
 
     public final static int MOUSEEVENT_NONE_BUTTON = 0;
     public final static int MOUSEEVENT_PRIMARY_BUTTON = 1;
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java	Tue Sep 06 15:08:30 2016 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java	Wed Sep 07 14:15:39 2016 +0300
@@ -71,7 +71,14 @@
                            boolean primaryBtnDown, boolean middleBtnDown, boolean secondaryBtnDown,
                            int x, int y, int xAbs, int yAbs,
                            boolean shift, boolean ctrl, boolean alt, boolean meta,
-                           int wheelRotation, boolean popupTrigger);
+                           boolean popupTrigger);
+    /*
+     * A notification about mouse wheel scroll events received by the host container;
+     */
+    public void scrollEvent(int type, double scrollX, double scrollY,
+                            double x, double y, double screenX, double screenY,
+                            boolean shift, boolean ctrl,
+                            boolean alt, boolean meta);
     /*
      * A notification about key event received by host container.
      */
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java	Tue Sep 06 15:08:30 2016 -0700
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java	Wed Sep 07 14:15:39 2016 +0300
@@ -273,7 +273,7 @@
                            final boolean primaryBtnDown, final boolean middleBtnDown, final boolean secondaryBtnDown,
                            final int x, final int y, final int xAbs, final int yAbs,
                            final boolean shift, final boolean ctrl, final boolean alt, final boolean meta,
-                           final int wheelRotation, final boolean popupTrigger)
+                           final boolean popupTrigger)
     {
         Platform.runLater(() -> {
             AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
@@ -282,24 +282,38 @@
                 }
                 // Click events are generated in Scene, so we don't expect them here
                 assert type != AbstractEvents.MOUSEEVENT_CLICKED;
-                if (type == AbstractEvents.MOUSEEVENT_WHEEL) {
-                    sceneListener.scrollEvent(ScrollEvent.SCROLL, 0, -wheelRotation, 0, 0, 40.0, 40.0,
-                            0, 0, 0, 0, 0,
-                            x, y, xAbs, yAbs, shift, ctrl, alt, meta, false, false);
-                } else {
-                    EventType<MouseEvent> eventType = AbstractEvents.mouseIDToFXEventID(type);
-                    sceneListener.mouseEvent(eventType, x, y, xAbs, yAbs,
+                EventType<MouseEvent> eventType = AbstractEvents.mouseIDToFXEventID(type);
+                sceneListener.mouseEvent(eventType, x, y, xAbs, yAbs,
                             AbstractEvents.mouseButtonToFXMouseButton(button),
                             popupTrigger, false, // do we know if it's synthesized? RT-20142
                             shift, ctrl, alt, meta,
                             primaryBtnDown, middleBtnDown, secondaryBtnDown);
-                }
                 return null;
             }, getAccessControlContext());
         });
     }
 
     @Override
+    public void scrollEvent(final int type, final double scrollX, final double scrollY,
+                            final double x, final double y,
+                            final double xAbs, final double yAbs,
+                            final boolean shift, final boolean ctrl, final boolean alt, final boolean meta) {
+        {
+            Platform.runLater(() -> {
+                AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                    if (sceneListener == null) {
+                        return null;
+                    }
+                    sceneListener.scrollEvent(ScrollEvent.SCROLL, scrollX, scrollY, 0, 0, 40.0, 40.0,
+                            0, 0, 0, 0, 0,
+                            x, y, xAbs, yAbs, shift, ctrl, alt, meta, false, false);
+                    return null;
+                }, getAccessControlContext());
+            });
+        }
+    }
+
+    @Override
     public void inputMethodEvent(final EventType<InputMethodEvent> type,
                                  final ObservableList<InputMethodTextRun> composed, final String committed,
                                  final int caretPosition) {
--- a/modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java	Tue Sep 06 15:08:30 2016 -0700
+++ b/modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java	Wed Sep 07 14:15:39 2016 +0300
@@ -369,16 +369,27 @@
         if (e.getID() == MouseEvent.MOUSE_PRESSED || e.getID() == MouseEvent.MOUSE_RELEASED) {
             popupTrigger = e.isPopupTrigger();
         }
-        scenePeer.mouseEvent(
-                SwingEvents.mouseIDToEmbedMouseType(e.getID()),
-                SwingEvents.mouseButtonToEmbedMouseButton(e.getButton(), extModifiers),
-                primaryBtnDown, middleBtnDown, secondaryBtnDown,
-                e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(),
-                (extModifiers & MouseEvent.SHIFT_DOWN_MASK) != 0,
-                (extModifiers & MouseEvent.CTRL_DOWN_MASK) != 0,
-                (extModifiers & MouseEvent.ALT_DOWN_MASK) != 0,
-                (extModifiers & MouseEvent.META_DOWN_MASK) != 0,
-                SwingEvents.getWheelRotation(e), popupTrigger);
+
+        if(e.getID() == MouseEvent.MOUSE_WHEEL) {
+            scenePeer.scrollEvent(AbstractEvents.MOUSEEVENT_VERTICAL_WHEEL,
+                    0, -SwingEvents.getWheelRotation(e),
+                    e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(),
+                    (extModifiers & MouseEvent.SHIFT_DOWN_MASK) != 0,
+                    (extModifiers & MouseEvent.CTRL_DOWN_MASK) != 0,
+                    (extModifiers & MouseEvent.ALT_DOWN_MASK) != 0,
+                    (extModifiers & MouseEvent.META_DOWN_MASK) != 0);
+        } else {
+            scenePeer.mouseEvent(
+                    SwingEvents.mouseIDToEmbedMouseType(e.getID()),
+                    SwingEvents.mouseButtonToEmbedMouseButton(e.getButton(), extModifiers),
+                    primaryBtnDown, middleBtnDown, secondaryBtnDown,
+                    e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(),
+                    (extModifiers & MouseEvent.SHIFT_DOWN_MASK) != 0,
+                    (extModifiers & MouseEvent.CTRL_DOWN_MASK) != 0,
+                    (extModifiers & MouseEvent.ALT_DOWN_MASK) != 0,
+                    (extModifiers & MouseEvent.META_DOWN_MASK) != 0,
+                    popupTrigger);
+        }
         if (e.isPopupTrigger()) {
             scenePeer.menuEvent(e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), false);
         }
--- a/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingEvents.java	Tue Sep 06 15:08:30 2016 -0700
+++ b/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingEvents.java	Wed Sep 07 14:15:39 2016 +0300
@@ -56,8 +56,6 @@
                 return AbstractEvents.MOUSEEVENT_ENTERED;
             case MouseEvent.MOUSE_EXITED:
                 return AbstractEvents.MOUSEEVENT_EXITED;
-            case MouseWheelEvent.MOUSE_WHEEL:
-                return AbstractEvents.MOUSEEVENT_WHEEL;
         }
         return 0;
     }
--- a/modules/javafx.swt/src/main/java/javafx/embed/swt/FXCanvas.java	Tue Sep 06 15:08:30 2016 -0700
+++ b/modules/javafx.swt/src/main/java/javafx/embed/swt/FXCanvas.java	Wed Sep 07 14:15:39 2016 +0300
@@ -94,6 +94,7 @@
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Shell;
 
@@ -463,8 +464,11 @@
             }
         });
 
-        addMouseWheelListener(me -> {
-            FXCanvas.this.sendMouseEventToFX(me, AbstractEvents.MOUSEEVENT_WHEEL);
+        addListener(SWT.MouseVerticalWheel, e -> {
+            FXCanvas.this.sendScrollEventToFX(e, AbstractEvents.MOUSEEVENT_VERTICAL_WHEEL);
+        });
+        addListener(SWT.MouseHorizontalWheel, e -> {
+            FXCanvas.this.sendScrollEventToFX(e, AbstractEvents.MOUSEEVENT_HORIZONTAL_WHEEL);
         });
 
         addMouseTrackListener(new MouseTrackListener() {
@@ -673,10 +677,25 @@
                 me.x, me.y,
                 los.x, los.y,
                 shift, control, alt, meta,
-                SWTEvents.getWheelRotation(me, embedMouseType),
                 false);  // RT-32990: popup trigger not implemented
     }
 
+    private void sendScrollEventToFX(Event event, int type){
+        if (scenePeer == null) {
+            return;
+        }
+        Point los = toDisplay(event.x, event.y);
+        scenePeer.scrollEvent(type,
+                (type == AbstractEvents.MOUSEEVENT_HORIZONTAL_WHEEL) ? -SWTEvents.getWheelRotation(event) : 0,
+                (type == AbstractEvents.MOUSEEVENT_VERTICAL_WHEEL) ? -SWTEvents.getWheelRotation(event) : 0,
+                event.x, event.y,
+                los.x, los.y,
+                (event.stateMask & SWT.SHIFT) != 0,
+                (event.stateMask & SWT.CONTROL) != 0,
+                (event.stateMask & SWT.ALT) != 0,
+                (event.stateMask & SWT.COMMAND) != 0);
+    }
+
     private void sendKeyEventToFX(final KeyEvent e, int type) {
         if (scenePeer == null /*|| !isFxEnabled()*/) {
             return;
--- a/modules/javafx.swt/src/main/java/javafx/embed/swt/SWTEvents.java	Tue Sep 06 15:08:30 2016 -0700
+++ b/modules/javafx.swt/src/main/java/javafx/embed/swt/SWTEvents.java	Wed Sep 07 14:15:39 2016 +0300
@@ -32,6 +32,8 @@
 
 //import com.sun.glass.events.KeyEvent;
 import com.sun.javafx.embed.AbstractEvents;
+import org.eclipse.swt.widgets.Event;
+
 import java.lang.reflect.InvocationTargetException;
 
 /**
@@ -58,8 +60,6 @@
                 return AbstractEvents.MOUSEEVENT_ENTERED;
             case MouseEvent.MOUSE_EXITED:
                 return AbstractEvents.MOUSEEVENT_EXITED;
-            case MouseWheelEvent.MOUSE_WHEEL:
-                return AbstractEvents.MOUSEEVENT_WHEEL;
         }
         return 0;
     }
@@ -73,33 +73,30 @@
         return AbstractEvents.MOUSEEVENT_NONE_BUTTON;
     }
 
-    static int getWheelRotation(MouseEvent e, int embedMouseType) {
+    static int getWheelRotation(Event e) {
         int divisor = 1;
-        if (embedMouseType == AbstractEvents.MOUSEEVENT_WHEEL) {
-            if ("win32".equals(SWT.getPlatform())) {
-                int [] linesToScroll = new int [1];
-                //OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, linesToScroll, 0);
-                try {
-                    Class clazz = Class.forName("org.eclipse.swt.internal.win32.OS");
-                    Method method = clazz.getDeclaredMethod("SystemParametersInfo", new Class []{int.class, int.class, int [].class, int.class});
-                    method.invoke(clazz, 104 /*SPI_GETWHEELSCROLLLINES*/, 0, linesToScroll, 0);
-                } catch (IllegalAccessException iae) {
-                } catch (InvocationTargetException ite) {
-                } catch (NoSuchMethodException nme) {
-                } catch (ClassNotFoundException cfe) {
-                    //Fail silently
-                }
-                if (linesToScroll [0] != -1 /*OS.WHEEL_PAGESCROLL*/) {
-                    divisor = linesToScroll [0];
-                }
-            } else {
-                if ("gtk".equals(SWT.getPlatform())) {
-                    divisor = 3;
-                }
+        if ("win32".equals(SWT.getPlatform())) {
+            int [] linesToScroll = new int [1];
+            //OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, linesToScroll, 0);
+            try {
+                Class clazz = Class.forName("org.eclipse.swt.internal.win32.OS");
+                Method method = clazz.getDeclaredMethod("SystemParametersInfo", new Class []{int.class, int.class, int [].class, int.class});
+                method.invoke(clazz, 104 /*SPI_GETWHEELSCROLLLINES*/, 0, linesToScroll, 0);
+            } catch (IllegalAccessException iae) {
+            } catch (InvocationTargetException ite) {
+            } catch (NoSuchMethodException nme) {
+            } catch (ClassNotFoundException cfe) {
+                //Fail silently
             }
-            return -e.count / Math.max(1, divisor);
+            if (linesToScroll [0] != -1 /*OS.WHEEL_PAGESCROLL*/) {
+                divisor = linesToScroll [0];
+            }
+        } else {
+            if ("gtk".equals(SWT.getPlatform())) {
+                divisor = 3;
+            }
         }
-        return 0;
+        return -e.count / Math.max(1, divisor);
     }
 
     static int keyIDToEmbedKeyType(int id) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/manual/swt/FXCanvasMouseWheelEventsTest.java	Wed Sep 07 14:15:39 2016 +0300
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 javafx.embed.swt.FXCanvas;
+import javafx.scene.Group;
+import javafx.scene.Scene;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.VBox;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class FXCanvasMouseWheelEventsTest {
+
+    static final String instructions =
+            "This tests that SWT mouse wheel events are properly transferred to SWT. " +
+                    "It passes if both, vertical and horizontal mouse wheel events are both recognized properly.";
+
+    private static TextArea createInfo(String msg) {
+        TextArea t = new TextArea(msg);
+        t.setWrapText(true);
+        t.setEditable(false);
+        t.setMaxWidth(400);
+        t.setMaxHeight(100);
+        return t;
+    }
+
+    public static void main(String[] args) {
+        final Display display = new Display();
+        final Shell shell = new Shell(display);
+        shell.setText("FXCanvasMouseWheelEventsTest");
+        shell.setSize(400, 200);
+        shell.setLayout(new FillLayout());
+        final FXCanvas canvas = new FXCanvas(shell, SWT.NONE);
+        shell.open();
+
+        // create and hook scene
+        Group root = new Group();
+
+        TextArea info = createInfo(instructions);
+        Label output = new Label("No events yet...");
+
+        VBox vbox = new VBox();
+        vbox.getChildren().addAll(info, output);
+        root.getChildren().add(vbox);
+
+        final Scene scene = new Scene(root, 200, 200);
+
+        final int[] eventCount = {0};
+        root.setOnScroll(scrollEvent -> {
+            output.setText("Scroll event #" + eventCount[0]++ + ": deltaX: " + scrollEvent.getDeltaX() + ", deltaY: " + scrollEvent.getDeltaY());
+        });
+        canvas.setScene(scene);
+
+        while (!shell.isDisposed()) {
+            // run SWT event loop
+            if (!display.readAndDispatch()) {
+                display.sleep();
+            }
+        }
+        display.dispose();
+    }
+}