8150954: Taking screenshots on x11 composite desktop produce wrong result
The AWT Robot X11 code that takes screenshots uses the default root window, which may not contain the final composited desktop. Reviewed-by: alexsch, ssadetsky
This commit is contained in:
parent
653531139e
commit
c584705096
jdk
make/mapfiles/libawt_xawt
src/java.desktop/unix
@ -164,6 +164,7 @@ SUNWprivate_1.1 {
|
||||
Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl;
|
||||
Java_sun_awt_X11_XRobotPeer_mouseWheelImpl;
|
||||
Java_sun_awt_X11_XRobotPeer_setup;
|
||||
Java_sun_awt_X11_XRobotPeer_loadNativeLibraries;
|
||||
Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl;
|
||||
Java_java_awt_Component_initIDs;
|
||||
Java_java_awt_Container_initIDs;
|
||||
|
@ -35,8 +35,16 @@ import sun.awt.X11GraphicsEnvironment;
|
||||
|
||||
class XRobotPeer implements RobotPeer {
|
||||
|
||||
private static volatile boolean isGtkSupported;
|
||||
static final boolean tryGtk;
|
||||
static {
|
||||
loadNativeLibraries();
|
||||
tryGtk = Boolean.getBoolean("awt.robot.gtk");
|
||||
}
|
||||
|
||||
private static boolean isGtkSupported = false;
|
||||
private static volatile boolean useGtk;
|
||||
private X11GraphicsConfig xgc = null;
|
||||
|
||||
/*
|
||||
* native implementation uses some static shared data (pipes, processes)
|
||||
* so use a class lock to synchronize native method calls
|
||||
@ -49,13 +57,14 @@ class XRobotPeer implements RobotPeer {
|
||||
setup(tk.getNumberOfButtons(),
|
||||
AWTAccessor.getInputEventAccessor().getButtonDownMasks());
|
||||
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
if (!isGtkSupported) {
|
||||
if (toolkit instanceof UNIXToolkit
|
||||
&& ((UNIXToolkit) toolkit).loadGTK()) {
|
||||
boolean isGtkSupported = false;
|
||||
if (tryGtk) {
|
||||
if (tk instanceof UNIXToolkit && ((UNIXToolkit) tk).loadGTK()) {
|
||||
isGtkSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
useGtk = (tryGtk && isGtkSupported);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,7 +113,7 @@ class XRobotPeer implements RobotPeer {
|
||||
public int getRGBPixel(int x, int y) {
|
||||
int pixelArray[] = new int[1];
|
||||
getRGBPixelsImpl(xgc, x, y, 1, 1, xgc.getScale(), pixelArray,
|
||||
isGtkSupported);
|
||||
useGtk);
|
||||
return pixelArray[0];
|
||||
}
|
||||
|
||||
@ -112,11 +121,12 @@ class XRobotPeer implements RobotPeer {
|
||||
public int [] getRGBPixels(Rectangle bounds) {
|
||||
int pixelArray[] = new int[bounds.width*bounds.height];
|
||||
getRGBPixelsImpl(xgc, bounds.x, bounds.y, bounds.width, bounds.height,
|
||||
xgc.getScale(), pixelArray, isGtkSupported);
|
||||
xgc.getScale(), pixelArray, useGtk);
|
||||
return pixelArray;
|
||||
}
|
||||
|
||||
private static synchronized native void setup(int numberOfButtons, int[] buttonDownMasks);
|
||||
private static native void loadNativeLibraries();
|
||||
|
||||
private static synchronized native void mouseMoveImpl(X11GraphicsConfig xgc, int x, int y);
|
||||
private static synchronized native void mousePressImpl(int buttons);
|
||||
|
@ -27,6 +27,9 @@
|
||||
#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
|
||||
@ -50,11 +53,46 @@
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
static Bool (*compositeQueryExtension) (Display*, int*, int*);
|
||||
static Status (*compositeQueryVersion) (Display*, int*, int*);
|
||||
static Window (*compositeGetOverlayWindow) (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");
|
||||
}
|
||||
|
||||
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;
|
||||
@ -89,6 +127,35 @@ static int32_t isXTestAvailable() {
|
||||
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,
|
||||
@ -211,7 +278,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
|
||||
jint jheight,
|
||||
jint scale,
|
||||
jintArray pixelArray,
|
||||
jboolean isGtkSupported) {
|
||||
jboolean useGtk) {
|
||||
XImage *image;
|
||||
jint *ary; /* Array of jints for sending pixel values back
|
||||
* to parent process.
|
||||
@ -238,6 +305,14 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
|
||||
|
||||
rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
|
||||
|
||||
if (!useGtk) {
|
||||
if (hasXCompositeOverlayExtension(awt_display) &&
|
||||
isXCompositeDisplay(awt_display, adata->awt_visInfo.screen))
|
||||
{
|
||||
rootWindow = compositeGetOverlayWindow(awt_display, rootWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
|
||||
|| sx + swidth <= attr.x
|
||||
|| attr.x + attr.width <= sx
|
||||
@ -262,7 +337,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
|
||||
|
||||
int index;
|
||||
|
||||
if (isGtkSupported) {
|
||||
if (useGtk) {
|
||||
gtk->gdk_threads_enter();
|
||||
gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width,
|
||||
height, jwidth, dx, dy, scale);
|
||||
@ -454,3 +529,8 @@ Java_sun_awt_X11_XRobotPeer_mouseWheelImpl (JNIEnv *env,
|
||||
|
||||
AWT_UNLOCK();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_X11_XRobotPeer_loadNativeLibraries (JNIEnv *env, jclass cls) {
|
||||
initXCompositeFunctions();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user