diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index c7168e9800e..74880fa728c 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -257,6 +257,9 @@ java/awt/print/PrinterJob/GlyphPositions.java 7003378 generic-all java/awt/Choice/ChoiceMouseWheelTest/ChoiceMouseWheelTest.java 6849371 macosx-all,linux-all java/awt/Component/GetScreenLocTest/GetScreenLocTest.java 4753654 generic-all java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java 8165863 macosx-all +java/awt/Clipboard/PasteNullToTextComponentsTest.java 8234140 macosx-all,windows-all +java/awt/Clipboard/NoOwnerNoTargetsTest.java 8234140 macosx-all +java/awt/Clipboard/LostOwnershipChainTest/SystemClipboard2ProcTest.java 8234140 macosx-all java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java 8017454 macosx-all java/awt/Frame/MiscUndecorated/RepaintTest.java 8266244 macosx-aarch64 java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009 macosx-all diff --git a/test/jdk/java/awt/Clipboard/ClipRWTest.java b/test/jdk/java/awt/Clipboard/ClipRWTest.java new file mode 100644 index 00000000000..c173dd17f0d --- /dev/null +++ b/test/jdk/java/awt/Clipboard/ClipRWTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002, 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 4177171 4180145 4180148 + * @summary Can't copy to clipboard + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ClipRWTest + */ + +import java.awt.Button; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; + +public class ClipRWTest { + private static final String INSTRUCTIONS = """ + 1. Type some text in the text field and press Copy Text. + 2. Switch to a _native_ application (e.g. Notepad) and paste the text in + 3. Verify the text that is pasted matches what you typed in the Java window + 4. In the native app, type some new text and copy it + 5. Switch back to the test frame and press Paste Text + 6. Verify the text that is pasted matches what you typed in the native app + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("ClipRWTest Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(ClipFrame::new) + .build() + .awaitAndCheck(); + } + + private static class ClipFrame extends Frame { + TextField field =new TextField(50); + Button copyText = new Button("Copy Text"); + Button pasteText = new Button("Paste Text"); + Clipboard clipboard; + + public ClipFrame() { + super("ClipRWTest 4177171"); + setLayout(new FlowLayout()); + + clipboard = getToolkit().getSystemClipboard(); + + add(field); + add(copyText); + add(pasteText); + + copyText.addActionListener( + ev -> { + String text = field.getText(); + try { + clipboard.setContents(new StringSelection(text), null); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + ); + + pasteText.addActionListener( + ev -> { + String text = ""; + try { + text = (String) clipboard.getContents(null) + .getTransferData(DataFlavor.stringFlavor); + } catch (Exception ex) { + ex.printStackTrace(); + } + field.setText(text); + } + ); + + pack(); + } + } +} diff --git a/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/SystemClipboard2ProcTest.java b/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/SystemClipboard2ProcTest.java new file mode 100644 index 00000000000..9bd76ad0962 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/SystemClipboard2ProcTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2002, 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 4683804 + * @summary Tests that in ClipboardOwner.lostOwnership() Clipboard.getContents() + * returns actual contents of the clipboard and Clipboard.setContents() + * can set contents of the clipboard and its owner. The clipboard is + * the system clipboard and the owners of the clipboard are in + * 2 different processes. + * @key headful + * @library /test/lib + * @run main SystemClipboard2ProcTest +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class SystemClipboard2ProcTest { + + public static void main(String[] args) throws Exception { + SystemClipboardOwner.run(); + + if (SystemClipboardOwner.failed) { + throw new RuntimeException("test failed: can not get actual " + + "contents of the clipboard or set owner of the clipboard"); + } else { + System.err.println("test passed"); + } + } +} + +class SystemClipboardOwner implements ClipboardOwner { + static volatile boolean failed; + + private static final Object LOCK = new Object(); + + private static final int CHAIN_LENGTH = 5; + private final static Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + + private int m, id; + + public SystemClipboardOwner(int m) { this.m = m; id = m; } + + public void lostOwnership(Clipboard cb, Transferable contents) { + System.err.println(id + " lost clipboard ownership"); + + Transferable t = getClipboardContents(cb, null); + // for test passing if t.getTransferData() will throw an exception + String msg = "" + (m + 1); + try { + msg = (String)t.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + System.err.println(id + " can't getTransferData: " + e); + } + System.err.println(id + " Clipboard.getContents(): " + msg); + if (!msg.equals("" + (m + 1))) { + failed = true; + System.err.println("Clipboard.getContents() returned incorrect contents!"); + } + + m += 2; + if (m <= CHAIN_LENGTH) { + System.err.println(id + " Clipboard.setContents(): " + m); + setClipboardContents(cb, new StringSelection(m + ""), this); + } + if (m >= CHAIN_LENGTH) { + synchronized (LOCK) { + LOCK.notifyAll(); + } + } + } + + public static void run() throws Exception { + SystemClipboardOwner cbo1 = new SystemClipboardOwner(0); + System.err.println(cbo1.m + " Clipboard.setContents(): " + cbo1.m); + setClipboardContents(clipboard, new StringSelection(cbo1.m + ""), + cbo1); + + ProcessBuilder pb = ProcessTools + .createTestJavaProcessBuilder(SystemClipboardOwner.class.getName()); + + Process process = ProcessTools.startProcess("Child", pb); + OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process); + + if (!process.waitFor(15, TimeUnit.SECONDS)) { + process.destroyForcibly(); + throw new TimeoutException("Timed out waiting for Child"); + } + + outputAnalyzer.shouldHaveExitValue(0); + + if (cbo1.m < CHAIN_LENGTH) { + failed = true; + System.err.println("chain of calls of lostOwnership() broken!"); + } + } + + public static void main(String[] args) throws InterruptedException { + SystemClipboardOwner cbo2 = new SystemClipboardOwner(1); + System.err.println(cbo2.m + " Clipboard.setContents(): " + cbo2.m); + synchronized (LOCK) { + setClipboardContents(clipboard, new StringSelection(cbo2.m + ""), + cbo2); + LOCK.wait(); + } + } + + private static void setClipboardContents(Clipboard cb, + Transferable contents, + ClipboardOwner owner) { + synchronized (cb) { + boolean set = false; + while (!set) { + try { + cb.setContents(contents, owner); + set = true; + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } + + private static Transferable getClipboardContents(Clipboard cb, + Object requestor) { + synchronized (cb) { + while (true) { + try { + Transferable t = cb.getContents(requestor); + return t; + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } +} diff --git a/test/jdk/java/awt/Clipboard/NoOwnerNoTargetsTest.java b/test/jdk/java/awt/Clipboard/NoOwnerNoTargetsTest.java new file mode 100644 index 00000000000..178fe9b7074 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/NoOwnerNoTargetsTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2002, 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 4655996 + * @summary tests that getting the system clipboard contents doesn't cause + * IOException if there is no clipboard owner or the owner doesn't + * export any target types + * @key headful + * @library /test/lib + * @run main NoOwnerNoTargetsTest + */ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class NoOwnerNoTargetsTest implements ClipboardOwner { + + final Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + public static final int CLIPBOARD_DELAY = 1000; + + public static void main(String[] args) throws Exception { + if (args.length > 0) { + NoOwnerNoTargetsTest test = new NoOwnerNoTargetsTest(); + test.execute(); + return; + } + + new NoOwnerNoTargetsTest().start(); + } + + public void execute() { + final ClipboardOwner clipboardOwner = new ClipboardOwner() { + public void lostOwnership(Clipboard clip, + Transferable contents) { + System.exit(0); + } + }; + final Transferable emptyTransferable = new Transferable() { + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[0]; + } + public boolean isDataFlavorSupported(DataFlavor df) { + return false; + } + public Object getTransferData(DataFlavor df) + throws UnsupportedFlavorException { + throw new UnsupportedFlavorException(df); + } + }; + + clipboard.setContents(emptyTransferable, clipboardOwner); + final Object o = new Object(); + synchronized (o) { + try { + o.wait(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + + public void start() throws Exception { + clipboard.getContents(null); + + Transferable transferable = new StringSelection("TEXT"); + clipboard.setContents(transferable, this); + + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + NoOwnerNoTargetsTest.class.getName(), + "child" + ); + + Process process = ProcessTools.startProcess("Child", pb); + OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process); + + if (!process.waitFor(15, TimeUnit.SECONDS)) { + process.destroyForcibly(); + throw new TimeoutException("Timed out waiting for Child"); + } + + outputAnalyzer.shouldHaveExitValue(0); + } + + public void lostOwnership(Clipboard clip, Transferable contents) { + final Transferable transferable = new StringSelection("TEXT"); + final Runnable r = () -> { + try { + Thread.sleep(CLIPBOARD_DELAY); + } catch (InterruptedException e) { + e.printStackTrace(); + } + clipboard.getContents(null); + clipboard.setContents(transferable, null); + }; + final Thread t = new Thread(r); + t.start(); + } +} diff --git a/test/jdk/java/awt/Clipboard/PasteNullToTextComponentsTest.java b/test/jdk/java/awt/Clipboard/PasteNullToTextComponentsTest.java new file mode 100644 index 00000000000..191ba2288b7 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/PasteNullToTextComponentsTest.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2002, 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 4401853 + * @summary Tests that pasting null to TextArea and TextField on Solaris/Linux + * removes selected text; doing it on Windows to TextArea does nothing, + * to TextField removes selected text. + * @key headful + * @run main PasteNullToTextComponentsTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class PasteNullToTextComponentsTest { + + private static final int NATIVE_EVENT_PROCESSING_TIMEOUT = 500; + private static final int WAIT_TIMEOUT = 3000; + + private boolean failed; + + private static final boolean isOSWindows = + System.getProperty("os.name").startsWith("Windows"); + + private final Object LOCK = new Object(); + + private Robot robot; + + private Frame frame; + private TextArea ta; + private TextField tf; + private Component initialFocusComp; + + private final String beg = "a"; + private final String sel = "b"; + private final String end = "c"; + private final String text = beg + sel + end; + private final String begEnd = beg + end; + + private boolean initialFocusGained; + + public void init() { + ta = new TextArea(text, 3, text.length() + 3); + tf = new TextField(text, text.length() + 3); + initialFocusComp = new Button("Initially focused button"); + + frame = new Frame(); + frame.add(initialFocusComp, BorderLayout.NORTH); + frame.add(ta, BorderLayout.CENTER); + frame.add(tf, BorderLayout.SOUTH); + frame.setSize(200, 200); + + FocusListener fl = new FocusAdapter() { + public void focusGained(FocusEvent e) { + System.out.println(e + "; source class=" + e.getSource().getClass()); + synchronized (LOCK) { + TextComponent tc = (TextComponent) e.getComponent(); + tc.select(1, 2); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_V); + robot.keyRelease(KeyEvent.VK_V); + robot.keyRelease(KeyEvent.VK_CONTROL); + tc.removeFocusListener(this); + LOCK.notifyAll(); + } + } + }; + ta.addFocusListener(fl); + tf.addFocusListener(fl); + + initialFocusComp.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + System.out.println(e + "; source class=" + e.getSource().getClass()); + synchronized (LOCK) { + initialFocusGained = true; + LOCK.notifyAll(); + } + } + }); + + setClipboardContents(Toolkit.getDefaultToolkit().getSystemClipboard(), + new StringSelection(null), null); + + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public void start() throws Exception { + robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + Point iniFocusPoint = initialFocusComp.getLocationOnScreen(); + synchronized (LOCK) { + if (!initialFocusGained) { + robot.mouseMove(iniFocusPoint.x + 3, iniFocusPoint.y + 3); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + LOCK.wait(WAIT_TIMEOUT); + } + } + + initialFocusComp.requestFocusInWindow(); + robot.waitForIdle(); + + synchronized (LOCK) { + ta.requestFocusInWindow(); + LOCK.wait(WAIT_TIMEOUT); + } + + // wait until native control process key event (C^V) + robot.waitForIdle(); + robot.delay(NATIVE_EVENT_PROCESSING_TIMEOUT); + + synchronized (LOCK) { + tf.requestFocusInWindow(); + LOCK.wait(WAIT_TIMEOUT); + } + + // wait until native control process key event (C^V) + robot.waitForIdle(); + robot.delay(NATIVE_EVENT_PROCESSING_TIMEOUT); + + String taText = ta.getText(); + String tfText = tf.getText(); + + System.err.println("TextArea text=" + taText + + " TextField text=" + tfText); + + boolean taSelDeleted = begEnd.equals(taText); + boolean taSelRemained = text.equals(taText); + boolean tfSelDeleted = begEnd.equals(tfText); + + System.out.println("taSelDeleted = " + taSelDeleted); + System.out.println("taSelRemained = " + taSelRemained); + System.out.println("tfSelDeleted = " + tfSelDeleted); + + if (isOSWindows + ? !(taSelRemained && tfSelDeleted) + : !(taSelDeleted && tfSelDeleted)) { + failed = true; + } + + if (!initialFocusGained) { + System.err.println("Initial component did not gain focus"); + failed = false; + } + + if (failed) { + throw new RuntimeException("test failed: wrong behavior of text " + + "component on pasting null"); + } else { + System.err.println("test passed"); + } + } + + + private static void setClipboardContents(Clipboard cb, + Transferable contents, + ClipboardOwner owner) { + synchronized (cb) { + boolean set = false; + while (!set) { + try { + cb.setContents(contents, owner); + set = true; + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } + + public static void main(String[] args) throws Exception { + PasteNullToTextComponentsTest app = new PasteNullToTextComponentsTest(); + try { + EventQueue.invokeAndWait(app::init); + app.start(); + } finally { + EventQueue.invokeAndWait(() -> { + if (app.frame != null) { + app.frame.dispose(); + } + }); + } + } +}