jdk/test/java/awt/dnd/ImageTransferTest/ImageTransferTest.java
changeset 23652 11515e3c3f85
child 28087 622b2f420bc3
equal deleted inserted replaced
23651:e41298d0da2f 23652:11515e3c3f85
       
     1 /*
       
     2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25   @test
       
    26   @bug 4397404 4720930
       
    27   @summary tests that images of all supported native image formats are transfered properly
       
    28   @library ../../regtesthelpers/process/
       
    29   @build ProcessResults ProcessCommunicator
       
    30   @author gas@sparc.spb.su area=Clipboard
       
    31   @run main ImageTransferTest
       
    32 */
       
    33 
       
    34 import sun.awt.OSInfo;
       
    35 import sun.awt.SunToolkit;
       
    36 import test.java.awt.regtesthelpers.process.ProcessCommunicator;
       
    37 import test.java.awt.regtesthelpers.process.ProcessResults;
       
    38 
       
    39 import java.awt.*;
       
    40 import java.awt.datatransfer.DataFlavor;
       
    41 import java.awt.datatransfer.SystemFlavorMap;
       
    42 import java.awt.datatransfer.Transferable;
       
    43 import java.awt.datatransfer.UnsupportedFlavorException;
       
    44 import java.awt.dnd.DnDConstants;
       
    45 import java.awt.dnd.DragSource;
       
    46 import java.awt.dnd.DragSourceAdapter;
       
    47 import java.awt.dnd.DragSourceDropEvent;
       
    48 import java.awt.dnd.DragSourceListener;
       
    49 import java.awt.dnd.DropTarget;
       
    50 import java.awt.dnd.DropTargetAdapter;
       
    51 import java.awt.dnd.DropTargetDropEvent;
       
    52 import java.awt.event.InputEvent;
       
    53 import java.awt.image.BufferedImage;
       
    54 import java.awt.image.MemoryImageSource;
       
    55 import java.util.stream.Stream;
       
    56 
       
    57 public class ImageTransferTest {
       
    58     public static void main(String[] arg) throws Exception {
       
    59         ImageDragSource ids = new ImageDragSource();
       
    60         ids.frame.setLocation(100, 100);
       
    61         ids.frame.setVisible(true);
       
    62         Util.sync();
       
    63         String classpath = System.getProperty("java.class.path");
       
    64         String[] args = new String[ids.formats.length + 4];
       
    65         args[0] = "200";
       
    66         args[1] = "100";
       
    67         args[2] = args[3] = "150";
       
    68 
       
    69         System.arraycopy(ids.formats, 0, args, 4, ids.formats.length);
       
    70         ProcessResults pres = ProcessCommunicator.executeChildProcess(ImageDropTarget.class, classpath, args);
       
    71 
       
    72         if (pres.getStdErr() != null && pres.getStdErr().length() > 0) {
       
    73             System.err.println("========= Child VM System.err ========");
       
    74             System.err.print(pres.getStdErr());
       
    75             System.err.println("======================================");
       
    76         }
       
    77 
       
    78         if (pres.getStdOut() != null && pres.getStdOut().length() > 0) {
       
    79             System.err.println("========= Child VM System.out ========");
       
    80             System.err.print(pres.getStdOut());
       
    81             System.err.println("======================================");
       
    82         }
       
    83 
       
    84         boolean failed = false;
       
    85         String passedFormats = "";
       
    86         String failedFormats = "";
       
    87 
       
    88         for (int i = 0; i < ids.passedArray.length; i++) {
       
    89             if (ids.passedArray[i]) passedFormats += ids.formats[i] + " ";
       
    90             else {
       
    91                 failed = true;
       
    92                 failedFormats += ids.formats[i] + " ";
       
    93             }
       
    94         }
       
    95 
       
    96         if (failed) {
       
    97             throw new RuntimeException("test failed: images in following " +
       
    98                     "native formats are not transferred properly: " + failedFormats);
       
    99         } else {
       
   100             System.err.println("images in following " +
       
   101                     "native formats are transferred properly: " + passedFormats);
       
   102         }
       
   103     }
       
   104 }
       
   105 
       
   106 
       
   107 class Util {
       
   108     public static void sync() {
       
   109         ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
       
   110         try {
       
   111             Thread.sleep(500);
       
   112         } catch (InterruptedException e) {
       
   113             throw new RuntimeException(e);
       
   114         }
       
   115     }
       
   116 }
       
   117 
       
   118 abstract class ImageTransferer {
       
   119     Image image;
       
   120     String[] formats;
       
   121     int fi; // current format index
       
   122     Frame frame = new Frame();
       
   123 
       
   124 
       
   125     ImageTransferer() {
       
   126         image = createImage();
       
   127         frame.setSize(100, 100);
       
   128     }
       
   129 
       
   130     private static Image createImage() {
       
   131         int w = 100;
       
   132         int h = 100;
       
   133         int[] pix = new int[w * h];
       
   134 
       
   135         int index = 0;
       
   136         for (int y = 0; y < h; y++) {
       
   137             for (int x = 0; x < w; x++) {
       
   138                 int red = 127;
       
   139                 int green = 127;
       
   140                 int blue = y > h / 2 ? 127 : 0;
       
   141                 int alpha = 255;
       
   142                 if (x < w / 4 && y < h / 4) {
       
   143                     alpha = 0;
       
   144                     red = 0;
       
   145                 }
       
   146                 pix[index++] = (alpha << 24) | (red << 16) | (green << 8) | blue;
       
   147             }
       
   148         }
       
   149         return Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(w, h, pix, 0, w));
       
   150     }
       
   151 
       
   152 
       
   153     static String[] retrieveFormatsToTest() {
       
   154         SystemFlavorMap sfm = (SystemFlavorMap) SystemFlavorMap.getDefaultFlavorMap();
       
   155         java.util.List<String> ln = sfm.getNativesForFlavor(DataFlavor.imageFlavor);
       
   156         if (OSInfo.OSType.WINDOWS.equals(OSInfo.getOSType()) && !ln.contains("METAFILEPICT")) {
       
   157             // for test failing on JDK without this fix
       
   158             ln.add("METAFILEPICT");
       
   159         }
       
   160         return ln.toArray(new String[ln.size()]);
       
   161     }
       
   162 
       
   163     static void leaveFormat(String format) {
       
   164         SystemFlavorMap sfm = (SystemFlavorMap) SystemFlavorMap.getDefaultFlavorMap();
       
   165         sfm.setFlavorsForNative(format, new DataFlavor[]{DataFlavor.imageFlavor});
       
   166         sfm.setNativesForFlavor(DataFlavor.imageFlavor, new String[]{format});
       
   167     }
       
   168 
       
   169 
       
   170     boolean areImagesIdentical(Image im1, Image im2) {
       
   171         if (formats[fi].equals("JFIF") || formats[fi].equals("image/jpeg") ||
       
   172                 formats[fi].equals("GIF") || formats[fi].equals("image/gif")) {
       
   173             // JFIF and GIF are lossy formats
       
   174             return true;
       
   175         }
       
   176         int[] ib1 = getImageData(im1);
       
   177         int[] ib2 = getImageData(im2);
       
   178 
       
   179         if (ib1.length != ib2.length) {
       
   180             return false;
       
   181         }
       
   182 
       
   183         if (formats[fi].equals("PNG") ||
       
   184                 formats[fi].equals("image/png") ||
       
   185                 formats[fi].equals("image/x-png")) {
       
   186             // check alpha as well
       
   187             for (int i = 0; i < ib1.length; i++) {
       
   188                 if (ib1[i] != ib2[i]) {
       
   189                     System.err.println("different pixels: " +
       
   190                             Integer.toHexString(ib1[i]) + " " +
       
   191                             Integer.toHexString(ib2[i]));
       
   192                     return false;
       
   193                 }
       
   194             }
       
   195         } else {
       
   196             for (int i = 0; i < ib1.length; i++) {
       
   197                 if ((ib1[i] & 0x00FFFFFF) != (ib2[i] & 0x00FFFFFF)) {
       
   198                     System.err.println("different pixels: " +
       
   199                             Integer.toHexString(ib1[i]) + " " +
       
   200                             Integer.toHexString(ib2[i]));
       
   201                     return false;
       
   202                 }
       
   203             }
       
   204         }
       
   205         return true;
       
   206     }
       
   207 
       
   208     private static int[] getImageData(Image image) {
       
   209         int width = image.getWidth(null);
       
   210         int height = image.getHeight(null);
       
   211         BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
       
   212         Graphics2D g2d = bimage.createGraphics();
       
   213         try {
       
   214             g2d.drawImage(image, 0, 0, width, height, null);
       
   215         } finally {
       
   216             g2d.dispose();
       
   217         }
       
   218         return bimage.getRGB(0, 0, width, height, null, 0, width);
       
   219     }
       
   220 
       
   221     public static int sign(int n) {
       
   222         return n < 0 ? -1 : n == 0 ? 0 : 1;
       
   223     }
       
   224 
       
   225 }
       
   226 
       
   227 
       
   228 class ImageDragSource extends ImageTransferer {
       
   229     boolean[] passedArray;
       
   230 
       
   231     ImageDragSource() {
       
   232         formats = retrieveFormatsToTest();
       
   233         passedArray = new boolean[formats.length];
       
   234         final DragSourceListener dsl = new DragSourceAdapter() {
       
   235             public void dragDropEnd(DragSourceDropEvent e) {
       
   236                 System.err.println("Drop was successful=" + e.getDropSuccess());
       
   237                 notifyTransferSuccess(e.getDropSuccess());
       
   238                 if (++fi < formats.length) {
       
   239                     leaveFormat(formats[fi]);
       
   240                 }
       
   241             }
       
   242         };
       
   243 
       
   244         new DragSource().createDefaultDragGestureRecognizer(frame,
       
   245                 DnDConstants.ACTION_COPY,
       
   246                 dge -> dge.startDrag(null, new ImageSelection(image), dsl));
       
   247         leaveFormat(formats[fi]);
       
   248     }
       
   249 
       
   250 
       
   251     void notifyTransferSuccess(boolean status) {
       
   252         passedArray[fi] = status;
       
   253     }
       
   254 }
       
   255 
       
   256 
       
   257 class ImageDropTarget extends ImageTransferer {
       
   258     private final Robot robot;
       
   259     private static Point startPoint, endPoint = new Point(250, 150);
       
   260 
       
   261     ImageDropTarget() throws AWTException {
       
   262         DropTargetAdapter dropTargetAdapter = new DropTargetAdapter() {
       
   263             @Override
       
   264             public void drop(DropTargetDropEvent dtde) {
       
   265                 checkImage(dtde);
       
   266                 startImageDrag();
       
   267             }
       
   268         };
       
   269         new DropTarget(frame, dropTargetAdapter);
       
   270         robot = new Robot();
       
   271     }
       
   272 
       
   273 
       
   274     void checkImage(DropTargetDropEvent dtde) {
       
   275         final Transferable t = dtde.getTransferable();
       
   276         if (t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
       
   277             dtde.acceptDrop(DnDConstants.ACTION_COPY);
       
   278             Image im;
       
   279             try {
       
   280                 im = (Image) t.getTransferData(DataFlavor.imageFlavor);
       
   281                 System.err.println("getTransferData was successful");
       
   282             } catch (Exception e) {
       
   283                 System.err.println("Can't getTransferData: " + e);
       
   284                 dtde.dropComplete(false);
       
   285                 notifyTransferSuccess(false);
       
   286                 return;
       
   287             }
       
   288 
       
   289             if (im == null) {
       
   290                 System.err.println("getTransferData returned null");
       
   291                 dtde.dropComplete(false);
       
   292                 notifyTransferSuccess(false);
       
   293             } else if (areImagesIdentical(image, im)) {
       
   294                 dtde.dropComplete(true);
       
   295                 notifyTransferSuccess(true);
       
   296             } else {
       
   297                 System.err.println("transferred image is different from initial image");
       
   298                 dtde.dropComplete(false);
       
   299                 notifyTransferSuccess(false);
       
   300             }
       
   301 
       
   302         } else {
       
   303             System.err.println("imageFlavor is not supported by Transferable");
       
   304             dtde.rejectDrop();
       
   305             notifyTransferSuccess(false);
       
   306         }
       
   307     }
       
   308 
       
   309     void startImageDrag() {
       
   310         leaveFormat(formats[fi]);
       
   311         new Thread(() -> {
       
   312             try {
       
   313                 Thread.sleep(1000);
       
   314             } catch (InterruptedException e) {
       
   315                 e.printStackTrace();
       
   316                 // Exit from the child process
       
   317                 System.exit(1);
       
   318             }
       
   319             robot.mouseMove(startPoint.x, startPoint.y);
       
   320             robot.mousePress(InputEvent.BUTTON1_MASK);
       
   321             for (Point p = new Point(startPoint); !p.equals(endPoint);
       
   322                  p.translate(sign(endPoint.x - p.x), sign(endPoint.y - p.y))) {
       
   323                 robot.mouseMove(p.x, p.y);
       
   324                 try {
       
   325                     Thread.sleep(50);
       
   326                 } catch (InterruptedException e) {
       
   327                     e.printStackTrace();
       
   328                 }
       
   329             }
       
   330 
       
   331             robot.mouseRelease(InputEvent.BUTTON1_MASK);
       
   332         }).start();
       
   333     }
       
   334 
       
   335     void notifyTransferSuccess(boolean status) {
       
   336         if (status) {
       
   337             System.err.println("format passed: " + formats[fi]);
       
   338         } else {
       
   339             System.err.println("format failed: " + formats[fi]);
       
   340             System.exit(1);
       
   341         }
       
   342         if (fi < formats.length - 1) {
       
   343             leaveFormat(formats[++fi]);
       
   344         } else {
       
   345             new Thread(() -> {
       
   346                 try {
       
   347                     Thread.sleep(500);
       
   348                 } catch (InterruptedException e) {
       
   349                     e.printStackTrace();
       
   350                 }
       
   351                 System.exit(0);
       
   352             }).start();
       
   353         }
       
   354     }
       
   355 
       
   356 
       
   357     public static void main(String[] args) {
       
   358         try {
       
   359             ImageDropTarget idt = new ImageDropTarget();
       
   360 
       
   361             int x = Integer.parseInt(args[0]);
       
   362             int y = Integer.parseInt(args[1]);
       
   363             startPoint = new Point(Integer.parseInt(args[2]), Integer.parseInt(args[3]));
       
   364 
       
   365             idt.formats = new String[args.length - 4];
       
   366             System.arraycopy(args, 4, idt.formats, 0, args.length - 4);
       
   367             leaveFormat(idt.formats[0]);
       
   368 
       
   369             idt.frame.setLocation(x, y);
       
   370             idt.frame.setVisible(true);
       
   371             Util.sync();
       
   372 
       
   373             idt.startImageDrag();
       
   374         } catch (Throwable e) {
       
   375             e.printStackTrace();
       
   376             System.exit(1);
       
   377         }
       
   378     }
       
   379 
       
   380 }
       
   381 
       
   382 
       
   383 class ImageSelection implements Transferable {
       
   384     private static final int IMAGE = 0;
       
   385     private static final DataFlavor[] flavors = {DataFlavor.imageFlavor};
       
   386     private Image data;
       
   387 
       
   388     public ImageSelection(Image data) {
       
   389         this.data = data;
       
   390     }
       
   391 
       
   392     @Override
       
   393     public DataFlavor[] getTransferDataFlavors() {
       
   394         // returning flavors itself would allow client code to modify
       
   395         // our internal behavior
       
   396         return flavors.clone();
       
   397     }
       
   398 
       
   399     @Override
       
   400     public boolean isDataFlavorSupported(DataFlavor flavor) {
       
   401         return Stream.of(flavor).anyMatch(flavor::equals);
       
   402     }
       
   403 
       
   404     @Override
       
   405     public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
       
   406         if (flavor.equals(flavors[IMAGE])) {
       
   407             return data;
       
   408         } else {
       
   409             throw new UnsupportedFlavorException(flavor);
       
   410         }
       
   411     }
       
   412 }