annotate src/solaris/native/sun/awt/awt_Robot.c @ 3261:a06412e13bf7

6962318: Update copyright year Reviewed-by: xdono
author ohair
date Tue, 28 Dec 2010 15:53:50 -0800
parents c595c2730226
children 346b4438a7d6
rev   line source
duke@0 1 /*
ohair@3261 2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
ohair@2362 7 * published by the Free Software Foundation. Oracle designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
ohair@2362 9 * by Oracle in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
ohair@2362 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@2362 22 * or visit www.oracle.com if you need additional information or have any
ohair@2362 23 * questions.
duke@0 24 */
duke@0 25
duke@0 26 #ifdef HEADLESS
duke@0 27 #error This file should not be included in headless library
duke@0 28 #endif
duke@0 29
duke@0 30 #include "awt_p.h"
duke@0 31 #include "awt_Component.h"
duke@0 32 #include "awt_GraphicsEnv.h"
duke@0 33 #define XK_MISCELLANY
duke@0 34 #include <X11/keysymdef.h>
duke@0 35 #include <X11/Intrinsic.h>
duke@0 36 #include <X11/Xutil.h>
duke@0 37 #include <X11/Xmd.h>
duke@0 38 #include <X11/extensions/xtestext1.h>
duke@0 39 #include <X11/extensions/XTest.h>
duke@0 40 #include <X11/extensions/XInput.h>
duke@0 41 #include <X11/extensions/XI.h>
duke@0 42 #include <jni.h>
duke@0 43 #include "robot_common.h"
duke@0 44 #include "canvas.h"
duke@0 45 #include "wsutils.h"
duke@0 46 #include "list.h"
duke@0 47 #include "multiVis.h"
duke@0 48 #ifdef __linux__
duke@0 49 #include <sys/socket.h>
duke@0 50 #endif
duke@0 51
duke@0 52 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
duke@0 53
dav@870 54 static jint * masks;
dcherepanov@1444 55 static jint num_buttons;
duke@0 56
duke@0 57 static int32_t isXTestAvailable() {
duke@0 58 int32_t major_opcode, first_event, first_error;
duke@0 59 int32_t event_basep, error_basep, majorp, minorp;
duke@0 60 int32_t isXTestAvailable;
duke@0 61
duke@0 62 /* check if XTest is available */
duke@0 63 isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
duke@0 64 DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
duke@0 65 major_opcode, first_event, first_error);
duke@0 66 if (isXTestAvailable) {
duke@0 67 /* check if XTest version is OK */
duke@0 68 XTestQueryExtension(awt_display, &event_basep, &error_basep, &majorp, &minorp);
duke@0 69 DTRACE_PRINTLN4("RobotPeer: XTestQueryExtension returns event_basep = %d, error_basep = %d, majorp = %d, minorp = %d",
duke@0 70 event_basep, error_basep, majorp, minorp);
duke@0 71 if (majorp < 2 || (majorp == 2 && minorp < 2)) {
duke@0 72 /* bad version*/
duke@0 73 DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
duke@0 74 if (majorp == 2 && minorp == 1) {
duke@0 75 DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
duke@0 76 } else {
duke@0 77 isXTestAvailable = False;
duke@0 78 }
duke@0 79 } else {
duke@0 80 /* allow XTest calls even if someone else has the grab; e.g. during
duke@0 81 * a window resize operation. Works only with XTEST2.2*/
duke@0 82 XTestGrabControl(awt_display, True);
duke@0 83 }
duke@0 84 } else {
duke@0 85 DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
duke@0 86 }
duke@0 87
duke@0 88 return isXTestAvailable;
duke@0 89 }
duke@0 90
duke@0 91
duke@0 92 static XImage *getWindowImage(Display * display, Window window,
duke@0 93 int32_t x, int32_t y,
duke@0 94 int32_t w, int32_t h) {
duke@0 95 XImage *image;
duke@0 96 int32_t transparentOverlays;
duke@0 97 int32_t numVisuals;
duke@0 98 XVisualInfo *pVisuals;
duke@0 99 int32_t numOverlayVisuals;
duke@0 100 OverlayInfo *pOverlayVisuals;
duke@0 101 int32_t numImageVisuals;
duke@0 102 XVisualInfo **pImageVisuals;
duke@0 103 list_ptr vis_regions; /* list of regions to read from */
duke@0 104 list_ptr vis_image_regions ;
duke@0 105 int32_t allImage = 0 ;
duke@0 106 int32_t format = ZPixmap;
duke@0 107
duke@0 108 /* prevent user from moving stuff around during the capture */
duke@0 109 XGrabServer(display);
duke@0 110
duke@0 111 /*
duke@0 112 * The following two functions live in multiVis.c-- they are pretty
duke@0 113 * much verbatim taken from the source to the xwd utility from the
duke@0 114 * X11 source. This version of the xwd source was somewhat better written
duke@0 115 * for reuse compared to Sun's version.
duke@0 116 *
duke@0 117 * ftp.x.org/pub/R6.3/xc/programs/xwd
duke@0 118 *
duke@0 119 * We use these functions since they do the very tough job of capturing
duke@0 120 * the screen correctly when it contains multiple visuals. They take into
duke@0 121 * account the depth/colormap of each visual and produce a capture as a
duke@0 122 * 24-bit RGB image so we don't have to fool around with colormaps etc.
duke@0 123 */
duke@0 124
duke@0 125 GetMultiVisualRegions(
duke@0 126 display,
duke@0 127 window,
duke@0 128 x, y, w, h,
duke@0 129 &transparentOverlays,
duke@0 130 &numVisuals,
duke@0 131 &pVisuals,
duke@0 132 &numOverlayVisuals,
duke@0 133 &pOverlayVisuals,
duke@0 134 &numImageVisuals,
duke@0 135 &pImageVisuals,
duke@0 136 &vis_regions,
duke@0 137 &vis_image_regions,
duke@0 138 &allImage );
duke@0 139
duke@0 140 image = ReadAreaToImage(
duke@0 141 display,
duke@0 142 window,
duke@0 143 x, y, w, h,
duke@0 144 numVisuals,
duke@0 145 pVisuals,
duke@0 146 numOverlayVisuals,
duke@0 147 pOverlayVisuals,
duke@0 148 numImageVisuals,
duke@0 149 pImageVisuals,
duke@0 150 vis_regions,
duke@0 151 vis_image_regions,
duke@0 152 format,
duke@0 153 allImage );
duke@0 154
duke@0 155 /* allow user to do stuff again */
duke@0 156 XUngrabServer(display);
duke@0 157
duke@0 158 /* make sure the grab/ungrab is flushed */
duke@0 159 XSync(display, False);
duke@0 160
duke@0 161 return image;
duke@0 162 }
duke@0 163
duke@0 164 /*********************************************************************************************/
duke@0 165
dcherepanov@1444 166 // this should be called from XRobotPeer constructor
duke@0 167 JNIEXPORT void JNICALL
art@2859 168 Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButtons, jintArray buttonDownMasks)
art@2859 169 {
duke@0 170 int32_t xtestAvailable;
art@2859 171 jint *tmp;
art@2859 172 int i;
duke@0 173
dcherepanov@1444 174 DTRACE_PRINTLN("RobotPeer: setup()");
dcherepanov@1444 175
dcherepanov@1444 176 num_buttons = numberOfButtons;
art@2859 177 tmp = (*env)->GetIntArrayElements(env, buttonDownMasks, JNI_FALSE);
art@2859 178 masks = (jint *)malloc(sizeof(jint) * num_buttons);
dav@870 179 if (masks == (jint *) NULL) {
dav@870 180 JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL);
art@2859 181 (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
art@2859 182 return;
dav@870 183 }
dcherepanov@1444 184 for (i = 0; i < num_buttons; i++) {
dav@870 185 masks[i] = tmp[i];
dav@870 186 }
art@2859 187 (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
dav@870 188
duke@0 189 AWT_LOCK();
duke@0 190 xtestAvailable = isXTestAvailable();
duke@0 191 DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
duke@0 192 if (!xtestAvailable) {
duke@0 193 JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
duke@0 194 }
duke@0 195
dav@870 196 AWT_UNLOCK();
dav@870 197 }
duke@0 198
duke@0 199
duke@0 200 JNIEXPORT void JNICALL
yan@547 201 Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
duke@0 202 jclass cls,
duke@0 203 jobject xgc,
duke@0 204 jint x,
duke@0 205 jint y,
duke@0 206 jint width,
duke@0 207 jint height,
duke@0 208 jintArray pixelArray) {
duke@0 209
duke@0 210 XImage *image;
duke@0 211 jint *ary; /* Array of jints for sending pixel values back
duke@0 212 * to parent process.
duke@0 213 */
duke@0 214 Window rootWindow;
duke@0 215 AwtGraphicsConfigDataPtr adata;
duke@0 216
duke@0 217 DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray);
duke@0 218
duke@0 219 AWT_LOCK();
duke@0 220
duke@0 221 /* avoid a lot of work for empty rectangles */
duke@0 222 if ((width * height) == 0) {
duke@0 223 AWT_UNLOCK();
duke@0 224 return;
duke@0 225 }
duke@0 226 DASSERT(width * height > 0); /* only allow positive size */
duke@0 227
duke@0 228 adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
duke@0 229 DASSERT(adata != NULL);
duke@0 230
duke@0 231 rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
duke@0 232 image = getWindowImage(awt_display, rootWindow, x, y, width, height);
duke@0 233
duke@0 234 /* Array to use to crunch around the pixel values */
duke@0 235 ary = (jint *) malloc(width * height * sizeof (jint));
duke@0 236 if (ary == NULL) {
duke@0 237 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
duke@0 238 XDestroyImage(image);
duke@0 239 AWT_UNLOCK();
duke@0 240 return;
duke@0 241 }
duke@0 242 /* convert to Java ARGB pixels */
duke@0 243 for (y = 0; y < height; y++) {
duke@0 244 for (x = 0; x < width; x++) {
duke@0 245 jint pixel = (jint) XGetPixel(image, x, y); /* Note ignore upper
duke@0 246 * 32-bits on 64-bit
duke@0 247 * OSes.
duke@0 248 */
duke@0 249
duke@0 250 pixel |= 0xff000000; /* alpha - full opacity */
duke@0 251
duke@0 252 ary[(y * width) + x] = pixel;
duke@0 253 }
duke@0 254 }
duke@0 255 (*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
duke@0 256 free(ary);
duke@0 257
duke@0 258 XDestroyImage(image);
duke@0 259
duke@0 260 AWT_UNLOCK();
duke@0 261 }
duke@0 262
duke@0 263 JNIEXPORT void JNICALL
yan@547 264 Java_sun_awt_X11_XRobotPeer_keyPressImpl (JNIEnv *env,
duke@0 265 jclass cls,
duke@0 266 jint keycode) {
duke@0 267
duke@0 268 AWT_LOCK();
duke@0 269
duke@0 270 DTRACE_PRINTLN1("RobotPeer: keyPressImpl(%i)", keycode);
duke@0 271
duke@0 272 XTestFakeKeyEvent(awt_display,
duke@0 273 XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
duke@0 274 True,
duke@0 275 CurrentTime);
duke@0 276
duke@0 277 XSync(awt_display, False);
duke@0 278
duke@0 279 AWT_UNLOCK();
duke@0 280
duke@0 281 }
duke@0 282
duke@0 283 JNIEXPORT void JNICALL
yan@547 284 Java_sun_awt_X11_XRobotPeer_keyReleaseImpl (JNIEnv *env,
duke@0 285 jclass cls,
duke@0 286 jint keycode) {
duke@0 287 AWT_LOCK();
duke@0 288
duke@0 289 DTRACE_PRINTLN1("RobotPeer: keyReleaseImpl(%i)", keycode);
duke@0 290
duke@0 291 XTestFakeKeyEvent(awt_display,
duke@0 292 XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
duke@0 293 False,
duke@0 294 CurrentTime);
duke@0 295
duke@0 296 XSync(awt_display, False);
duke@0 297
duke@0 298 AWT_UNLOCK();
duke@0 299 }
duke@0 300
duke@0 301 JNIEXPORT void JNICALL
yan@547 302 Java_sun_awt_X11_XRobotPeer_mouseMoveImpl (JNIEnv *env,
duke@0 303 jclass cls,
duke@0 304 jobject xgc,
duke@0 305 jint root_x,
duke@0 306 jint root_y) {
duke@0 307
duke@0 308 AwtGraphicsConfigDataPtr adata;
duke@0 309
duke@0 310 AWT_LOCK();
duke@0 311
duke@0 312 DTRACE_PRINTLN3("RobotPeer: mouseMoveImpl(%lx, %i, %i)", xgc, root_x, root_y);
duke@0 313
duke@0 314 adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
duke@0 315 DASSERT(adata != NULL);
duke@0 316
duke@0 317 XWarpPointer(awt_display, None, XRootWindow(awt_display, adata->awt_visInfo.screen), 0, 0, 0, 0, root_x, root_y);
duke@0 318 XSync(awt_display, False);
duke@0 319
duke@0 320 AWT_UNLOCK();
duke@0 321 }
duke@0 322
dav@870 323 /*
dav@870 324 * Function joining the code of mousePressImpl and mouseReleaseImpl
dav@870 325 */
dav@870 326 void mouseAction(JNIEnv *env,
dav@870 327 jclass cls,
dav@870 328 jint buttonMask,
dav@870 329 Bool isMousePress)
dav@870 330 {
dav@870 331 AWT_LOCK();
dav@870 332
dav@870 333 DTRACE_PRINTLN1("RobotPeer: mouseAction(%i)", buttonMask);
dav@870 334 DTRACE_PRINTLN1("RobotPeer: mouseAction, press = %d", isMousePress);
dav@870 335
dav@870 336 if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ||
dav@870 337 buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK )
dav@870 338 {
dav@870 339 XTestFakeButtonEvent(awt_display, 1, isMousePress, CurrentTime);
dav@870 340 }
dav@870 341 if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ||
dav@870 342 buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) &&
dav@870 343 (num_buttons >= 2)) {
dav@870 344 XTestFakeButtonEvent(awt_display, 2, isMousePress, CurrentTime);
dav@870 345 }
dav@870 346 if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ||
dav@870 347 buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) &&
dav@870 348 (num_buttons >= 3)) {
dav@870 349 XTestFakeButtonEvent(awt_display, 3, isMousePress, CurrentTime);
dav@870 350 }
dav@870 351
dav@870 352 if (num_buttons > 3){
dav@870 353 int32_t i;
dav@870 354 int32_t button = 0;
dav@870 355 for (i = 3; i<num_buttons; i++){
dav@870 356 if ((buttonMask & masks[i])) {
dav@870 357 // arrays starts from zero index => +1
dav@870 358 // users wants to affect 4 or 5 button but they are assigned
dav@870 359 // to the wheel so => we have to shift it to the right by 2.
dav@870 360 button = i + 3;
dav@870 361 XTestFakeButtonEvent(awt_display, button, isMousePress, CurrentTime);
dav@870 362 }
dav@870 363 }
dav@870 364 }
dav@870 365
dav@870 366 XSync(awt_display, False);
dav@870 367 AWT_UNLOCK();
dav@870 368 }
dav@870 369
dav@873 370 JNIEXPORT void JNICALL
dav@873 371 Java_sun_awt_X11_XRobotPeer_mousePressImpl (JNIEnv *env,
dav@873 372 jclass cls,
dav@873 373 jint buttonMask) {
dav@873 374 mouseAction(env, cls, buttonMask, True);
dav@873 375 }
dav@873 376
dav@873 377 JNIEXPORT void JNICALL
dav@873 378 Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl (JNIEnv *env,
dav@873 379 jclass cls,
dav@873 380 jint buttonMask) {
dav@873 381 mouseAction(env, cls, buttonMask, False);
dav@873 382 }
dav@870 383
duke@0 384 JNIEXPORT void JNICALL
yan@547 385 Java_sun_awt_X11_XRobotPeer_mouseWheelImpl (JNIEnv *env,
duke@0 386 jclass cls,
duke@0 387 jint wheelAmt) {
duke@0 388 /* Mouse wheel is implemented as a button press of button 4 and 5, so it */
duke@0 389 /* probably could have been hacked into robot_mouseButtonEvent, but it's */
duke@0 390 /* cleaner to give it its own command type, in case the implementation */
duke@0 391 /* needs to be changed later. -bchristi, 6/20/01 */
duke@0 392
duke@0 393 int32_t repeat = abs(wheelAmt);
duke@0 394 int32_t button = wheelAmt < 0 ? 4 : 5; /* wheel up: button 4 */
duke@0 395 /* wheel down: button 5 */
duke@0 396 int32_t loopIdx;
duke@0 397
duke@0 398 AWT_LOCK();
duke@0 399
duke@0 400 DTRACE_PRINTLN1("RobotPeer: mouseWheelImpl(%i)", wheelAmt);
duke@0 401
duke@0 402 for (loopIdx = 0; loopIdx < repeat; loopIdx++) { /* do nothing for */
duke@0 403 /* wheelAmt == 0 */
duke@0 404 XTestFakeButtonEvent(awt_display, button, True, CurrentTime);
duke@0 405 XTestFakeButtonEvent(awt_display, button, False, CurrentTime);
duke@0 406 }
duke@0 407 XSync(awt_display, False);
duke@0 408
duke@0 409 AWT_UNLOCK();
duke@0 410 }