Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8210895

Support mouse forward/back buttons

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • jfx12
    • javafx
    • None
    • minimal
    • Hide
      The MouseButton enumerations will have two new values, BACK and FORWARD. Since these values didn't exist before there is no risk of the new buttons doing anything unintended except for the case where a `default` switch statement clause was used in a way such that the developer assumed that the MouseButton enumeration would never get any new values and so assumed that they could handle, say, PRIMARY and SECONDARY explicitly and the OTHER/MIDDLE button as the default case.
      Show
      The MouseButton enumerations will have two new values, BACK and FORWARD. Since these values didn't exist before there is no risk of the new buttons doing anything unintended except for the case where a `default` switch statement clause was used in a way such that the developer assumed that the MouseButton enumeration would never get any new values and so assumed that they could handle, say, PRIMARY and SECONDARY explicitly and the OTHER/MIDDLE button as the default case.
    • Java API
    • JDK

      Summary

      Add support for extended mouse buttons MouseButton.BACK and MouseButton.FORWARD. This means adding support to the native windows, provided by the underlying operating system, to listen for these mouse events as well as allowing the Robot to trigger these events when the MouseButton argument to Robot#mousePress and Robot#mouseRelease is one of the new mouse buttons (BACK or FORWARD).

      Problem

      JavaFX currently supports three mouse-buttons: Left (also known as Primary), Right (also known as secondary) and Middle (also known as Other). Any MouseEvents fired in a Scene will therefore only support these three buttons. There is no way for someone using JavaFX to listen for MouseEvents that involve other buttons (namely: BACK and FORWARD). This is partly because the native windows provided by the operating system do not listen for such mouse events and also because the JavaFX API does not have a way to represent them (i.e. there are only 3 values of the MouseButton enumeration).

      Solution

      • Add MouseButton.BACK and MouseButton.FORWARD to the MouseButton enum.
      • Make the native windows supplied by the OS listen to (and propagate up to the Java API) mouse events for these extended buttons.
      • Make the native Robots (Windows, macOS, Linux, and Headless Monocle) "do the right thing" when mousePress or mouseRelease are called with either of the new buttons (MouseButton.BACK and MouseButton.FORWARD).

      Specification

      javafx.graphics/src/main/java/javafx/scene/input/MouseEvent.java:

      @@ -297,6 +297,10 @@ public MouseEvent copyFor(Object newSource, EventTarget newTarget, EventType<? e
      
           /**
            * Constructs new MouseEvent event with null source and target.
      +     *
      +     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
      +     * will return {@literal false} for this event.
      +     *
            * @param eventType The type of the event.
            * @param x The x with respect to the scene.
            * @param y The y with respect to the scene.
      
      @@ -342,8 +346,64 @@ public MouseEvent(
                       synthesized, popupTrigger, stillSincePress, pickResult);
           }
      
      +    /**
      +     * Constructs new MouseEvent event with null source and target.
      +     * @param eventType The type of the event.
      +     * @param x The x with respect to the scene.
      +     * @param y The y with respect to the scene.
      +     * @param screenX The x coordinate relative to screen.
      +     * @param screenY The y coordinate relative to screen.
      +     * @param button the mouse button used
      +     * @param clickCount number of click counts
      +     * @param shiftDown true if shift modifier was pressed.
      +     * @param controlDown true if control modifier was pressed.
      +     * @param altDown true if alt modifier was pressed.
      +     * @param metaDown true if meta modifier was pressed.
      +     * @param primaryButtonDown true if primary button was pressed.
      +     * @param middleButtonDown true if middle button was pressed.
      +     * @param secondaryButtonDown true if secondary button was pressed.
      +     * @param backButtonDown true if back button was pressed.
      +     * @param forwardButtonDown true if forward button was pressed
      +     * @param synthesized if this event was synthesized
      +     * @param popupTrigger whether this event denotes a popup trigger for current platform
      +     * @param stillSincePress see {@link #isStillSincePress() }
      +     * @param pickResult pick result. Can be null, in this case a 2D pick result
      +     *                   without any further values is constructed
      +     *                   based on the scene coordinates
      +     * @since 12
      +     */
      +    public MouseEvent(
      +            @NamedArg("eventType") EventType<? extends MouseEvent> eventType,
      +            @NamedArg("x") double x, @NamedArg("y") double y,
      +            @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
      +            @NamedArg("button") MouseButton button,
      +            @NamedArg("clickCount") int clickCount,
      +            @NamedArg("shiftDown") boolean shiftDown,
      +            @NamedArg("controlDown") boolean controlDown,
      +            @NamedArg("altDown") boolean altDown,
      +            @NamedArg("metaDown") boolean metaDown,
      +            @NamedArg("primaryButtonDown") boolean primaryButtonDown,
      +            @NamedArg("middleButtonDown") boolean middleButtonDown,
      +            @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
      +            @NamedArg("backButtonDown") boolean backButtonDown,
      +            @NamedArg("forwardButtonDown") boolean forwardButtonDown,
      +            @NamedArg("synthesized") boolean synthesized,
      +            @NamedArg("popupTrigger") boolean popupTrigger,
      +            @NamedArg("stillSincePress") boolean stillSincePress,
      +            @NamedArg("pickResult") PickResult pickResult) {
      +        this(null, null, eventType, x, y, screenX, screenY, button, clickCount,
      +                shiftDown, controlDown, altDown, metaDown,
      +                primaryButtonDown, middleButtonDown, secondaryButtonDown,
      +                backButtonDown, forwardButtonDown,
      +                synthesized, popupTrigger, stillSincePress, pickResult);
      +    }
      +
           /**
            * Constructs new MouseEvent event.
      +     *
      +     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
      +     * will return {@literal false} for this event.
      +     *
            * @param source the source of the event. Can be null.
            * @param target the target of the event. Can be null.
            * @param eventType The type of the event.
      
      /**
       * Constructs new MouseEvent event.
       * @param source the source of the event. Can be null.
       * @param target the target of the event. Can be null.
       * @param eventType The type of the event.
       * @param x The x with respect to the source. Should be in scene coordinates if source == null or source is not a Node.
       * @param y The y with respect to the source. Should be in scene coordinates if source == null or source is not a Node.
       * @param screenX The x coordinate relative to screen.
       * @param screenY The y coordinate relative to screen.
       * @param button the mouse button used
       * @param clickCount number of click counts
       * @param shiftDown true if shift modifier was pressed.
       * @param controlDown true if control modifier was pressed.
       * @param altDown true if alt modifier was pressed.
       * @param metaDown true if meta modifier was pressed.
       * @param primaryButtonDown true if primary button was pressed.
       * @param middleButtonDown true if middle button was pressed.
       * @param secondaryButtonDown true if secondary button was pressed.
       * @param backButtonDown true if the back button was pressed
       * @param forwardButtonDown true if the forward button was pressed
       * @param synthesized if this event was synthesized
       * @param popupTrigger whether this event denotes a popup trigger for current platform
       * @param stillSincePress see {@link #isStillSincePress() }
       * @param pickResult pick result. Can be null, in this case a 2D pick result
       *                   without any further values is constructed
       *                   based on the scene coordinates and target
       * @since 12
       */
      public MouseEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target,
                        @NamedArg("eventType") EventType<? extends MouseEvent> eventType,
                        @NamedArg("x") double x, @NamedArg("y") double y,
                        @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
                        @NamedArg("button") MouseButton button,
                        @NamedArg("clickCount") int clickCount,
                        @NamedArg("shiftDown") boolean shiftDown,
                        @NamedArg("controlDown") boolean controlDown,
                        @NamedArg("altDown") boolean altDown,
                        @NamedArg("metaDown") boolean metaDown,
                        @NamedArg("primaryButtonDown") boolean primaryButtonDown,
                        @NamedArg("middleButtonDown") boolean middleButtonDown,
                        @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
                        @NamedArg("backButtonDown") boolean backButtonDown,
                        @NamedArg("forwardButtonDown") boolean forwardButtonDown,
                        @NamedArg("synthesized") boolean synthesized,
                        @NamedArg("popupTrigger") boolean popupTrigger,
                        @NamedArg("stillSincePress") boolean stillSincePress,
                        @NamedArg("pickResult") PickResult pickResult) {}
      
      /**
       * Returns {@code true} if back button (button 4)
       * is currently pressed. Note that this is different from the
       * {@code getButton()} method that indicates which button press was
       * responsible for this event while this method indicates whether the
       * back button is depressed.
       *
       * @return {@code true} if back button (button 4) is currently pressed
       * @since 12
       */
      public final boolean isBackButtonDown() {}
      
      /**
       * Returns {@code true} if forward button (button 5)
       * is currently pressed. Note that this is different from the
       * {@code getButton()} method that indicates which button press was
       * responsible for this event while this method indicates whether the
       * back button is depressed.
       *
       * @return {@code true} if forward button (button 5) is currently pressed
       * @since 12
       */
      public final boolean isForwardButtonDown() {}

      modules/javafx.graphics/src/main/java/javafx/scene/input/MouseDragEvent.java:

      diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseDragEvent.java b/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseDragEvent.java
      index 588b65a20d..7bbdae7062 100644
      --- a/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseDragEvent.java
      +++ b/modules/javafx.graphics/src/main/java/javafx/scene/input/MouseDragEvent.java
      @@ -130,40 +130,104 @@
      
           /**
            * Constructs new MouseDragEvent event.
      -     * @param source the source of the event. Can be null.
      -     * @param target the target of the event. Can be null.
      -     * @param eventType The type of the event.
      -     * @param x The x with respect to the scene.
      -     * @param y The y with respect to the scene.
      -     * @param screenX The x coordinate relative to screen.
      -     * @param screenY The y coordinate relative to screen.
      +     *
      +     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
      +     * will return {@literal false} for this event
      +     *
      +     * @param source the source of the event, which can be {@code null}
      +     * @param target the target of the event, which can be {@code null}
      +     * @param eventType The type of the event
      +     * @param x The x with respect to the scene
      +     * @param y The y with respect to the scene
      +     * @param screenX The x coordinate relative to screen
      +     * @param screenY The y coordinate relative to screen
            * @param button the mouse button used
            * @param clickCount number of click counts
      -     * @param shiftDown true if shift modifier was pressed.
      -     * @param controlDown true if control modifier was pressed.
      -     * @param altDown true if alt modifier was pressed.
      -     * @param metaDown true if meta modifier was pressed.
      -     * @param primaryButtonDown true if primary button was pressed.
      -     * @param middleButtonDown true if middle button was pressed.
      -     * @param secondaryButtonDown true if secondary button was pressed.
      +     * @param shiftDown true if shift modifier was pressed
      +     * @param controlDown true if control modifier was pressed
      +     * @param altDown true if alt modifier was pressed
      +     * @param metaDown true if meta modifier was pressed
      +     * @param primaryButtonDown true if primary button was pressed
      +     * @param middleButtonDown true if middle button was pressed
      +     * @param secondaryButtonDown true if secondary button was pressed
            * @param synthesized if this event was synthesized
            * @param popupTrigger whether this event denotes a popup trigger for current platform
            * @param pickResult pick result. Can be null, in this case a 2D pick result
            *                   without any further values is constructed
            *                   based on the scene coordinates and target
      -     * @param gestureSource source object of the ongoing gesture.
      +     * @param gestureSource source object of the ongoing gesture
            * @since JavaFX 8.0
            */
      -    public MouseDragEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target, @NamedArg("eventType") EventType<MouseDragEvent> eventType,
      -            @NamedArg("x") double x, @NamedArg("y") double y, @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
      -            @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
      -            @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
      -            @NamedArg("primaryButtonDown") boolean primaryButtonDown, @NamedArg("middleButtonDown") boolean middleButtonDown, @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
      -            @NamedArg("synthesized") boolean synthesized, @NamedArg("popupTrigger") boolean popupTrigger, @NamedArg("pickResult") PickResult pickResult,
      -            @NamedArg("gestureSource") Object gestureSource) {
      +    public MouseDragEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target,
      +                          @NamedArg("eventType") EventType<MouseDragEvent> eventType,
      +                          @NamedArg("x") double x, @NamedArg("y") double y,
      +                          @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
      +                          @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
      +                          @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
      +                          @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
      +                          @NamedArg("primaryButtonDown") boolean primaryButtonDown,
      +                          @NamedArg("middleButtonDown") boolean middleButtonDown,
      +                          @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
      +                          @NamedArg("synthesized") boolean synthesized,
      +                          @NamedArg("popupTrigger") boolean popupTrigger,
      +                          @NamedArg("pickResult") PickResult pickResult,
      +                          @NamedArg("gestureSource") Object gestureSource) {
      +
      +    /**
      +     * Constructs new MouseDragEvent event.
      +     *
      +     * @param source the source of the event, which can be {@code null}
      +     * @param target the target of the event, which can be {@code null}
      +     * @param eventType The type of the event
      +     * @param x The x with respect to the scene
      +     * @param y The y with respect to the scene
      +     * @param screenX The x coordinate relative to screen
      +     * @param screenY The y coordinate relative to screen
      +     * @param button the mouse button used
      +     * @param clickCount number of click counts
      +     * @param shiftDown true if shift modifier was pressed
      +     * @param controlDown true if control modifier was pressed
      +     * @param altDown true if alt modifier was pressed
      +     * @param metaDown true if meta modifier was pressed
      +     * @param primaryButtonDown true if primary button was pressed
      +     * @param middleButtonDown true if middle button was pressed
      +     * @param secondaryButtonDown true if secondary button was pressed
      +     * @param backButtonDown true if back button was pressed
      +     * @param forwardButtonDown true if forward button was pressed
      +     * @param synthesized if this event was synthesized
      +     * @param popupTrigger whether this event denotes a popup trigger for current platform
      +     * @param pickResult pick result. Can be null, in this case a 2D pick result
      +     *                   without any further values is constructed
      +     *                   based on the scene coordinates and target
      +     * @param gestureSource source object of the ongoing gesture
      +     * @since 12
      +     */
      +    public MouseDragEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target,
      +                          @NamedArg("eventType") EventType<MouseDragEvent> eventType,
      +                          @NamedArg("x") double x, @NamedArg("y") double y,
      +                          @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
      +                          @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
      +                          @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
      +                          @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
      +                          @NamedArg("primaryButtonDown") boolean primaryButtonDown,
      +                          @NamedArg("middleButtonDown") boolean middleButtonDown,
      +                          @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
      +                          @NamedArg("backButtonDown") boolean backButtonDown,
      +                          @NamedArg("forwardButtonDown") boolean forwardButtonDown,
      +                          @NamedArg("synthesized") boolean synthesized,
      +                          @NamedArg("popupTrigger") boolean popupTrigger,
      +                          @NamedArg("pickResult") PickResult pickResult,
      +                          @NamedArg("gestureSource") Object gestureSource) {
      @@ -171,35 +235,43 @@ public MouseDragEvent(@NamedArg("source") Object source, @NamedArg("target") Eve
           /**
            * Constructs new MouseDragEvent event with null source and target.
            *
      -     * @param eventType The type of the event.
      -     * @param x The x with respect to the scene.
      -     * @param y The y with respect to the scene.
      -     * @param screenX The x coordinate relative to screen.
      -     * @param screenY The y coordinate relative to screen.
      +     * Both {@link #isBackButtonDown()}  and {@link #isForwardButtonDown()}
      +     * will return {@literal false} for this event.
      +     *
      +     * @param eventType The type of the event
      +     * @param x The x with respect to the scene
      +     * @param y The y with respect to the scene
      +     * @param screenX The x coordinate relative to screen
      +     * @param screenY The y coordinate relative to screen
            * @param button the mouse button used
            * @param clickCount number of click counts
      -     * @param shiftDown true if shift modifier was pressed.
      -     * @param controlDown true if control modifier was pressed.
      -     * @param altDown true if alt modifier was pressed.
      -     * @param metaDown true if meta modifier was pressed.
      -     * @param primaryButtonDown true if primary button was pressed.
      -     * @param middleButtonDown true if middle button was pressed.
      -     * @param secondaryButtonDown true if secondary button was pressed.
      +     * @param shiftDown true if shift modifier was pressed
      +     * @param controlDown true if control modifier was pressed
      +     * @param altDown true if alt modifier was pressed
      +     * @param metaDown true if meta modifier was pressed
      +     * @param primaryButtonDown true if primary button was pressed
      +     * @param middleButtonDown true if middle button was pressed
      +     * @param secondaryButtonDown true if secondary button was pressed
            * @param synthesized if this event was synthesized
            * @param popupTrigger whether this event denotes a popup trigger for current platform
            * @param pickResult pick result. Can be null, in this case a 2D pick result
            *                   without any further values is constructed
            *                   based on the scene coordinates
      -     * @param gestureSource source object of the ongoing gesture.
      +     * @param gestureSource source object of the ongoing gesture
            * @since JavaFX 8.0
            */
           public MouseDragEvent(@NamedArg("eventType") EventType<MouseDragEvent> eventType,
      -            @NamedArg("x") double x, @NamedArg("y") double y, @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
      -            @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
      -            @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
      -            @NamedArg("primaryButtonDown") boolean primaryButtonDown, @NamedArg("middleButtonDown") boolean middleButtonDown, @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
      -            @NamedArg("synthesized") boolean synthesized, @NamedArg("popupTrigger") boolean popupTrigger, @NamedArg("pickResult") PickResult pickResult,
      -            @NamedArg("gestureSource") Object gestureSource) {
      +                          @NamedArg("x") double x, @NamedArg("y") double y,
      +                          @NamedArg("screenX") double screenX, @NamedArg("screenY") double screenY,
      +                          @NamedArg("button") MouseButton button, @NamedArg("clickCount") int clickCount,
      +                          @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown,
      +                          @NamedArg("altDown") boolean altDown, @NamedArg("metaDown") boolean metaDown,
      +                          @NamedArg("primaryButtonDown") boolean primaryButtonDown,
      +                          @NamedArg("middleButtonDown") boolean middleButtonDown,
      +                          @NamedArg("secondaryButtonDown") boolean secondaryButtonDown,
      +                          @NamedArg("synthesized") boolean synthesized, @NamedArg("popupTrigger") boolean popupTrigger,
      +                          @NamedArg("pickResult") PickResult pickResult,
      +                          @NamedArg("gestureSource") Object gestureSource) {

      modules/javafx.graphics/src/main/java/javafx/scene/input/MouseButton.java:

      public enum MouseButton {
      
          // ...
      
          /**
           * Represents back (button 4) mouse button.
           *
           * @since 12
           */
          BACK,
      
          /**
           * Represents forward (button 5) mouse button.
           *
           * @since 12
           */
          FORWARD;
      }

            mennen Michael Ennen
            duke J. Duke
            Kevin Rushforth
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: