10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
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/Xutil.h>
35 #include <X11/Xmd.h>
36 #include <X11/extensions/xtestext1.h>
37 #include <X11/extensions/XTest.h>
38 #include <X11/extensions/XInput.h>
39 #include <X11/extensions/XI.h>
40 #include <jni.h>
41 #include <sizecalc.h>
42 #include "robot_common.h"
43 #include "canvas.h"
44 #include "wsutils.h"
45 #include "list.h"
46 #include "multiVis.h"
47 #include "gtk_interface.h"
48
49 #if defined(__linux__) || defined(MACOSX)
50 #include <sys/socket.h>
51 #endif
52
53 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
54
55 static jint * masks;
56 static jint num_buttons;
57
58 static int32_t isXTestAvailable() {
59 int32_t major_opcode, first_event, first_error;
60 int32_t event_basep, error_basep, majorp, minorp;
61 int32_t isXTestAvailable;
62
63 /* check if XTest is available */
64 isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
65 DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
66 major_opcode, first_event, first_error);
67 if (isXTestAvailable) {
68 /* check if XTest version is OK */
69 XTestQueryExtension(awt_display, &event_basep, &error_basep, &majorp, &minorp);
70 DTRACE_PRINTLN4("RobotPeer: XTestQueryExtension returns event_basep = %d, error_basep = %d, majorp = %d, minorp = %d",
71 event_basep, error_basep, majorp, minorp);
72 if (majorp < 2 || (majorp == 2 && minorp < 2)) {
73 /* bad version*/
74 DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
75 if (majorp == 2 && minorp == 1) {
76 DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
77 } else {
78 isXTestAvailable = False;
79 }
80 } else {
81 /* allow XTest calls even if someone else has the grab; e.g. during
82 * a window resize operation. Works only with XTEST2.2*/
83 XTestGrabControl(awt_display, True);
84 }
85 } else {
86 DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
87 }
88
89 return isXTestAvailable;
90 }
91
92
93 static XImage *getWindowImage(Display * display, Window window,
94 int32_t x, int32_t y,
95 int32_t w, int32_t h) {
96 XImage *image;
97 int32_t transparentOverlays;
98 int32_t numVisuals;
99 XVisualInfo *pVisuals;
100 int32_t numOverlayVisuals;
101 OverlayInfo *pOverlayVisuals;
102 int32_t numImageVisuals;
103 XVisualInfo **pImageVisuals;
104 list_ptr vis_regions; /* list of regions to read from */
105 list_ptr vis_image_regions ;
106 int32_t allImage = 0 ;
107 int32_t format = ZPixmap;
108
109 /* prevent user from moving stuff around during the capture */
110 XGrabServer(display);
111
194 xtestAvailable = isXTestAvailable();
195 DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
196 if (!xtestAvailable) {
197 JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
198 }
199
200 AWT_UNLOCK();
201 }
202
203
204 JNIEXPORT void JNICALL
205 Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
206 jclass cls,
207 jobject xgc,
208 jint jx,
209 jint jy,
210 jint jwidth,
211 jint jheight,
212 jint scale,
213 jintArray pixelArray,
214 jboolean isGtkSupported) {
215 XImage *image;
216 jint *ary; /* Array of jints for sending pixel values back
217 * to parent process.
218 */
219 Window rootWindow;
220 XWindowAttributes attr;
221 AwtGraphicsConfigDataPtr adata;
222
223 DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, jx, jy, jwidth, jheight, pixelArray);
224
225 if (jwidth <= 0 || jheight <= 0) {
226 return;
227 }
228
229 adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
230 DASSERT(adata != NULL);
231
232 AWT_LOCK();
233
234 jint sx = jx * scale;
235 jint sy = jy * scale;
236 jint swidth = jwidth * scale;
237 jint sheight = jheight * scale;
238
239 rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
240
241 if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
242 || sx + swidth <= attr.x
243 || attr.x + attr.width <= sx
244 || sy + sheight <= attr.y
245 || attr.y + attr.height <= sy) {
246
247 AWT_UNLOCK();
248 return; // Does not intersect with root window
249 }
250
251 gboolean gtk_failed = TRUE;
252 jint _x, _y;
253
254 jint x = MAX(sx, attr.x);
255 jint y = MAX(sy, attr.y);
256 jint width = MIN(sx + swidth, attr.x + attr.width) - x;
257 jint height = MIN(sy + sheight, attr.y + attr.height) - y;
258
259
260 int dx = attr.x > sx ? attr.x - sx : 0;
261 int dy = attr.y > sy ? attr.y - sy : 0;
262
263 int index;
264
265 if (isGtkSupported) {
266 gtk->gdk_threads_enter();
267 gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width,
268 height, jwidth, dx, dy, scale);
269 gtk->gdk_threads_leave();
270 }
271
272 if (gtk_failed) {
273 image = getWindowImage(awt_display, rootWindow, sx, sy, swidth, sheight);
274
275 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
276
277 if (!ary) {
278 XDestroyImage(image);
279 AWT_UNLOCK();
280 return;
281 }
282
283 dx /= scale;
284 dy /= scale;
285 width /= scale;
436 /* cleaner to give it its own command type, in case the implementation */
437 /* needs to be changed later. -bchristi, 6/20/01 */
438
439 int32_t repeat = abs(wheelAmt);
440 int32_t button = wheelAmt < 0 ? 4 : 5; /* wheel up: button 4 */
441 /* wheel down: button 5 */
442 int32_t loopIdx;
443
444 AWT_LOCK();
445
446 DTRACE_PRINTLN1("RobotPeer: mouseWheelImpl(%i)", wheelAmt);
447
448 for (loopIdx = 0; loopIdx < repeat; loopIdx++) { /* do nothing for */
449 /* wheelAmt == 0 */
450 XTestFakeButtonEvent(awt_display, button, True, CurrentTime);
451 XTestFakeButtonEvent(awt_display, button, False, CurrentTime);
452 }
453 XSync(awt_display, False);
454
455 AWT_UNLOCK();
456 }
|
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
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 "jvm_md.h"
31 #include <dlfcn.h>
32
33 #include "awt_p.h"
34 #include "awt_GraphicsEnv.h"
35 #define XK_MISCELLANY
36 #include <X11/keysymdef.h>
37 #include <X11/Xutil.h>
38 #include <X11/Xmd.h>
39 #include <X11/extensions/xtestext1.h>
40 #include <X11/extensions/XTest.h>
41 #include <X11/extensions/XInput.h>
42 #include <X11/extensions/XI.h>
43 #include <jni.h>
44 #include <sizecalc.h>
45 #include "robot_common.h"
46 #include "canvas.h"
47 #include "wsutils.h"
48 #include "list.h"
49 #include "multiVis.h"
50 #include "gtk_interface.h"
51
52 #if defined(__linux__) || defined(MACOSX)
53 #include <sys/socket.h>
54 #endif
55
56 static Bool (*compositeQueryExtension) (Display*, int*, int*);
57 static Status (*compositeQueryVersion) (Display*, int*, int*);
58 static Window (*compositeGetOverlayWindow) (Display *, Window);
59
60 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
61
62 static jint * masks;
63 static jint num_buttons;
64
65 static void *xCompositeHandle;
66
67 static const char* XCOMPOSITE = JNI_LIB_NAME("Xcomposite");
68 static const char* XCOMPOSITE_VERSIONED = VERSIONED_JNI_LIB_NAME("Xcomposite", "1");
69
70 static Bool checkXCompositeFunctions(void) {
71 return (compositeQueryExtension != NULL &&
72 compositeQueryVersion != NULL &&
73 compositeGetOverlayWindow != NULL);
74 }
75
76 static void initXCompositeFunctions(void) {
77
78 if (xCompositeHandle == NULL) {
79 xCompositeHandle = dlopen(XCOMPOSITE, RTLD_LAZY | RTLD_GLOBAL);
80 if (xCompositeHandle == NULL) {
81 xCompositeHandle = dlopen(XCOMPOSITE_VERSIONED, RTLD_LAZY | RTLD_GLOBAL);
82 }
83 }
84 //*(void **)(&asyncGetCallTraceFunction)
85 if (xCompositeHandle != NULL) {
86 *(void **)(&compositeQueryExtension) = dlsym(xCompositeHandle, "XCompositeQueryExtension");
87 *(void **)(&compositeQueryVersion) = dlsym(xCompositeHandle, "XCompositeQueryVersion");
88 *(void **)(&compositeGetOverlayWindow) = dlsym(xCompositeHandle, "XCompositeGetOverlayWindow");
89 }
90
91 if (xCompositeHandle && !checkXCompositeFunctions()) {
92 dlclose(xCompositeHandle);
93 }
94 }
95
96 static int32_t isXTestAvailable() {
97 int32_t major_opcode, first_event, first_error;
98 int32_t event_basep, error_basep, majorp, minorp;
99 int32_t isXTestAvailable;
100
101 /* check if XTest is available */
102 isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
103 DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
104 major_opcode, first_event, first_error);
105 if (isXTestAvailable) {
106 /* check if XTest version is OK */
107 XTestQueryExtension(awt_display, &event_basep, &error_basep, &majorp, &minorp);
108 DTRACE_PRINTLN4("RobotPeer: XTestQueryExtension returns event_basep = %d, error_basep = %d, majorp = %d, minorp = %d",
109 event_basep, error_basep, majorp, minorp);
110 if (majorp < 2 || (majorp == 2 && minorp < 2)) {
111 /* bad version*/
112 DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
113 if (majorp == 2 && minorp == 1) {
114 DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
115 } else {
116 isXTestAvailable = False;
117 }
118 } else {
119 /* allow XTest calls even if someone else has the grab; e.g. during
120 * a window resize operation. Works only with XTEST2.2*/
121 XTestGrabControl(awt_display, True);
122 }
123 } else {
124 DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
125 }
126
127 return isXTestAvailable;
128 }
129
130 static Bool hasXCompositeOverlayExtension(Display *display) {
131
132 int xoverlay = False;
133 int eventBase, errorBase;
134 if (checkXCompositeFunctions() &&
135 compositeQueryExtension(display, &eventBase, &errorBase))
136 {
137 int major = 0;
138 int minor = 0;
139
140 compositeQueryVersion(display, &major, &minor);
141 if (major > 0 || minor >= 3) {
142 xoverlay = True;
143 }
144 }
145
146 return xoverlay;
147 }
148
149 static jboolean isXCompositeDisplay(Display *display, int screenNumber) {
150
151 char NET_WM_CM_Sn[25];
152 snprintf(NET_WM_CM_Sn, sizeof(NET_WM_CM_Sn), "_NET_WM_CM_S%d\0", screenNumber);
153
154 Atom managerSelection = XInternAtom(display, NET_WM_CM_Sn, 0);
155 Window owner = XGetSelectionOwner(display, managerSelection);
156
157 return owner != 0;
158 }
159
160 static XImage *getWindowImage(Display * display, Window window,
161 int32_t x, int32_t y,
162 int32_t w, int32_t h) {
163 XImage *image;
164 int32_t transparentOverlays;
165 int32_t numVisuals;
166 XVisualInfo *pVisuals;
167 int32_t numOverlayVisuals;
168 OverlayInfo *pOverlayVisuals;
169 int32_t numImageVisuals;
170 XVisualInfo **pImageVisuals;
171 list_ptr vis_regions; /* list of regions to read from */
172 list_ptr vis_image_regions ;
173 int32_t allImage = 0 ;
174 int32_t format = ZPixmap;
175
176 /* prevent user from moving stuff around during the capture */
177 XGrabServer(display);
178
261 xtestAvailable = isXTestAvailable();
262 DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
263 if (!xtestAvailable) {
264 JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
265 }
266
267 AWT_UNLOCK();
268 }
269
270
271 JNIEXPORT void JNICALL
272 Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
273 jclass cls,
274 jobject xgc,
275 jint jx,
276 jint jy,
277 jint jwidth,
278 jint jheight,
279 jint scale,
280 jintArray pixelArray,
281 jboolean useGtk) {
282 XImage *image;
283 jint *ary; /* Array of jints for sending pixel values back
284 * to parent process.
285 */
286 Window rootWindow;
287 XWindowAttributes attr;
288 AwtGraphicsConfigDataPtr adata;
289
290 DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, jx, jy, jwidth, jheight, pixelArray);
291
292 if (jwidth <= 0 || jheight <= 0) {
293 return;
294 }
295
296 adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
297 DASSERT(adata != NULL);
298
299 AWT_LOCK();
300
301 jint sx = jx * scale;
302 jint sy = jy * scale;
303 jint swidth = jwidth * scale;
304 jint sheight = jheight * scale;
305
306 rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
307
308 if (!useGtk) {
309 if (hasXCompositeOverlayExtension(awt_display) &&
310 isXCompositeDisplay(awt_display, adata->awt_visInfo.screen))
311 {
312 rootWindow = compositeGetOverlayWindow(awt_display, rootWindow);
313 }
314 }
315
316 if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
317 || sx + swidth <= attr.x
318 || attr.x + attr.width <= sx
319 || sy + sheight <= attr.y
320 || attr.y + attr.height <= sy) {
321
322 AWT_UNLOCK();
323 return; // Does not intersect with root window
324 }
325
326 gboolean gtk_failed = TRUE;
327 jint _x, _y;
328
329 jint x = MAX(sx, attr.x);
330 jint y = MAX(sy, attr.y);
331 jint width = MIN(sx + swidth, attr.x + attr.width) - x;
332 jint height = MIN(sy + sheight, attr.y + attr.height) - y;
333
334
335 int dx = attr.x > sx ? attr.x - sx : 0;
336 int dy = attr.y > sy ? attr.y - sy : 0;
337
338 int index;
339
340 if (useGtk) {
341 gtk->gdk_threads_enter();
342 gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width,
343 height, jwidth, dx, dy, scale);
344 gtk->gdk_threads_leave();
345 }
346
347 if (gtk_failed) {
348 image = getWindowImage(awt_display, rootWindow, sx, sy, swidth, sheight);
349
350 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
351
352 if (!ary) {
353 XDestroyImage(image);
354 AWT_UNLOCK();
355 return;
356 }
357
358 dx /= scale;
359 dy /= scale;
360 width /= scale;
511 /* cleaner to give it its own command type, in case the implementation */
512 /* needs to be changed later. -bchristi, 6/20/01 */
513
514 int32_t repeat = abs(wheelAmt);
515 int32_t button = wheelAmt < 0 ? 4 : 5; /* wheel up: button 4 */
516 /* wheel down: button 5 */
517 int32_t loopIdx;
518
519 AWT_LOCK();
520
521 DTRACE_PRINTLN1("RobotPeer: mouseWheelImpl(%i)", wheelAmt);
522
523 for (loopIdx = 0; loopIdx < repeat; loopIdx++) { /* do nothing for */
524 /* wheelAmt == 0 */
525 XTestFakeButtonEvent(awt_display, button, True, CurrentTime);
526 XTestFakeButtonEvent(awt_display, button, False, CurrentTime);
527 }
528 XSync(awt_display, False);
529
530 AWT_UNLOCK();
531 }
532
533 JNIEXPORT void JNICALL
534 Java_sun_awt_X11_XRobotPeer_loadNativeLibraries (JNIEnv *env, jclass cls) {
535 initXCompositeFunctions();
536 }
|