21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #ifdef HEADLESS
27 #error This file should not be included in headless library
28 #endif
29
30 #include "awt_p.h"
31 #include "awt_GraphicsEnv.h"
32 #define XK_MISCELLANY
33 #include <X11/keysymdef.h>
34 #include <X11/Intrinsic.h>
35 #include <X11/Xutil.h>
36 #include <X11/Xmd.h>
37 #include <X11/extensions/xtestext1.h>
38 #include <X11/extensions/XTest.h>
39 #include <X11/extensions/XInput.h>
40 #include <X11/extensions/XI.h>
41 #include <jni.h>
42 #include <sizecalc.h>
43 #include "robot_common.h"
44 #include "canvas.h"
45 #include "wsutils.h"
46 #include "list.h"
47 #include "multiVis.h"
48 #include "gtk2_interface.h"
49
50 #if defined(__linux__) || defined(MACOSX)
51 #include <sys/socket.h>
52 #endif
53
54 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
55
56 static jint * masks;
57 static jint num_buttons;
58
59 static int32_t isXTestAvailable() {
60 int32_t major_opcode, first_event, first_error;
61 int32_t event_basep, error_basep, majorp, minorp;
62 int32_t isXTestAvailable;
63
64 /* check if XTest is available */
65 isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
66 DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
67 major_opcode, first_event, first_error);
68 if (isXTestAvailable) {
73 if (majorp < 2 || (majorp == 2 && minorp < 2)) {
74 /* bad version*/
75 DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
76 if (majorp == 2 && minorp == 1) {
77 DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
78 } else {
79 isXTestAvailable = False;
80 }
81 } else {
82 /* allow XTest calls even if someone else has the grab; e.g. during
83 * a window resize operation. Works only with XTEST2.2*/
84 XTestGrabControl(awt_display, True);
85 }
86 } else {
87 DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
88 }
89
90 return isXTestAvailable;
91 }
92
93
94 static XImage *getWindowImage(Display * display, Window window,
95 int32_t x, int32_t y,
96 int32_t w, int32_t h) {
97 XImage *image;
98 int32_t transparentOverlays;
99 int32_t numVisuals;
100 XVisualInfo *pVisuals;
101 int32_t numOverlayVisuals;
102 OverlayInfo *pOverlayVisuals;
103 int32_t numImageVisuals;
104 XVisualInfo **pImageVisuals;
105 list_ptr vis_regions; /* list of regions to read from */
106 list_ptr vis_image_regions ;
107 int32_t allImage = 0 ;
108 int32_t format = ZPixmap;
109
110 /* prevent user from moving stuff around during the capture */
111 XGrabServer(display);
112
194 AWT_LOCK();
195 xtestAvailable = isXTestAvailable();
196 DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
197 if (!xtestAvailable) {
198 JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
199 }
200
201 AWT_UNLOCK();
202 }
203
204
205 JNIEXPORT void JNICALL
206 Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
207 jclass cls,
208 jobject xgc,
209 jint jx,
210 jint jy,
211 jint jwidth,
212 jint jheight,
213 jint scale,
214 jintArray pixelArray,
215 jboolean isGtkSupported) {
216 XImage *image;
217 jint *ary; /* Array of jints for sending pixel values back
218 * to parent process.
219 */
220 Window rootWindow;
221 XWindowAttributes attr;
222 AwtGraphicsConfigDataPtr adata;
223
224 DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, jx, jy, jwidth, jheight, pixelArray);
225
226 if (jwidth <= 0 || jheight <= 0) {
227 return;
228 }
229
230 adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
231 DASSERT(adata != NULL);
232
233 AWT_LOCK();
234
235 jint sx = jx * scale;
236 jint sy = jy * scale;
237 jint swidth = jwidth * scale;
238 jint sheight = jheight * scale;
239
240 rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
241
242 if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
243 || sx + swidth <= attr.x
244 || attr.x + attr.width <= sx
245 || sy + sheight <= attr.y
246 || attr.y + attr.height <= sy) {
247
248 AWT_UNLOCK();
249 return; // Does not intersect with root window
250 }
251
252 gboolean gtk_failed = TRUE;
253 jint _x, _y;
254
255 jint x = MAX(sx, attr.x);
256 jint y = MAX(sy, attr.y);
257 jint width = MIN(sx + swidth, attr.x + attr.width) - x;
258 jint height = MIN(sy + sheight, attr.y + attr.height) - y;
259
260
261 int dx = attr.x > sx ? attr.x - sx : 0;
262 int dy = attr.y > sy ? attr.y - sy : 0;
263
264 int index;
265
266 if (isGtkSupported) {
267 GdkPixbuf *pixbuf;
268 (*fp_gdk_threads_enter)();
269 GdkWindow *root = (*fp_gdk_get_default_root_window)();
270
271 pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL,
272 x, y, 0, 0, width, height);
273 if (pixbuf && scale != 1) {
274 GdkPixbuf *scaledPixbuf;
275 x /= scale;
276 y /= scale;
277 width /= scale;
278 height /= scale;
279 dx /= scale;
280 dy /= scale;
281 scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
282 GDK_INTERP_BILINEAR);
283 (*fp_g_object_unref)(pixbuf);
284 pixbuf = scaledPixbuf;
285 }
286
287 if (pixbuf) {
288 int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
289 int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
290
291 if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
292 && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
293 && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
294 && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
295 && nchan >= 3
296 ) {
297 guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
298
299 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
300 if (!ary) {
301 (*fp_g_object_unref)(pixbuf);
302 (*fp_gdk_threads_leave)();
303 AWT_UNLOCK();
304 return;
305 }
306
307 for (_y = 0; _y < height; _y++) {
308 for (_x = 0; _x < width; _x++) {
309 p = pix + _y * stride + _x * nchan;
310
311 index = (_y + dy) * jwidth + (_x + dx);
312 ary[index] = 0xff000000
313 | (p[0] << 16)
314 | (p[1] << 8)
315 | (p[2]);
316
317 }
318 }
319 (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
320 if ((*env)->ExceptionCheck(env)) {
321 (*fp_g_object_unref)(pixbuf);
322 (*fp_gdk_threads_leave)();
323 AWT_UNLOCK();
324 return;
325 }
326 gtk_failed = FALSE;
327 }
328 (*fp_g_object_unref)(pixbuf);
329 }
330 (*fp_gdk_threads_leave)();
331 }
332
333 if (gtk_failed) {
334 image = getWindowImage(awt_display, rootWindow, sx, sy, swidth, sheight);
335
336 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
337
338 if (!ary) {
339 XDestroyImage(image);
340 AWT_UNLOCK();
341 return;
342 }
343
344 dx /= scale;
345 dy /= scale;
346 width /= scale;
347 height /= scale;
348
349 /* convert to Java ARGB pixels */
350 for (_y = 0; _y < height; _y++) {
351 for (_x = 0; _x < width; _x++) {
352 jint pixel = (jint) XGetPixel(image, _x * scale, _y * scale);
353 /* Note ignore upper
354 * 32-bits on 64-bit
355 * OSes.
356 */
357 pixel |= 0xff000000; /* alpha - full opacity */
358
359 index = (_y + dy) * jwidth + (_x + dx);
360 ary[index] = pixel;
361 }
362 }
363
364 XDestroyImage(image);
365 (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
366 }
367 AWT_UNLOCK();
368 }
369
370 JNIEXPORT void JNICALL
371 Java_sun_awt_X11_XRobotPeer_keyPressImpl (JNIEnv *env,
372 jclass cls,
373 jint keycode) {
374
375 AWT_LOCK();
376
377 DTRACE_PRINTLN1("RobotPeer: keyPressImpl(%i)", keycode);
378
379 XTestFakeKeyEvent(awt_display,
380 XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
381 True,
382 CurrentTime);
383
384 XSync(awt_display, False);
385
386 AWT_UNLOCK();
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #ifdef HEADLESS
27 #error This file should not be included in headless library
28 #endif
29
30 #include "awt_p.h"
31 #include "awt_GraphicsEnv.h"
32 #define XK_MISCELLANY
33 #include <X11/keysymdef.h>
34 #include <X11/Intrinsic.h>
35 #include <X11/Xutil.h>
36 #include <X11/Xmd.h>
37 #include <X11/extensions/xtestext1.h>
38 #include <X11/extensions/XTest.h>
39 #include <X11/extensions/XInput.h>
40 #include <X11/extensions/XI.h>
41 #include <X11/extensions/Xcomposite.h>
42 #include <jni.h>
43 #include <sizecalc.h>
44 #include "robot_common.h"
45 #include "canvas.h"
46 #include "wsutils.h"
47 #include "list.h"
48 #include "multiVis.h"
49
50 #if defined(__linux__) || defined(MACOSX)
51 #include <sys/socket.h>
52 #endif
53
54 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
55
56 static jint * masks;
57 static jint num_buttons;
58
59 static int32_t isXTestAvailable() {
60 int32_t major_opcode, first_event, first_error;
61 int32_t event_basep, error_basep, majorp, minorp;
62 int32_t isXTestAvailable;
63
64 /* check if XTest is available */
65 isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
66 DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
67 major_opcode, first_event, first_error);
68 if (isXTestAvailable) {
73 if (majorp < 2 || (majorp == 2 && minorp < 2)) {
74 /* bad version*/
75 DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
76 if (majorp == 2 && minorp == 1) {
77 DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
78 } else {
79 isXTestAvailable = False;
80 }
81 } else {
82 /* allow XTest calls even if someone else has the grab; e.g. during
83 * a window resize operation. Works only with XTEST2.2*/
84 XTestGrabControl(awt_display, True);
85 }
86 } else {
87 DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
88 }
89
90 return isXTestAvailable;
91 }
92
93 static Bool hasXCompositeOverlayExtension(Display *display) {
94 int xoverlay = False;
95 int eventBase, errorBase;
96 if (XCompositeQueryExtension(display, &eventBase, &errorBase)) {
97 int major = 0;
98 int minor = 0;
99
100 XCompositeQueryVersion(display, &major, &minor);
101 if (major > 0 || minor >= 3) {
102 xoverlay = True;
103 }
104 }
105
106 return xoverlay;
107 }
108
109 static jboolean isXCompositeDisplay(Display *display, int screenNumber) {
110
111 char NET_WM_CM_Sn[25];
112 snprintf(NET_WM_CM_Sn, sizeof(NET_WM_CM_Sn), "_NET_WM_CM_S%d\0", screenNumber);
113
114 Atom managerSelection = XInternAtom(display, NET_WM_CM_Sn, 0);
115 Window owner = XGetSelectionOwner(display, managerSelection);
116
117 return owner != 0;
118 }
119
120 static XImage *getWindowImage(Display * display, Window window,
121 int32_t x, int32_t y,
122 int32_t w, int32_t h) {
123 XImage *image;
124 int32_t transparentOverlays;
125 int32_t numVisuals;
126 XVisualInfo *pVisuals;
127 int32_t numOverlayVisuals;
128 OverlayInfo *pOverlayVisuals;
129 int32_t numImageVisuals;
130 XVisualInfo **pImageVisuals;
131 list_ptr vis_regions; /* list of regions to read from */
132 list_ptr vis_image_regions ;
133 int32_t allImage = 0 ;
134 int32_t format = ZPixmap;
135
136 /* prevent user from moving stuff around during the capture */
137 XGrabServer(display);
138
220 AWT_LOCK();
221 xtestAvailable = isXTestAvailable();
222 DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
223 if (!xtestAvailable) {
224 JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
225 }
226
227 AWT_UNLOCK();
228 }
229
230
231 JNIEXPORT void JNICALL
232 Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
233 jclass cls,
234 jobject xgc,
235 jint jx,
236 jint jy,
237 jint jwidth,
238 jint jheight,
239 jint scale,
240 jintArray pixelArray) {
241 XImage *image;
242 jint *ary; /* Array of jints for sending pixel values back
243 * to parent process.
244 */
245 Window rootWindow;
246 XWindowAttributes attr;
247 AwtGraphicsConfigDataPtr adata;
248
249 DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, jx, jy, jwidth, jheight, pixelArray);
250
251 if (jwidth <= 0 || jheight <= 0) {
252 return;
253 }
254
255 adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
256 DASSERT(adata != NULL);
257
258 AWT_LOCK();
259
260 jint sx = jx * scale;
261 jint sy = jy * scale;
262 jint swidth = jwidth * scale;
263 jint sheight = jheight * scale;
264
265 rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
266 if (isXCompositeDisplay(awt_display, adata->awt_visInfo.screen) &&
267 hasXCompositeOverlayExtension(awt_display))
268 {
269 rootWindow = XCompositeGetOverlayWindow(awt_display, rootWindow);
270 }
271
272 if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
273 || sx + swidth <= attr.x
274 || attr.x + attr.width <= sx
275 || sy + sheight <= attr.y
276 || attr.y + attr.height <= sy) {
277
278 AWT_UNLOCK();
279 return; // Does not intersect with root window
280 }
281
282 jint _x, _y;
283
284 jint x = MAX(sx, attr.x);
285 jint y = MAX(sy, attr.y);
286 jint width = MIN(sx + swidth, attr.x + attr.width) - x;
287 jint height = MIN(sy + sheight, attr.y + attr.height) - y;
288
289
290 int dx = attr.x > sx ? attr.x - sx : 0;
291 int dy = attr.y > sy ? attr.y - sy : 0;
292
293 int index;
294
295 image = getWindowImage(awt_display, rootWindow, sx, sy, swidth, sheight);
296
297 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
298
299 if (!ary) {
300 XDestroyImage(image);
301 AWT_UNLOCK();
302 return;
303 }
304
305 dx /= scale;
306 dy /= scale;
307 width /= scale;
308 height /= scale;
309
310 /* convert to Java ARGB pixels */
311 for (_y = 0; _y < height; _y++) {
312 for (_x = 0; _x < width; _x++) {
313 jint pixel = (jint) XGetPixel(image, _x * scale, _y * scale);
314 /* Note ignore upper
315 * 32-bits on 64-bit
316 * OSes.
317 */
318 pixel |= 0xff000000; /* alpha - full opacity */
319
320 index = (_y + dy) * jwidth + (_x + dx);
321 ary[index] = pixel;
322 }
323 }
324
325 XDestroyImage(image);
326 (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
327
328 AWT_UNLOCK();
329 }
330
331 JNIEXPORT void JNICALL
332 Java_sun_awt_X11_XRobotPeer_keyPressImpl (JNIEnv *env,
333 jclass cls,
334 jint keycode) {
335
336 AWT_LOCK();
337
338 DTRACE_PRINTLN1("RobotPeer: keyPressImpl(%i)", keycode);
339
340 XTestFakeKeyEvent(awt_display,
341 XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
342 True,
343 CurrentTime);
344
345 XSync(awt_display, False);
346
347 AWT_UNLOCK();
|