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

[macos] Using trackpad continuous MouseDragged events is caused in JTextComponent, No MouseReleased event

XMLWordPrintable

    • In Review
    • generic
    • os_x

      ADDITIONAL SYSTEM INFORMATION :
      MacBook Air (M1, 2020), macOS Montery version 12.2.1, JDK 20 Early-Access Build 25 (2022/11/28) from jdk.java.net

      A DESCRIPTION OF THE PROBLEM :
      When clicking+dragging inside a JTextComponent (JTextPane, JTextField etc.) and then releasing outside the JTextComponent very often there will be no MouseReleased event fired and MouseDragged will be fired continuously. This only seems to happen when using the trackpad.

      When a user selects the text in a JTextComponent using the trackpad the continuous MouseDragged events cause new text to be selected immediately making it impossible to enter new text.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached test case, click inside the JTextComponent using the trackpad, drag outside the JTextComponent and release the trackpad. Repeat until exception is thrown (I was able to reproduce within 10 tries)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      No MouseDragged events should be fired after releasing the mouse (trackpad)
      ACTUAL -
      MouseDragged events are fired continuously after releasing the mouse (trackpad), the attached test case throws an exception after 5 invalid MouseDragged events

      ---------- BEGIN SOURCE ----------
      import java.awt.AWTEvent;
      import java.awt.Toolkit;
      import java.awt.event.AWTEventListener;
      import java.awt.event.MouseAdapter;
      import java.awt.event.MouseEvent;

      import javax.swing.JComponent;
      import javax.swing.JFrame;
      import javax.swing.JTextField;
      import javax.swing.SwingUtilities;

      public class MouseEventTests {

      boolean mouseDown = false;

      public MouseEventTests() {

      // AWT event listener doesn't seem to be affected, lets use this
      // to detect when mouse is down
      Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {

      @Override
      public void eventDispatched(AWTEvent event) {

      switch (event.getID()) {

      case MouseEvent.MOUSE_PRESSED:
      System.out.println("MouseEvent.MOUSE_PRESSED");
      mouseDown = true;
      break;

      case MouseEvent.MOUSE_RELEASED:
      System.out.println("MouseEvent.MOUSE_RELEASED");
      mouseDown = false;
      break;

      default:
      break;

      }

      }
      }, AWTEvent.MOUSE_EVENT_MASK);

      JFrame frame = new JFrame("Mouse Event Tests");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(600, 350);

      JComponent component;

      // Uncomment to test different components,
      // only text components seem to be affected
      component = new JTextField();
      // component = new JTextArea();
      // component = new JTextPane();
      // component = new JLabel();
      // component = new JButton();

      component.addMouseMotionListener(new MouseAdapter() {

      int invalidEventCount = 0;

      @Override
      public void mouseDragged(MouseEvent e) {

      System.out.println("mouseDragged, mouseDown = " + mouseDown);

      if (!mouseDown) {

      invalidEventCount++;
      if (invalidEventCount >= 5) {
      throw new IllegalStateException();
      }

      } else {
      invalidEventCount = 0;
      }

      }
      });

      // Place component in middle of frame so we can test different scenarios:
      // Start drag inside component, release outside frame: problem occurs
      // Start drag inside component, release outside component: problem occurs
      // Start drag inside component, release inside component: problem doesn't occur
      component.setBounds(100, 100, 400, 100);
      frame.getContentPane().setLayout(null);
      frame.getContentPane().add(component);

      frame.setLocationRelativeTo(null);
      frame.setVisible(true);

      }

      public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {

      @Override
      public void run() {
      new MouseEventTests();
      }
      });
      }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The attached test case uses a AWTEventListener to detect when the mouse is down, this can be used to check if a MouseDragged event fired by a component is valid. The only workaround I could find to stop the continuous MouseDragged events from being fired is to throw an exception.

      FREQUENCY : often


            honkar Harshitha Onkar
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: