8188081: Text selection does not clear after focus is lost
Reviewed-by: serb, psadhukhan
--- a/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java Mon Oct 23 13:06:04 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java Tue Oct 24 08:37:11 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -352,6 +352,7 @@
setVisible(true);
}
setSelectionVisible(true);
+ updateSystemSelection();
}
}
@@ -365,7 +366,9 @@
*/
public void focusLost(FocusEvent e) {
setVisible(false);
- setSelectionVisible(ownsSelection || e.isTemporary());
+ setSelectionVisible((e.getCause() == FocusEvent.Cause.ACTIVATION ||
+ e.getOppositeComponent() instanceof JRootPane) &&
+ (ownsSelection || e.isTemporary()));
}
@@ -866,7 +869,6 @@
Highlighter.HighlightPainter p = getSelectionPainter();
try {
selectionTag = h.addHighlight(p0, p1, p);
- updateOwnsSelection();
} catch (BadLocationException bl) {
selectionTag = null;
}
@@ -877,7 +879,6 @@
Highlighter h = component.getHighlighter();
h.removeHighlight(selectionTag);
selectionTag = null;
- updateOwnsSelection();
}
}
}
@@ -1119,7 +1120,6 @@
if (selectionTag != null) {
h.removeHighlight(selectionTag);
selectionTag = null;
- updateOwnsSelection();
}
// otherwise, change or add the highlight
} else {
@@ -1130,7 +1130,6 @@
Highlighter.HighlightPainter p = getSelectionPainter();
selectionTag = h.addHighlight(p0, p1, p);
}
- updateOwnsSelection();
} catch (BadLocationException e) {
throw new StateInvariantError("Bad caret position");
}
@@ -1181,7 +1180,6 @@
if (this.dot != dot || this.dotBias != dotBias ||
selectionTag != null || forceCaretPositionChange) {
changeCaretPosition(dot, dotBias);
- updateOwnsSelection();
}
this.markBias = this.dotBias;
this.markLTR = dotLTR;
@@ -1189,7 +1187,6 @@
if ((h != null) && (selectionTag != null)) {
h.removeHighlight(selectionTag);
selectionTag = null;
- updateOwnsSelection();
}
}
@@ -1940,13 +1937,6 @@
}
}
- /**
- * Updates ownsSelection based on text selection in the caret.
- */
- private void updateOwnsSelection() {
- ownsSelection = (selectionTag != null)
- && SwingUtilities2.canAccessSystemClipboard();
- }
private class DefaultFilterBypass extends NavigationFilter.FilterBypass {
public Caret getCaret() {
--- a/test/jdk/javax/swing/JTextPane/bug8025082.java Mon Oct 23 13:06:04 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @key headful
- * @bug 8025082
- * @summary The behaviour of the highlight will be lost after clicking the set
- * button.
- * @run main bug8025082
- */
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
-import javax.swing.*;
-
-public class bug8025082 {
-
- private static JButton button;
- private static JFrame frame;
-
- public static void main(String[] args) throws Exception {
- Robot robo = new Robot();
- robo.delay(500);
-
- SwingUtilities.invokeAndWait(new Runnable() {
- public void run() {
- createUI();
- }
- });
-
- robo.waitForIdle();
- Point point = getButtonLocationOnScreen();
- robo.mouseMove(point.x, point.y);
- robo.mousePress(InputEvent.BUTTON1_MASK);
- robo.mouseRelease(InputEvent.BUTTON1_MASK);
- robo.waitForIdle();
-
- SwingUtilities.invokeAndWait(new Runnable() {
- public void run() {
- frame.dispose();
- }
- });
- }
-
- private static void createUI() {
- frame = new JFrame();
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setSize(500, 500);
- JTextPane textpane = new JTextPane();
- textpane.setText("Select Me");
- textpane.selectAll();
-
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(textpane, BorderLayout.CENTER);
- button = new JButton("Press Me");
- panel.add(button, BorderLayout.SOUTH);
-
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- if (!textpane.getCaret().isSelectionVisible()) {
- throw new RuntimeException("Highlight removed after "
- + "button click");
- }
- }
- });
-
- frame.getContentPane().add(panel);
- frame.setLocationRelativeTo(null);
- frame.setVisible(true);
- }
-
- private static Point getButtonLocationOnScreen() throws Exception {
- final Point[] result = new Point[1];
-
- SwingUtilities.invokeAndWait(new Runnable() {
- @Override
- public void run() {
- Point point = button.getLocationOnScreen();
- point.x += button.getWidth() / 2;
- point.y += button.getHeight() / 2;
- result[0] = point;
- }
- });
- return result[0];
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java Tue Oct 24 08:37:11 2017 -0700
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017, 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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.image.BufferedImage;
+
+/**
+ * @test
+ * @bug 8188081
+ * @summary Text selection does not clear after focus is lost
+ * @run main HidingSelectionTest
+ */
+
+public class HidingSelectionTest {
+
+ private static JTextField field1;
+ private static JTextField field2;
+ private static JFrame frame;
+ private static Rectangle bounds;
+ private static JMenu menu;
+ private static JTextField anotherWindow;
+ private static Point menuLoc;
+ private static JFrame frame2;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ frame = new JFrame();
+ field1 = new JTextField("field1 ");
+ field2 = new JTextField("field2 ");
+ field1.setEditable(false);
+ field2.setEditable(false);
+ frame.getContentPane().setLayout(new FlowLayout());
+ frame.getContentPane().add(field1);
+ frame.getContentPane().add(field2);
+ JMenuBar menuBar = new JMenuBar();
+ menu = new JMenu("menu");
+ menu.add(new JMenuItem("item"));
+ menuBar.add(menu);
+ frame.setJMenuBar(menuBar);
+ frame.pack();
+ frame.setVisible(true);
+ });
+
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ robot.delay(200);
+ SwingUtilities.invokeAndWait(() -> {
+ bounds = field2.getBounds();
+ bounds.setLocation(field2.getLocationOnScreen());
+ });
+ BufferedImage nosel = robot.createScreenCapture(bounds);
+
+ SwingUtilities.invokeAndWait(field2::requestFocus);
+ SwingUtilities.invokeAndWait(field2::selectAll);
+ robot.waitForIdle();
+ robot.delay(200);
+ BufferedImage sel = robot.createScreenCapture(bounds);
+
+ SwingUtilities.invokeAndWait(() -> {
+ menuLoc = menu.getLocationOnScreen();
+ menuLoc.translate(10, 10);
+ });
+ robot.mouseMove(menuLoc.x, menuLoc.y);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ robot.delay(50);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ robot.waitForIdle();
+ robot.delay(200);
+ if (!biEqual(robot.createScreenCapture(bounds), sel)) {
+ throw new RuntimeException("Test fails: menu hides selection");
+ }
+
+ SwingUtilities.invokeAndWait(
+ MenuSelectionManager.defaultManager()::clearSelectedPath);
+ SwingUtilities.invokeAndWait(field1::requestFocus);
+ robot.waitForIdle();
+ robot.delay(200);
+ if (!biEqual(robot.createScreenCapture(bounds), nosel)) {
+ throw new RuntimeException(
+ "Test fails: focus lost doesn't hide selection");
+ }
+
+ SwingUtilities.invokeAndWait(field2::requestFocus);
+ robot.waitForIdle();
+ SwingUtilities.invokeAndWait(() ->{
+ frame2 = new JFrame();
+ Point loc = frame.getLocationOnScreen();
+ loc.translate(0, frame.getHeight());
+ frame2.setLocation(loc);
+ anotherWindow = new JTextField("textField3");
+ frame2.add(anotherWindow);
+ frame2.pack();
+ frame2.setVisible(true);
+ });
+ robot.waitForIdle();
+ SwingUtilities.invokeAndWait(anotherWindow::requestFocus);
+ robot.waitForIdle();
+ robot.delay(200);
+ if (biEqual(robot.createScreenCapture(bounds), nosel)) {
+ throw new RuntimeException(
+ "Test fails: switch window hides selection");
+ }
+
+ SwingUtilities.invokeAndWait(anotherWindow::selectAll);
+ robot.waitForIdle();
+ robot.delay(200);
+ if (biEqual(robot.createScreenCapture(bounds), sel)) {
+ throw new RuntimeException(
+ "Test fails: selection ownership is lost selection is shown");
+ }
+
+ SwingUtilities.invokeLater(frame2::dispose);
+ SwingUtilities.invokeLater(frame::dispose);
+ }
+
+ static boolean biEqual(BufferedImage i1, BufferedImage i2) {
+ if (i1.getWidth() == i2.getWidth() &&
+ i1.getHeight() == i2.getHeight()) {
+ for (int x = 0; x < i1.getWidth(); x++) {
+ for (int y = 0; y < i1.getHeight(); y++) {
+ if (i1.getRGB(x, y) != i2.getRGB(x, y)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}