< prev index next >

src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c

Print this page

        

@@ -43,10 +43,11 @@
 #include "robot_common.h"
 #include "canvas.h"
 #include "wsutils.h"
 #include "list.h"
 #include "multiVis.h"
+#include "gtk2_interface.h"
 #if defined(__linux__) || defined(MACOSX)
 #include <sys/socket.h>
 #endif
 
 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;

@@ -206,34 +207,97 @@
                              jobject xgc,
                              jint x,
                              jint y,
                              jint width,
                              jint height,
-                             jintArray pixelArray) {
+                             jintArray pixelArray,
+                             jboolean isGtkSupported) {
 
     XImage *image;
+    XWindowAttributes attr;
     jint *ary;               /* Array of jints for sending pixel values back
                               * to parent process.
                               */
     Window rootWindow;
     AwtGraphicsConfigDataPtr adata;
 
     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();
+    if (width <= 0
+            || height <= 0
+            || x < 0
+            || y < 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);
+
+    if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
+            || x >= attr.width
+            || y >= attr.height
+            ) {
+        AWT_UNLOCK();
+        return;
+    }
+
+    width  = (x + width  > attr.width)  ? attr.width  - x: width;
+    height = (y + height > attr.height) ? attr.height - y: height;
+
+    gboolean gtk_failed = TRUE;
+    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
+                    ) {
+                if (!IS_SAFE_SIZE_MUL(width, height) ||
+                    !(ary = (jint *) SAFE_SIZE_ARRAY_ALLOC(malloc, width * height, sizeof (jint))))
+                {
+                    (*fp_g_object_unref)(pixbuf);
+                    JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
+                    return;
+                }
+
+                guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+                int pb_x, pb_y;
+                for (pb_y = 0; pb_y < height; pb_y++) {
+                    for (pb_x = 0; pb_x < width; pb_x++) {
+                        p = pix + pb_y * stride + pb_x * nchan;
+                        /* convert to Java ARGB pixels */
+                        ary[pb_y * width + pb_x] = 0xff000000
+                                                    | (p[0] << 16)
+                                                    | (p[1] << 8)
+                                                    | (p[2]);
+                    }
+                }
+                (*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
+                free(ary);
+                gtk_failed = FALSE;
+            }
+            (*fp_g_object_unref)(pixbuf);
+        }
+    }
+
+    if (gtk_failed) {
     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))))

@@ -258,11 +322,11 @@
     }
     (*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
     free(ary);
 
     XDestroyImage(image);
-
+    }
     AWT_UNLOCK();
 }
 
 JNIEXPORT void JNICALL
 Java_sun_awt_X11_XRobotPeer_keyPressImpl (JNIEnv *env,
< prev index next >