diff --git a/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java b/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java new file mode 100644 index 00000000000..3f8d10651ff --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2000, 2025, 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. + */ + +/* + * @test + * @bug 4327618 4327623 4327639 4327654 4327664 4327666 4327676 4327679 4507822 + * @summary Tests that MouseDragged and MouseReleased are triggered by Button, + * Checkbox, Choice, Label, List, Scrollbar, TextArea, TextField + * for Left, Middle and Right mouse buttons + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main/othervm -Dsun.java2d.uiScale=1 DragMouseEventTest +*/ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.List; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Arrays; + +import test.java.awt.regtesthelpers.Util; + +public class DragMouseEventTest { + private static ExtendedRobot robot; + private static DragMouseEventFrame dmef; + private static final int DELAY = 200; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(DragMouseEventTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (dmef != null) { + dmef.dispose(); + } + }); + } + } + + private static void createAndShowGUI() { + dmef = new DragMouseEventFrame(); + dmef.setVisible(true); + } + + private static void test() throws Exception { + robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + testComponent(dmef.scrollbar); + testComponent(dmef.choice); + testComponent(dmef.textarea); + testComponent(dmef.textfield); + testComponent(dmef.checkbox); + testComponent(dmef.label); + testComponent(dmef.list); + testComponent(dmef.button); + } + + private static void testComponent(Component component) throws Exception { + Rectangle componentBounds = Util.invokeOnEDT(() -> { + Point locationOnScreen = component.getLocationOnScreen(); + Dimension size = component.getSize(); + return new Rectangle(locationOnScreen, size); + }); + + Rectangle frameBounds = Util.invokeOnEDT(() -> dmef.getBounds()); + + Point start = new Point(componentBounds.x + 10, componentBounds.y + 10); + + Adapter adapter = getAdapterFromComponent(component); + + testItemStateChanged(component, adapter, start, componentBounds); + testActionListener(component, adapter, start); + + Point mid = getEndPoint(start, frameBounds, 3); + Point end = getEndPoint(start, frameBounds, 15); + + testButtonDrag(component, adapter, MouseEvent.BUTTON1_DOWN_MASK, start, mid, end); + testButtonDrag(component, adapter, MouseEvent.BUTTON2_DOWN_MASK, start, mid, end); + testButtonDrag(component, adapter, MouseEvent.BUTTON3_DOWN_MASK, start, mid, end); + } + + private static Adapter getAdapterFromComponent(Component component) { + return (Adapter) Arrays + .stream(component.getMouseListeners()) + .filter((m) -> m instanceof Adapter) + .findFirst() + .orElseThrow(); + } + + private static void testItemStateChanged(Component component, + Adapter adapter, + Point start, + Rectangle componentBounds) { + if (!(component instanceof Choice + || component instanceof Checkbox + || component instanceof List)) { + return; + } + + System.out.println("\ntestItemStateChanged " + component); + + adapter.reset(); + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + robot.click(); + + if (component instanceof Choice) { + robot.mouseMove(start.x, componentBounds.y + componentBounds.height + 25); + robot.waitForIdle(); + robot.click(); + } + + robot.waitForIdle(); + + if (!adapter.itemStateChangedReceived) { + throw new RuntimeException("itemStateChanged was not received for " + component); + } + } + + private static void testActionListener(Component component, + Adapter adapter, + Point start) { + if (!(component instanceof Button || component instanceof List)) { + // skip for not applicable components + return; + } + + System.out.println("\ntestActionListener " + component); + adapter.reset(); + + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + + if (component instanceof List) { + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(DELAY); + } else { + robot.click(); + } + + robot.waitForIdle(); + robot.delay(DELAY); + + if (!adapter.actionPerformedReceived) { + throw new RuntimeException("actionPerformed was not received for " + component); + } + } + + private static String getButtonName(int button) { + return switch (button) { + case MouseEvent.BUTTON1_DOWN_MASK -> "BUTTON1"; + case MouseEvent.BUTTON2_DOWN_MASK -> "BUTTON2"; + case MouseEvent.BUTTON3_DOWN_MASK -> "BUTTON3"; + default -> throw new IllegalStateException("Unexpected value: " + button); + }; + } + + private static void testButtonDrag(Component component, + Adapter adapter, + int button, + Point start, Point mid, Point end) { + String buttonName = getButtonName(button); + System.out.printf("\n> testButtonDrag: %s on %s\n", + buttonName, component); + + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + + robot.mousePress(button); + robot.waitForIdle(); + + System.out.printf("> gliding from (%d,%d) to (%d,%d)\n", + start.x, start.y, mid.x, mid.y); + robot.glide(start, mid); + robot.waitForIdle(); + robot.delay(DELAY); + + + // Catch events only after we leave the frame boundaries + adapter.reset(); + + System.out.printf("> gliding after crossing the border (%d,%d) to (%d,%d)\n", + mid.x, mid.y, end.x, end.y); + robot.glide(mid, end); + + robot.mouseRelease(button); + robot.waitForIdle(); + robot.delay(DELAY); + System.out.printf("> %s released\n", buttonName); + + boolean mouseDraggedReceived = adapter.mouseDraggedReceived; + boolean mouseReleasedReceived = adapter.mouseReleasedReceived; + + if (component instanceof Choice) { + // Close the popup if it is still open + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.delay(25); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); + robot.delay(DELAY); + } + + + if (!mouseDraggedReceived || !mouseReleasedReceived) { + throw new RuntimeException(("%d: Mouse drag or release was not received\n" + + "mouseDraggedReceived %b mouseReleasedReceived %b") + .formatted(button, mouseDraggedReceived, mouseReleasedReceived)); + } + } + + /* + * returns the closest border point with a specified offset + */ + private static Point getEndPoint(Point start, Rectangle bounds, int offset) { + int left = bounds.x; + int right = bounds.x + bounds.width; + int top = bounds.y; + int bottom = bounds.y + bounds.height; + + int distanceLeft = start.x - left; + int distanceRight = right - start.x; + int distanceTop = start.y - top; + int distanceBottom = bottom - start.y; + + int minDistance = Math.min( + Math.min(distanceLeft, distanceRight), + Math.min(distanceTop, distanceBottom) + ); + + if (minDistance == distanceLeft) { + return new Point(left - offset, start.y); + } else if (minDistance == distanceRight) { + return new Point(right + offset, start.y); + } else if (minDistance == distanceTop) { + return new Point(start.x, top - offset); + } else { + return new Point(start.x, bottom + offset); + } + } + + private static class DragMouseEventFrame extends Frame { + TextArea textarea = new TextArea("TextArea", 20, 30); + Label label = new Label("Label"); + Panel panel = new Panel(); + List list = new List(); + Choice choice = new Choice(); + Button button = new Button("Button"); + TextField textfield = new TextField("TextField"); + Checkbox checkbox = new Checkbox("CheckBox"); + Scrollbar scrollbar = new Scrollbar(); + Panel centerPanel = new Panel(); + + public DragMouseEventFrame() { + setTitle("DragMouseEventTest"); + + add(centerPanel, BorderLayout.CENTER); + centerPanel.setLayout(new FlowLayout()); + + add(panel, BorderLayout.NORTH); + panel.setLayout(new FlowLayout()); + + choice.add("choice item 1"); + choice.add("choice item 2"); + choice.add("choice item 3"); + panel.add(choice); + + Adapter adapter = new Adapter(); + choice.addMouseMotionListener(adapter); + choice.addMouseListener(adapter); + choice.addItemListener(adapter); + + adapter = new Adapter(); + panel.add(label); + label.addMouseMotionListener(adapter); + label.addMouseListener(adapter); + + adapter = new Adapter(); + panel.add(button); + button.addMouseMotionListener(adapter); + button.addMouseListener(adapter); + button.addActionListener(adapter); + + adapter = new Adapter(); + panel.add(checkbox); + checkbox.addMouseMotionListener(adapter); + checkbox.addMouseListener(adapter); + checkbox.addItemListener(adapter); + + adapter = new Adapter(); + panel.add(textfield, BorderLayout.EAST); + textfield.addMouseMotionListener(adapter); + textfield.addMouseListener(adapter); + textfield.addActionListener(adapter); + + adapter = new Adapter(); + add(textarea, BorderLayout.EAST); + textarea.addMouseMotionListener(adapter); + textarea.addMouseListener(adapter); + + adapter = new Adapter(); + list.add("list item 1"); + list.add("list item 2"); + add(list, BorderLayout.SOUTH); + list.addMouseMotionListener(adapter); + list.addMouseListener(adapter); + list.addActionListener(adapter); + list.addItemListener(adapter); + + adapter = new Adapter(); + add(scrollbar, BorderLayout.WEST); + scrollbar.addMouseMotionListener(adapter); + scrollbar.addMouseListener(adapter); + + setSize(500, 400); + setLocationRelativeTo(null); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + DragMouseEventFrame.this.dispose(); + } + }); + } + } + + private static class Adapter extends MouseAdapter + implements ActionListener, ItemListener { + + public volatile boolean mouseDraggedReceived = false; + public volatile boolean mouseReleasedReceived = false; + public volatile boolean itemStateChangedReceived = false; + public volatile boolean actionPerformedReceived = false; + + + public void mouseDragged(MouseEvent me) { + mouseDraggedReceived = true; + System.out.println(me.paramString()); + } + + private void consumeIfNeeded(MouseEvent me) { + Component c = me.getComponent(); + // do not show popup menu for the following components, + // as it may interfere with the testing. + if (c instanceof TextArea + || c instanceof TextField + || c instanceof Scrollbar) { + if (me.isPopupTrigger()) { + System.out.println("CONSUMED: " + me); + me.consume(); + } + } + } + + public void mouseReleased(MouseEvent me) { + consumeIfNeeded(me); + mouseReleasedReceived = true; + System.out.println(me.paramString()); + } + + public void mousePressed(MouseEvent me) { + consumeIfNeeded(me); + System.out.println(me.paramString()); + } + + public void mouseClicked(MouseEvent me) { + System.out.println(me.paramString()); + } + + public void actionPerformed(ActionEvent e) { + actionPerformedReceived = true; + System.out.println(e.paramString()); + } + + public void itemStateChanged(ItemEvent e) { + itemStateChangedReceived = true; + System.out.println(e.paramString()); + } + + public void reset() { + mouseDraggedReceived = false; + mouseReleasedReceived = false; + itemStateChangedReceived = false; + actionPerformedReceived = false; + } + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java b/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java new file mode 100644 index 00000000000..4a4c9d36af1 --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 1999, 2025, 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. + */ + +/* + * @test + * @bug 4017222 + * @summary Checks whether mouse events are reported correctly during drag. + * @author Stuart Lawrence, Brent Christian: area=event + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main MouseEventsDuringDrag + */ + + +/* + * MouseEventsDuringDrag.java + * + * summary: + * On Solaris drag enter/exit events are only reported for the + * component where drag started, they're not reported on other + * components. On Win32 enter/exit events are reported correctly. + */ + +import test.java.awt.regtesthelpers.Util; + +import java.awt.Canvas; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class MouseEventsDuringDrag { + + private static ExtendedRobot robot; + private static Frame frame; + + private static final MouseHandler mouseHandler = new MouseHandler(); + + static Label lab; + static Canvas c1, c2; + static Choice choice; + + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(MouseEventsDuringDrag::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + // Part 1: Press and hold down the mouse button inside the red box. + // Drag the mouse over to the blue box (whilst still holding down + // the mouse button). + // Whilst dragging the mouse from the red box, enter and exit + // events should be reported for the blue box. + testcase(c2, "c1 to c2"); + + // Part 2: Again, press and hold down the mouse button inside the red box. + // This time drag the mouse over to the Choice menu. + // Enter and exit events should be reported for the Choice menu. + testcase(choice, "c1 to choice"); + } + + private static void testcase(Component moveTo, String message) throws Exception { + System.out.println("\ntestcase: " + message); + Rectangle c1bounds = getBounds(c1); + Rectangle moveToBound = getBounds(moveTo); + + Point startDragLocation = + new Point(c1bounds.x + c1bounds.width - 10, + c1bounds.y + c1bounds.height / 2); + + Point endDragLocation = + new Point(moveToBound.x + 10, moveToBound.y + moveToBound.height / 2); + + robot.mouseMove(startDragLocation); + robot.waitForIdle(); + robot.delay(200); + mouseHandler.reset(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + robot.glide(startDragLocation, endDragLocation); + robot.waitForIdle(); + + robot.glide(endDragLocation.x, endDragLocation.y, endDragLocation.x - 20, endDragLocation.y); + + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + robot.delay(200); + + List actual = mouseHandler.getRecordedEvents(); + + List expected = List.of( + new EventRecord(MouseEvent.MOUSE_PRESSED, c1), + new EventRecord(MouseEvent.MOUSE_EXITED, c1), + new EventRecord(MouseEvent.MOUSE_ENTERED, moveTo), + new EventRecord(MouseEvent.MOUSE_EXITED, moveTo), + new EventRecord(MouseEvent.MOUSE_RELEASED, c1) + ); + + System.out.println("Expected:\n" + expected); + System.out.println("Actual:\n" + actual); + if (!actual.equals(expected)) { + throw new RuntimeException("Mismatch between expected and actual events\n%s\n%s" + .formatted(expected, actual)); + } + } + + private static Rectangle getBounds(Component c) throws Exception { + return Util.invokeOnEDT(() -> { + Point locationOnScreen = c.getLocationOnScreen(); + Dimension size = c.getSize(); + return new Rectangle(locationOnScreen.x, locationOnScreen.y, size.width, size.height); + }); + } + + private static void createAndShowGUI() { + frame = new Frame(); + MouseHandler mouseHandler = new MouseHandler(); + frame.setLayout(new GridBagLayout()); + + int canvasSize = 100; + c1 = new Canvas(); + c1.setPreferredSize(new Dimension(canvasSize, canvasSize)); + c1.setBackground(Color.red); + c1.addMouseListener(mouseHandler); + + c2 = new Canvas(); + c2.setPreferredSize(new Dimension(canvasSize, canvasSize)); + c2.setBackground(Color.blue); + c2.addMouseListener(mouseHandler); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.insets = new Insets(5, 5, 5, 5); + + gbc.gridx = 0; + gbc.gridy = 0; + frame.add(c1, gbc); + + gbc.gridx = 2; + frame.add(c2, gbc); + + Panel p1 = new Panel(); + p1.setLayout(new FlowLayout()); + choice = new Choice(); + choice.addItem("Choice"); + choice.addItem("One"); + choice.addItem("Two"); + choice.addMouseListener(mouseHandler); + p1.add(choice); + + gbc.gridx = 1; + gbc.gridy = 1; + frame.add(p1, gbc); + + lab = new Label(); + + gbc.gridx = 0; + gbc.gridy = 2; + gbc.gridwidth = 3; + frame.add(lab, gbc); + + frame.pack(); + frame.setLocationRelativeTo(null); + + frame.setVisible(true); + } + + record EventRecord(int eventId, Component component) { + + @Override + public String toString() { + StringBuilder str = new StringBuilder(80); + switch(eventId) { + case MouseEvent.MOUSE_PRESSED: + str.append("MOUSE_PRESSED"); + break; + case MouseEvent.MOUSE_RELEASED: + str.append("MOUSE_RELEASED"); + break; + case MouseEvent.MOUSE_CLICKED: + str.append("MOUSE_CLICKED"); + break; + case MouseEvent.MOUSE_ENTERED: + str.append("MOUSE_ENTERED"); + break; + case MouseEvent.MOUSE_EXITED: + str.append("MOUSE_EXITED"); + break; + case MouseEvent.MOUSE_MOVED: + str.append("MOUSE_MOVED"); + break; + case MouseEvent.MOUSE_DRAGGED: + str.append("MOUSE_DRAGGED"); + break; + case MouseEvent.MOUSE_WHEEL: + str.append("MOUSE_WHEEL"); + break; + default: + str.append("unknown type"); + } + return str.append(" ").append(component).toString(); + } + } + + static class MouseHandler extends MouseAdapter { + static final List list = new CopyOnWriteArrayList<>(); + + public void mousePressed(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse pressed in red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse pressed in blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse pressed in choice"); + } + } + + public void mouseReleased(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + lab.setText("Mouse released"); + } + + public void mouseEntered(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse entered red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse entered blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse entered choice"); + } + } + + public void mouseExited(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse exited red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse exited blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse exited choice"); + } + } + + public void reset() { + list.clear(); + } + + public List getRecordedEvents() { + return new ArrayList<>(list); + } + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java b/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java new file mode 100644 index 00000000000..5b8f0f62f7b --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 1999, 2025, 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. + */ + +/* + * @test + * @bug 4117523 + * @summary Solaris: MousePressed event has modifier=0 when left button is pressed + * @key headful + * @library /javax/swing/regtesthelpers /test/lib + * @build Util jdk.test.lib.Platform + * @run main MouseModifierTest +*/ + + +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import jdk.test.lib.Platform; + +public class MouseModifierTest { + private static Frame frame; + private static volatile MouseEvent lastMousePressedEvent = null; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(MouseModifierTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + Point centerPoint = Util.getCenterPoint(frame); + + System.out.println("MOUSE1 press case"); + + robot.mouseMove(centerPoint.x, centerPoint.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(300); + + if (lastMousePressedEvent == null + || lastMousePressedEvent.getModifiers() != InputEvent.BUTTON1_MASK) { + throw new RuntimeException("Test failed"); + } + + if (Platform.isWindows()) { + System.out.println("Windows: Testing ALT + MOUSE1 press case"); + lastMousePressedEvent = null; + robot.waitForIdle(); + robot.delay(300); + + robot.keyPress(KeyEvent.VK_ALT); + robot.delay(25); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.keyRelease(KeyEvent.VK_ALT); + robot.delay(25); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(300); + + int expectedModifiers = InputEvent.BUTTON1_MASK + | InputEvent.BUTTON2_MASK + | InputEvent.ALT_MASK; + if (lastMousePressedEvent == null + || lastMousePressedEvent.getModifiers() != expectedModifiers) { + throw new RuntimeException("Test failed"); + } + } + } + + private static void createAndShowGUI() { + frame = new Frame("MouseModifierTest"); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.addMouseListener(new MouseHandler()); + frame.setVisible(true); + } + + private static class MouseHandler extends MouseAdapter { + public void mouseClicked(MouseEvent e) { + System.out.println("\nmouseClicked:"); + printMouseEventDetail(e); + } + + public void mousePressed(MouseEvent e) { + lastMousePressedEvent = e; + System.out.println("\nmousePressed:"); + printMouseEventDetail(e); + } + + public void mouseReleased(MouseEvent e) { + System.out.println("\nmouseReleased:"); + printMouseEventDetail(e); + } + + public void mouseEntered(MouseEvent e) { + System.out.println("\nmouseEntered:"); + printMouseEventDetail(e); + } + + public void mouseExited(MouseEvent e) { + System.out.println("\nmouseExited:"); + printMouseEventDetail(e); + } + + private void printMouseEventDetail(MouseEvent e) { + System.out.println(e.toString()); + System.out.println("Modifiers: "); + printModifiers(e); + } + + private void printModifiers(MouseEvent e) { + if (e == null) { + return; + } + + int mod = e.getModifiers(); + + if ((mod & InputEvent.ALT_MASK) != 0) { + System.out.println("\tALT_MASK"); + } + if ((mod & InputEvent.BUTTON1_MASK) != 0) { + System.out.println("\tBUTTON1_MASK"); + } + if ((mod & InputEvent.BUTTON2_MASK) != 0) { + System.out.println("\tBUTTON2_MASK"); + } + if ((mod & InputEvent.BUTTON3_MASK) != 0) { + System.out.println("\tBUTTON3_MASK"); + } + if ((mod & InputEvent.CTRL_MASK) != 0) { + System.out.println("\tCTRL_MASK"); + } + if ((mod & InputEvent.META_MASK) != 0) { + System.out.println("\tMETA_MASK"); + } + if ((mod & InputEvent.SHIFT_MASK) != 0) { + System.out.println("\tSHIFT_MASK"); + } + } + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java b/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java new file mode 100644 index 00000000000..e5cb1195bae --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1998, 2025, 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. + */ + +/* + * @test + * @bug 4037521 + * @summary Mouse Right button does not send mouseClick action + * @key headful + * @library /javax/swing/regtesthelpers + * @build Util + * @run main MouseRButTest + */ + +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class MouseRButTest { + private static Frame frame; + private static Button button; + private static final CountDownLatch latch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(MouseRButTest::createAndShowGUI); + + robot.waitForIdle(); + robot.delay(500); + + Point point = Util.getCenterPoint(button); + robot.mouseMove(point.x, point.y); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + + if (!latch.await(2, TimeUnit.SECONDS)) { + throw new RuntimeException("mouse click action was not sent"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowGUI() { + button = new Button("Click Me"); + button.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + System.out.println(e); + if (e.getModifiers() == e.BUTTON3_MASK) { + System.out.println("right mouse button clicked"); + latch.countDown(); + } + } + }); + + frame = new Frame(); + frame.setLayout(new FlowLayout()); + frame.add(button); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java b/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java new file mode 100644 index 00000000000..35f071a9e6d --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999, 2025, 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.Frame; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 4074498 + * @summary Test: MOUSE_PRESSED events in the title bar of a frame + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TitleBarGetsMousePressed + */ +public class TitleBarGetsMousePressed { + private static final String INSTRUCTIONS = """ + 1. You will see a Frame window next to this window with instructions + 2. Clicking in the title bar of the Frame and even moving around the Frame + should not generate MOUSE_PRESSED / MOUSE_RELEASED / MOUSE_CLICKED events. + (printed below in the log area). + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("TitleBarGetsMousePressed Instructions") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TitleBarGetsMousePressed::createTestUI) + .logArea(5) + .build() + .awaitAndCheck(); + } + + private static Window createTestUI() { + Frame frame = new Frame("TitleBarGetsMousePressed"); + frame.setSize(300, 200); + frame.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent ev) { + PassFailJFrame.log("mouseClicked at x:" + ev.getX() + + " y:" + ev.getY()); + } + + public void mousePressed(MouseEvent ev) { + PassFailJFrame.log("mousePressed at x:" + ev.getX() + + " y:" + ev.getY()); + } + + public void mouseReleased(MouseEvent ev) { + PassFailJFrame.log("mouseReleased at x:" + ev.getX() + + " y:" + ev.getY()); + } + }); + + return frame; + } +}