-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
8
-
x86_64
-
linux
ADDITIONAL SYSTEM INFORMATION :
OS: uos, a chinese linux.
CPU:Kirin, a chinese cpu(arm64/aarch64)
A DESCRIPTION OF THE PROBLEM :
We use Robot to capture srceen, and blocked.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1, Running the test code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Can move mouse
ACTUAL -
Can't move mouse.
---------- BEGIN SOURCE ----------
public class ScreenShot extends JFrame
{
private static Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
public ScreenShot()
{
Rectangle rectangle = new Rectangle(dimension.width, dimension.height);
try
{
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(rectangle);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
ScreenShot ss = new ScreenShot();
ss.setSize(dimension.width, dimension.height);
ss.setVisible(true);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
awt_Robot.c
#ifdef HEADLESS
#error This file should not be included in headless library
#endif
#include "jvm_md.h"
#include <dlfcn.h>
#include "awt_p.h"
#include "awt_GraphicsEnv.h"
#define XK_MISCELLANY
#include <X11/keysymdef.h>
#include <X11/Intrinsic.h>
#include <X11/Xutil.h>
#include <X11/Xmd.h>
#include <X11/extensions/xtestext1.h>
#include <X11/extensions/XTest.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XI.h>
#include <jni.h>
#include <sizecalc.h>
#include "canvas.h"
#include "wsutils.h"
#include "list.h"
#include "multiVis.h"
#include "java_awt_event_InputEvent.h"
#if defined(__linux__) || defined(MACOSX)
#include <sys/socket.h>
#endif
static Bool (*compositeQueryExtension) (Display*, int*, int*);
static Status (*compositeQueryVersion) (Display*, int*, int*);
static Window (*compositeGetOverlayWindow) (Display*, Window);
static Window (*compositeReleaseOverlayWindow) (Display*, Window);
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
static jint * masks;
static jint num_buttons;
static void *xCompositeHandle;
static const char* XCOMPOSITE = JNI_LIB_NAME("Xcomposite");
static const char* XCOMPOSITE_VERSIONED = VERSIONED_JNI_LIB_NAME("Xcomposite", "1");
static Bool checkXCompositeFunctions(void) {
return (compositeQueryExtension != NULL &&
compositeQueryVersion != NULL &&
compositeGetOverlayWindow != NULL);
}
static void initXCompositeFunctions(void) {
if (xCompositeHandle == NULL) {
xCompositeHandle = dlopen(XCOMPOSITE, RTLD_LAZY | RTLD_GLOBAL);
if (xCompositeHandle == NULL) {
xCompositeHandle = dlopen(XCOMPOSITE_VERSIONED, RTLD_LAZY | RTLD_GLOBAL);
}
}
//*(void **)(&asyncGetCallTraceFunction)
if (xCompositeHandle != NULL) {
*(void **)(&compositeQueryExtension) = dlsym(xCompositeHandle, "XCompositeQueryExtension");
*(void **)(&compositeQueryVersion) = dlsym(xCompositeHandle, "XCompositeQueryVersion");
*(void **)(&compositeGetOverlayWindow) = dlsym(xCompositeHandle, "XCompositeGetOverlayWindow");
*(void **)(&compositeReleaseOverlayWindow) = dlsym(xCompositeHandle, "XCompositeReleaseOverlayWindow");
}
if (xCompositeHandle && !checkXCompositeFunctions()) {
dlclose(xCompositeHandle);
}
}
static int32_t isXTestAvailable() {
int32_t major_opcode, first_event, first_error;
int32_t event_basep, error_basep, majorp, minorp;
int32_t isXTestAvailable;
/* check if XTest is available */
isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
if (isXTestAvailable) {
DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
major_opcode, first_event, first_error);
/* check if XTest version is OK */
XTestQueryExtension(awt_display, &event_basep, &error_basep, &majorp, &minorp);
DTRACE_PRINTLN4("RobotPeer: XTestQueryExtension returns event_basep = %d, error_basep = %d, majorp = %d, minorp = %d",
event_basep, error_basep, majorp, minorp);
if (majorp < 2 || (majorp == 2 && minorp < 2)) {
/* bad version*/
DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
if (majorp == 2 && minorp == 1) {
DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
} else {
isXTestAvailable = False;
}
} else {
/* allow XTest calls even if someone else has the grab; e.g. during
* a window resize operation. Works only with XTEST2.2*/
XTestGrabControl(awt_display, True);
}
} else {
DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
}
return isXTestAvailable;
}
static Bool hasXCompositeOverlayExtension(Display *display) {
int xoverlay = False;
int eventBase, errorBase;
if (checkXCompositeFunctions() &&
compositeQueryExtension(display, &eventBase, &errorBase))
{
int major = 0;
int minor = 0;
compositeQueryVersion(display, &major, &minor);
if (major > 0 || minor >= 3) {
xoverlay = True;
}
}
return xoverlay;
}
static jboolean isXCompositeDisplay(Display *display, int screenNumber) {
char NET_WM_CM_Sn[25];
snprintf(NET_WM_CM_Sn, sizeof(NET_WM_CM_Sn), "_NET_WM_CM_S%d\0", screenNumber);
Atom managerSelection = XInternAtom(display, NET_WM_CM_Sn, 0);
Window owner = XGetSelectionOwner(display, managerSelection);
return owner != 0;
}
static XImage *getWindowImage(Display * display, Window window,
int32_t x, int32_t y,
int32_t w, int32_t h) {
XImage *image;
int32_t transparentOverlays;
int32_t numVisuals;
XVisualInfo *pVisuals;
int32_t numOverlayVisuals;
OverlayInfo *pOverlayVisuals;
int32_t numImageVisuals;
XVisualInfo **pImageVisuals;
list_ptr vis_regions; /* list of regions to read from */
list_ptr vis_image_regions ;
int32_t allImage = 0 ;
int32_t format = ZPixmap;
/* prevent user from moving stuff around during the capture */
XGrabServer(display);
/*
* The following two functions live in multiVis.c-- they are pretty
* much verbatim taken from the source to the xwd utility from the
* X11 source. This version of the xwd source was somewhat better written
* for reuse compared to Sun's version.
*
* ftp.x.org/pub/R6.3/xc/programs/xwd
*
* We use these functions since they do the very tough job of capturing
* the screen correctly when it contains multiple visuals. They take into
* account the depth/colormap of each visual and produce a capture as a
* 24-bit RGB image so we don't have to fool around with colormaps etc.
*/
GetMultiVisualRegions(
display,
window,
x, y, w, h,
&transparentOverlays,
&numVisuals,
&pVisuals,
&numOverlayVisuals,
&pOverlayVisuals,
&numImageVisuals,
&pImageVisuals,
&vis_regions,
&vis_image_regions,
&allImage );
image = ReadAreaToImage(
display,
window,
x, y, w, h,
numVisuals,
pVisuals,
numOverlayVisuals,
pOverlayVisuals,
numImageVisuals,
pImageVisuals,
vis_regions,
vis_image_regions,
format,
allImage );
/* allow user to do stuff again */
XUngrabServer(display);
/* make sure the grab/ungrab is flushed */
XSync(display, False);
return image;
}
/*********************************************************************************************/
// this should be called from XRobotPeer constructor
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButtons, jintArray buttonDownMasks)
{
int32_t xtestAvailable;
jint *tmp;
int i;
DTRACE_PRINTLN("RobotPeer: setup()");
num_buttons = numberOfButtons;
tmp = (*env)->GetIntArrayElements(env, buttonDownMasks, JNI_FALSE);
CHECK_NULL(tmp);
masks = (jint *)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), num_buttons);
if (masks == (jint *) NULL) {
(*env)->ExceptionClear(env);
(*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL);
return;
}
for (i = 0; i < num_buttons; i++) {
masks[i] = tmp[i];
}
(*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
AWT_LOCK();
xtestAvailable = isXTestAvailable();
DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
if (!xtestAvailable) {
JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
}
AWT_UNLOCK();
}
JNIEXPORT int JNICALL
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
jclass cls,
jobject xgc,
jint x,
jint y,
jint width,
jint height,
jintArray pixelArray) {
XImage *image;
jint *ary; /* Array of jints for sending pixel values back
* to parent process.
*/
Window rootWindow;
AwtGraphicsConfigDataPtr adata;
int compositeFlag = 0;
DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray);
AWT_LOCK();
/* avoid a lot of work for empty rectangles */
if ((width * height) == 0) {
AWT_UNLOCK();
return;
}
DASSERT(width * height > 0); /* only allow positive size */
adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
DASSERT(adata != NULL);
rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
if (hasXCompositeOverlayExtension(awt_display) &&
isXCompositeDisplay(awt_display, adata->awt_visInfo.screen))
{
compositeFlag = 1;
rootWindow = compositeGetOverlayWindow(awt_display, rootWindow);
}
image = getWindowImage(awt_display, rootWindow, x, y, width, height);
if (image == NULL)
{
if (compositeFlag)
{
compositeReleaseOverlayWindow(awt_display, rootWindow);
}
AWT_UNLOCK();
return 0;
}
/* 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 (compositeFlag)
{
compositeReleaseOverlayWindow(awt_display, rootWindow);
}
AWT_UNLOCK();
return 0;
}
/* 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 */
ary[(y * width) + x] = pixel;
}
}
(*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
free(ary);
XDestroyImage(image);
if (compositeFlag)
{
compositeReleaseOverlayWindow(awt_display, rootWindow);
}
AWT_UNLOCK();
return (height * width);
}
OS: uos, a chinese linux.
CPU:Kirin, a chinese cpu(arm64/aarch64)
A DESCRIPTION OF THE PROBLEM :
We use Robot to capture srceen, and blocked.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1, Running the test code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Can move mouse
ACTUAL -
Can't move mouse.
---------- BEGIN SOURCE ----------
public class ScreenShot extends JFrame
{
private static Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
public ScreenShot()
{
Rectangle rectangle = new Rectangle(dimension.width, dimension.height);
try
{
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(rectangle);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
ScreenShot ss = new ScreenShot();
ss.setSize(dimension.width, dimension.height);
ss.setVisible(true);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
awt_Robot.c
#ifdef HEADLESS
#error This file should not be included in headless library
#endif
#include "jvm_md.h"
#include <dlfcn.h>
#include "awt_p.h"
#include "awt_GraphicsEnv.h"
#define XK_MISCELLANY
#include <X11/keysymdef.h>
#include <X11/Intrinsic.h>
#include <X11/Xutil.h>
#include <X11/Xmd.h>
#include <X11/extensions/xtestext1.h>
#include <X11/extensions/XTest.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XI.h>
#include <jni.h>
#include <sizecalc.h>
#include "canvas.h"
#include "wsutils.h"
#include "list.h"
#include "multiVis.h"
#include "java_awt_event_InputEvent.h"
#if defined(__linux__) || defined(MACOSX)
#include <sys/socket.h>
#endif
static Bool (*compositeQueryExtension) (Display*, int*, int*);
static Status (*compositeQueryVersion) (Display*, int*, int*);
static Window (*compositeGetOverlayWindow) (Display*, Window);
static Window (*compositeReleaseOverlayWindow) (Display*, Window);
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
static jint * masks;
static jint num_buttons;
static void *xCompositeHandle;
static const char* XCOMPOSITE = JNI_LIB_NAME("Xcomposite");
static const char* XCOMPOSITE_VERSIONED = VERSIONED_JNI_LIB_NAME("Xcomposite", "1");
static Bool checkXCompositeFunctions(void) {
return (compositeQueryExtension != NULL &&
compositeQueryVersion != NULL &&
compositeGetOverlayWindow != NULL);
}
static void initXCompositeFunctions(void) {
if (xCompositeHandle == NULL) {
xCompositeHandle = dlopen(XCOMPOSITE, RTLD_LAZY | RTLD_GLOBAL);
if (xCompositeHandle == NULL) {
xCompositeHandle = dlopen(XCOMPOSITE_VERSIONED, RTLD_LAZY | RTLD_GLOBAL);
}
}
//*(void **)(&asyncGetCallTraceFunction)
if (xCompositeHandle != NULL) {
*(void **)(&compositeQueryExtension) = dlsym(xCompositeHandle, "XCompositeQueryExtension");
*(void **)(&compositeQueryVersion) = dlsym(xCompositeHandle, "XCompositeQueryVersion");
*(void **)(&compositeGetOverlayWindow) = dlsym(xCompositeHandle, "XCompositeGetOverlayWindow");
*(void **)(&compositeReleaseOverlayWindow) = dlsym(xCompositeHandle, "XCompositeReleaseOverlayWindow");
}
if (xCompositeHandle && !checkXCompositeFunctions()) {
dlclose(xCompositeHandle);
}
}
static int32_t isXTestAvailable() {
int32_t major_opcode, first_event, first_error;
int32_t event_basep, error_basep, majorp, minorp;
int32_t isXTestAvailable;
/* check if XTest is available */
isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
if (isXTestAvailable) {
DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
major_opcode, first_event, first_error);
/* check if XTest version is OK */
XTestQueryExtension(awt_display, &event_basep, &error_basep, &majorp, &minorp);
DTRACE_PRINTLN4("RobotPeer: XTestQueryExtension returns event_basep = %d, error_basep = %d, majorp = %d, minorp = %d",
event_basep, error_basep, majorp, minorp);
if (majorp < 2 || (majorp == 2 && minorp < 2)) {
/* bad version*/
DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
if (majorp == 2 && minorp == 1) {
DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
} else {
isXTestAvailable = False;
}
} else {
/* allow XTest calls even if someone else has the grab; e.g. during
* a window resize operation. Works only with XTEST2.2*/
XTestGrabControl(awt_display, True);
}
} else {
DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
}
return isXTestAvailable;
}
static Bool hasXCompositeOverlayExtension(Display *display) {
int xoverlay = False;
int eventBase, errorBase;
if (checkXCompositeFunctions() &&
compositeQueryExtension(display, &eventBase, &errorBase))
{
int major = 0;
int minor = 0;
compositeQueryVersion(display, &major, &minor);
if (major > 0 || minor >= 3) {
xoverlay = True;
}
}
return xoverlay;
}
static jboolean isXCompositeDisplay(Display *display, int screenNumber) {
char NET_WM_CM_Sn[25];
snprintf(NET_WM_CM_Sn, sizeof(NET_WM_CM_Sn), "_NET_WM_CM_S%d\0", screenNumber);
Atom managerSelection = XInternAtom(display, NET_WM_CM_Sn, 0);
Window owner = XGetSelectionOwner(display, managerSelection);
return owner != 0;
}
static XImage *getWindowImage(Display * display, Window window,
int32_t x, int32_t y,
int32_t w, int32_t h) {
XImage *image;
int32_t transparentOverlays;
int32_t numVisuals;
XVisualInfo *pVisuals;
int32_t numOverlayVisuals;
OverlayInfo *pOverlayVisuals;
int32_t numImageVisuals;
XVisualInfo **pImageVisuals;
list_ptr vis_regions; /* list of regions to read from */
list_ptr vis_image_regions ;
int32_t allImage = 0 ;
int32_t format = ZPixmap;
/* prevent user from moving stuff around during the capture */
XGrabServer(display);
/*
* The following two functions live in multiVis.c-- they are pretty
* much verbatim taken from the source to the xwd utility from the
* X11 source. This version of the xwd source was somewhat better written
* for reuse compared to Sun's version.
*
* ftp.x.org/pub/R6.3/xc/programs/xwd
*
* We use these functions since they do the very tough job of capturing
* the screen correctly when it contains multiple visuals. They take into
* account the depth/colormap of each visual and produce a capture as a
* 24-bit RGB image so we don't have to fool around with colormaps etc.
*/
GetMultiVisualRegions(
display,
window,
x, y, w, h,
&transparentOverlays,
&numVisuals,
&pVisuals,
&numOverlayVisuals,
&pOverlayVisuals,
&numImageVisuals,
&pImageVisuals,
&vis_regions,
&vis_image_regions,
&allImage );
image = ReadAreaToImage(
display,
window,
x, y, w, h,
numVisuals,
pVisuals,
numOverlayVisuals,
pOverlayVisuals,
numImageVisuals,
pImageVisuals,
vis_regions,
vis_image_regions,
format,
allImage );
/* allow user to do stuff again */
XUngrabServer(display);
/* make sure the grab/ungrab is flushed */
XSync(display, False);
return image;
}
/*********************************************************************************************/
// this should be called from XRobotPeer constructor
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButtons, jintArray buttonDownMasks)
{
int32_t xtestAvailable;
jint *tmp;
int i;
DTRACE_PRINTLN("RobotPeer: setup()");
num_buttons = numberOfButtons;
tmp = (*env)->GetIntArrayElements(env, buttonDownMasks, JNI_FALSE);
CHECK_NULL(tmp);
masks = (jint *)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), num_buttons);
if (masks == (jint *) NULL) {
(*env)->ExceptionClear(env);
(*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL);
return;
}
for (i = 0; i < num_buttons; i++) {
masks[i] = tmp[i];
}
(*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
AWT_LOCK();
xtestAvailable = isXTestAvailable();
DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
if (!xtestAvailable) {
JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
}
AWT_UNLOCK();
}
JNIEXPORT int JNICALL
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
jclass cls,
jobject xgc,
jint x,
jint y,
jint width,
jint height,
jintArray pixelArray) {
XImage *image;
jint *ary; /* Array of jints for sending pixel values back
* to parent process.
*/
Window rootWindow;
AwtGraphicsConfigDataPtr adata;
int compositeFlag = 0;
DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray);
AWT_LOCK();
/* avoid a lot of work for empty rectangles */
if ((width * height) == 0) {
AWT_UNLOCK();
return;
}
DASSERT(width * height > 0); /* only allow positive size */
adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
DASSERT(adata != NULL);
rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
if (hasXCompositeOverlayExtension(awt_display) &&
isXCompositeDisplay(awt_display, adata->awt_visInfo.screen))
{
compositeFlag = 1;
rootWindow = compositeGetOverlayWindow(awt_display, rootWindow);
}
image = getWindowImage(awt_display, rootWindow, x, y, width, height);
if (image == NULL)
{
if (compositeFlag)
{
compositeReleaseOverlayWindow(awt_display, rootWindow);
}
AWT_UNLOCK();
return 0;
}
/* 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 (compositeFlag)
{
compositeReleaseOverlayWindow(awt_display, rootWindow);
}
AWT_UNLOCK();
return 0;
}
/* 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 */
ary[(y * width) + x] = pixel;
}
}
(*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
free(ary);
XDestroyImage(image);
if (compositeFlag)
{
compositeReleaseOverlayWindow(awt_display, rootWindow);
}
AWT_UNLOCK();
return (height * width);
}
- duplicates
-
JDK-8269245 [wayland] java.awt.Robot.createScreenCapture(r) produces black image
- Closed