mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-17 10:20:33 +00:00
8014212: Robot captures black screen
Reviewed-by: alexsch, serb
This commit is contained in:
parent
f0f77d2b23
commit
23438be9c4
@ -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 @@ class XRobotPeer implements RobotPeer {
|
||||
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 @@ class XRobotPeer implements RobotPeer {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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 @@ JNIEXPORT void JNICALL
|
||||
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);
|
||||
DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, jx, jy, jwidth, jheight, pixelArray);
|
||||
|
||||
AWT_LOCK();
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
pixel |= 0xff000000; /* alpha - full opacity */
|
||||
gboolean gtk_failed = TRUE;
|
||||
jint _x, _y;
|
||||
|
||||
ary[(y * width) + x] = pixel;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
XDestroyImage(image);
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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();
|
||||
}
|
||||
|
||||
|
||||
@ -203,9 +203,6 @@ static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean,
|
||||
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 @@ gboolean gtk2_load(JNIEnv *env)
|
||||
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 @@ gboolean gtk2_load(JNIEnv *env)
|
||||
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");
|
||||
|
||||
@ -772,6 +772,8 @@ void gtk2_set_range_value(WidgetType widget_type, jdouble value,
|
||||
|
||||
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_n_channels)(const GdkPixbuf *pixbuf);
|
||||
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);
|
||||
|
||||
@ -46,11 +46,8 @@ public class ShapeNotSetSometimes {
|
||||
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 class ShapeNotSetSometimes {
|
||||
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 @@ public class ShapeNotSetSometimes {
|
||||
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 {
|
||||
|
||||
@ -100,12 +100,10 @@ public class TranslucentJAppletTest {
|
||||
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)) {
|
||||
|
||||
@ -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 @@ public class bug6683775 {
|
||||
|| 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!");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user