Mercurial > hg > jdk9-shenandoah > jdk
changeset 12630:46894b1937af
8014212: Robot captures black screen
Reviewed-by: alexsch, serb
author | azvegint |
---|---|
date | Tue, 11 Aug 2015 16:32:13 +0300 |
parents | f45d4e52e7e2 |
children | 09b17ef4ac24 |
files | src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h test/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java test/javax/swing/JComponent/6683775/bug6683775.java |
diffstat | 7 files changed, 179 insertions(+), 83 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java Mon Aug 10 14:42:07 2015 +0200 +++ b/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java Tue Aug 11 16:32:13 2015 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,15 +25,16 @@ package sun.awt.X11; import java.awt.*; -import java.awt.event.InputEvent; import java.awt.peer.*; import sun.awt.AWTAccessor; import sun.awt.SunToolkit; +import sun.awt.UNIXToolkit; import sun.awt.X11GraphicsConfig; class XRobotPeer implements RobotPeer { + private static volatile boolean isGtkSupported; private X11GraphicsConfig xgc = null; /* * native implementation uses some static shared data (pipes, processes) @@ -44,46 +45,65 @@ XRobotPeer(GraphicsConfiguration gc) { this.xgc = (X11GraphicsConfig)gc; SunToolkit tk = (SunToolkit)Toolkit.getDefaultToolkit(); - setup(tk.getNumberOfButtons(), AWTAccessor.getInputEventAccessor().getButtonDownMasks()); + setup(tk.getNumberOfButtons(), + AWTAccessor.getInputEventAccessor().getButtonDownMasks()); + + Toolkit toolkit = Toolkit.getDefaultToolkit(); + if (!isGtkSupported) { + if (toolkit instanceof UNIXToolkit + && ((UNIXToolkit) toolkit).loadGTK()) { + isGtkSupported = true; + } + } } + @Override public void dispose() { // does nothing } + @Override public void mouseMove(int x, int y) { mouseMoveImpl(xgc, x, y); } + @Override public void mousePress(int buttons) { mousePressImpl(buttons); } + @Override public void mouseRelease(int buttons) { mouseReleaseImpl(buttons); } + @Override public void mouseWheel(int wheelAmt) { - mouseWheelImpl(wheelAmt); + mouseWheelImpl(wheelAmt); } + @Override public void keyPress(int keycode) { keyPressImpl(keycode); } + @Override public void keyRelease(int keycode) { keyReleaseImpl(keycode); } + @Override public int getRGBPixel(int x, int y) { int pixelArray[] = new int[1]; - getRGBPixelsImpl(xgc, x, y, 1, 1, pixelArray); + getRGBPixelsImpl(xgc, x, y, 1, 1, pixelArray, isGtkSupported); return pixelArray[0]; } + @Override public int [] getRGBPixels(Rectangle bounds) { int pixelArray[] = new int[bounds.width*bounds.height]; - getRGBPixelsImpl(xgc, bounds.x, bounds.y, bounds.width, bounds.height, pixelArray); + getRGBPixelsImpl(xgc, bounds.x, bounds.y, bounds.width, bounds.height, + pixelArray, isGtkSupported); return pixelArray; } @@ -97,5 +117,6 @@ private static native synchronized void keyPressImpl(int keycode); private static native synchronized void keyReleaseImpl(int keycode); - private static native synchronized void getRGBPixelsImpl(X11GraphicsConfig xgc, int x, int y, int width, int height, int pixelArray[]); + private static native synchronized void getRGBPixelsImpl(X11GraphicsConfig xgc, + int x, int y, int width, int height, int pixelArray[], boolean isGtkSupported); }
--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c Mon Aug 10 14:42:07 2015 +0200 +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c Tue Aug 11 16:32:13 2015 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -45,6 +45,8 @@ #include "wsutils.h" #include "list.h" #include "multiVis.h" +#include "gtk2_interface.h" + #if defined(__linux__) || defined(MACOSX) #include <sys/socket.h> #endif @@ -204,63 +206,135 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, jclass cls, jobject xgc, - jint x, - jint y, - jint width, - jint height, - jintArray pixelArray) { - + jint jx, + jint jy, + jint jwidth, + jint jheight, + jintArray pixelArray, + jboolean isGtkSupported) { XImage *image; jint *ary; /* Array of jints for sending pixel values back * to parent process. */ Window rootWindow; + XWindowAttributes attr; AwtGraphicsConfigDataPtr adata; - DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray); - - AWT_LOCK(); + DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, jx, jy, jwidth, jheight, pixelArray); - /* avoid a lot of work for empty rectangles */ - if ((width * height) == 0) { - AWT_UNLOCK(); + if (jwidth <= 0 || jheight <= 0) { return; } - DASSERT(width * height > 0); /* only allow positive size */ adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData); DASSERT(adata != NULL); + AWT_LOCK(); + rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen); - image = getWindowImage(awt_display, rootWindow, x, y, width, height); - /* Array to use to crunch around the pixel values */ - if (!IS_SAFE_SIZE_MUL(width, height) || - !(ary = (jint *) SAFE_SIZE_ARRAY_ALLOC(malloc, width * height, sizeof (jint)))) - { - JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); - XDestroyImage(image); + if (!XGetWindowAttributes(awt_display, rootWindow, &attr) + || jx + jwidth <= attr.x + || attr.x + attr.width <= jx + || jy + jheight <= attr.y + || attr.y + attr.height <= jy) { + AWT_UNLOCK(); - return; + return; // Does not intersect with root window } - /* convert to Java ARGB pixels */ - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - jint pixel = (jint) XGetPixel(image, x, y); /* Note ignore upper - * 32-bits on 64-bit - * OSes. - */ + + gboolean gtk_failed = TRUE; + jint _x, _y; + + jint x = MAX(jx, attr.x); + jint y = MAX(jy, attr.y); + jint width = MIN(jx + jwidth, attr.x + attr.width) - x; + jint height = MIN(jy + jheight, attr.y + attr.height) - y; + + + int dx = attr.x > jx ? attr.x - jx : 0; + int dy = attr.y > jy ? attr.y - jy : 0; + + int index; + + if (isGtkSupported) { + GdkPixbuf *pixbuf; + GdkWindow *root = (*fp_gdk_get_default_root_window)(); + + pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, + x, y, 0, 0, width, height); + + if (pixbuf) { + int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); + int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - pixel |= 0xff000000; /* alpha - full opacity */ + if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width + && (*fp_gdk_pixbuf_get_height)(pixbuf) == height + && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 + && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB + && nchan >= 3 + ) { + guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); + + ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); + if (!ary) { + (*fp_g_object_unref)(pixbuf); + AWT_UNLOCK(); + return; + } - ary[(y * width) + x] = pixel; + for (_y = 0; _y < height; _y++) { + for (_x = 0; _x < width; _x++) { + p = pix + _y * stride + _x * nchan; + + index = (_y + dy) * jwidth + (_x + dx); + ary[index] = 0xff000000 + | (p[0] << 16) + | (p[1] << 8) + | (p[2]); + + } + } + (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); + if ((*env)->ExceptionCheck(env)) { + (*fp_g_object_unref)(pixbuf); + AWT_UNLOCK(); + return; + } + gtk_failed = FALSE; + } + (*fp_g_object_unref)(pixbuf); } } - (*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary); - free(ary); + + if (gtk_failed) { + image = getWindowImage(awt_display, rootWindow, x, y, width, height); + + ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); + + if (!ary) { + XDestroyImage(image); + AWT_UNLOCK(); + return; + } - XDestroyImage(image); + /* convert to Java ARGB pixels */ + for (_y = 0; _y < height; _y++) { + for (_x = 0; _x < width; _x++) { + jint pixel = (jint) XGetPixel(image, _x, _y); /* Note ignore upper + * 32-bits on 64-bit + * OSes. + */ + pixel |= 0xff000000; /* alpha - full opacity */ + index = (_y + dy) * jwidth + (_x + dx); + ary[index] = pixel; + } + } + + XDestroyImage(image); + (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); + } AWT_UNLOCK(); }
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Mon Aug 10 14:42:07 2015 +0200 +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Tue Aug 11 16:32:13 2015 +0300 @@ -203,9 +203,6 @@ gint, gint, gint, gint); static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height); -static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest, - GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y, - int dest_x, int dest_y, int width, int height); static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable, gint* width, gint* height); @@ -646,6 +643,8 @@ fp_g_object_set = dl_symbol("g_object_set"); /* GDK */ + fp_gdk_get_default_root_window = + dl_symbol("gdk_get_default_root_window"); fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new"); fp_gdk_pixbuf_get_from_drawable = dl_symbol("gdk_pixbuf_get_from_drawable"); @@ -670,6 +669,8 @@ dl_symbol("gdk_pixbuf_get_bits_per_sample"); fp_gdk_pixbuf_get_n_channels = dl_symbol("gdk_pixbuf_get_n_channels"); + fp_gdk_pixbuf_get_colorspace = + dl_symbol("gdk_pixbuf_get_colorspace"); /* GTK painting */ fp_gtk_init_check = dl_symbol("gtk_init_check");
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Mon Aug 10 14:42:07 2015 +0200 +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Tue Aug 11 16:32:13 2015 +0300 @@ -772,6 +772,8 @@ void (*fp_g_free)(gpointer mem); void (*fp_g_object_unref)(gpointer object); +GdkWindow *(*fp_gdk_get_default_root_window) (void); + int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); @@ -780,6 +782,13 @@ int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); +GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf); + +GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest, + GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y, + int dest_x, int dest_y, int width, int height); + + void (*fp_gtk_widget_destroy)(GtkWidget *widget); void (*fp_gtk_window_present)(GtkWindow *window); void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y);
--- a/test/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java Mon Aug 10 14:42:07 2015 +0200 +++ b/test/java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java Tue Aug 11 16:32:13 2015 +0300 @@ -46,11 +46,8 @@ private static Robot robot; public ShapeNotSetSometimes() throws Exception { - EventQueue.invokeAndWait(new Runnable() { - public void run() { - initializeGUI(); - } - }); + EventQueue.invokeAndWait(this::initializeGUI); + robot.waitForIdle(); } private void initializeGUI() { @@ -119,7 +116,7 @@ public static void main(String[] args) throws Exception { robot = new Robot(); - for(int i = 0; i < 100; i++) { + for(int i = 0; i < 50; i++) { System.out.println("Attempt " + i); new ShapeNotSetSometimes().doTest(); } @@ -134,11 +131,7 @@ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.delay(500); - EventQueue.invokeAndWait(new Runnable() { - public void run() { - window.requestFocus(); - } - }); + EventQueue.invokeAndWait(window::requestFocus); robot.waitForIdle(); try {
--- a/test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java Mon Aug 10 14:42:07 2015 +0200 +++ b/test/java/awt/Window/TranslucentJAppletTest/TranslucentJAppletTest.java Tue Aug 11 16:32:13 2015 +0300 @@ -100,12 +100,10 @@ if (!paintComponentCalled) { throw new RuntimeException("Test FAILED: panel's paintComponent() method is not called"); } + Thread.sleep(1500); Color newColor1 = r.getPixelColor(100, 100); - // unfortunately, robot.getPixelColor() doesn't work for some unknown reason - // Color newColor2 = r.getPixelColor(200, 200); - BufferedImage bim = r.createScreenCapture(new Rectangle(200, 200, 1, 1)); - Color newColor2 = new Color(bim.getRGB(0, 0)); + Color newColor2 = r.getPixelColor(200, 200); // Frame must be transparent at (100, 100) in screen coords if (!color1.equals(newColor1)) {
--- a/test/javax/swing/JComponent/6683775/bug6683775.java Mon Aug 10 14:42:07 2015 +0200 +++ b/test/javax/swing/JComponent/6683775/bug6683775.java Tue Aug 11 16:32:13 2015 +0300 @@ -31,13 +31,15 @@ */ import com.sun.awt.AWTUtilities; -import sun.awt.SunToolkit; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; public class bug6683775 { + static final int LOC = 100, + SIZE = 200; + public static void main(String[] args) throws Exception { GraphicsConfiguration gc = getGC(); if (!AWTUtilities.isTranslucencySupported( @@ -45,39 +47,37 @@ || gc == null) { return; } - SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); Robot robot = new Robot(); final JFrame testFrame = new JFrame(gc); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - JFrame backgroundFrame = new JFrame("Background frame"); - backgroundFrame.setUndecorated(true); - JPanel panel = new JPanel(); - panel.setBackground(Color.RED); - backgroundFrame.add(panel); - backgroundFrame.setSize(200, 200); - backgroundFrame.setVisible(true); + SwingUtilities.invokeAndWait(() -> { + JFrame backgroundFrame = new JFrame("Background frame"); + backgroundFrame.setUndecorated(true); + JPanel panel = new JPanel(); + panel.setBackground(Color.RED); + backgroundFrame.add(panel); + backgroundFrame.setBounds(LOC, LOC, SIZE, SIZE); + backgroundFrame.setVisible(true); - testFrame.setUndecorated(true); - JPanel p = new JPanel(); - p.setOpaque(false); - testFrame.add(p); - AWTUtilities.setWindowOpaque(testFrame, false); - testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - testFrame.setSize(400, 400); - testFrame.setLocation(0, 0); - testFrame.setVisible(true); - } + testFrame.setUndecorated(true); + JPanel p = new JPanel(); + p.setOpaque(false); + testFrame.add(p); + AWTUtilities.setWindowOpaque(testFrame, false); + testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + testFrame.setBounds(LOC, LOC, SIZE, SIZE); + testFrame.setVisible(true); }); - toolkit.realSync(); + robot.waitForIdle(); + Thread.sleep(1500); //robot.getPixelColor() didn't work right for some reason - BufferedImage capture = robot.createScreenCapture(new Rectangle(100, 100)); + BufferedImage capture = + robot.createScreenCapture(new Rectangle(LOC, LOC, SIZE, SIZE)); int redRGB = Color.RED.getRGB(); - if (redRGB != capture.getRGB(10, 10)) { + if (redRGB != capture.getRGB(SIZE/2, SIZE/2)) { throw new RuntimeException("Transparent frame is not transparent!"); } }