PageRenderTime 24ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/java-1.7.0-openjdk/openjdk/jdk/src/solaris/native/sun/awt/awt_Robot.c

#
C | 410 lines | 276 code | 67 blank | 67 comment | 32 complexity | 456866c4932c3d8cf66ec3256fdd209b MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0, LGPL-2.0
  1. /*
  2. * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  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. #ifdef HEADLESS
  26. #error This file should not be included in headless library
  27. #endif
  28. #include "awt_p.h"
  29. #include "awt_Component.h"
  30. #include "awt_GraphicsEnv.h"
  31. #define XK_MISCELLANY
  32. #include <X11/keysymdef.h>
  33. #include <X11/Intrinsic.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 "robot_common.h"
  42. #include "canvas.h"
  43. #include "wsutils.h"
  44. #include "list.h"
  45. #include "multiVis.h"
  46. #if defined(__linux__) || defined(MACOSX)
  47. #include <sys/socket.h>
  48. #endif
  49. extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
  50. static jint * masks;
  51. static jint num_buttons;
  52. static int32_t isXTestAvailable() {
  53. int32_t major_opcode, first_event, first_error;
  54. int32_t event_basep, error_basep, majorp, minorp;
  55. int32_t isXTestAvailable;
  56. /* check if XTest is available */
  57. isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
  58. DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
  59. major_opcode, first_event, first_error);
  60. if (isXTestAvailable) {
  61. /* check if XTest version is OK */
  62. XTestQueryExtension(awt_display, &event_basep, &error_basep, &majorp, &minorp);
  63. DTRACE_PRINTLN4("RobotPeer: XTestQueryExtension returns event_basep = %d, error_basep = %d, majorp = %d, minorp = %d",
  64. event_basep, error_basep, majorp, minorp);
  65. if (majorp < 2 || (majorp == 2 && minorp < 2)) {
  66. /* bad version*/
  67. DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
  68. if (majorp == 2 && minorp == 1) {
  69. DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
  70. } else {
  71. isXTestAvailable = False;
  72. }
  73. } else {
  74. /* allow XTest calls even if someone else has the grab; e.g. during
  75. * a window resize operation. Works only with XTEST2.2*/
  76. XTestGrabControl(awt_display, True);
  77. }
  78. } else {
  79. DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
  80. }
  81. return isXTestAvailable;
  82. }
  83. static XImage *getWindowImage(Display * display, Window window,
  84. int32_t x, int32_t y,
  85. int32_t w, int32_t h) {
  86. XImage *image;
  87. int32_t transparentOverlays;
  88. int32_t numVisuals;
  89. XVisualInfo *pVisuals;
  90. int32_t numOverlayVisuals;
  91. OverlayInfo *pOverlayVisuals;
  92. int32_t numImageVisuals;
  93. XVisualInfo **pImageVisuals;
  94. list_ptr vis_regions; /* list of regions to read from */
  95. list_ptr vis_image_regions ;
  96. int32_t allImage = 0 ;
  97. int32_t format = ZPixmap;
  98. /* prevent user from moving stuff around during the capture */
  99. XGrabServer(display);
  100. /*
  101. * The following two functions live in multiVis.c-- they are pretty
  102. * much verbatim taken from the source to the xwd utility from the
  103. * X11 source. This version of the xwd source was somewhat better written
  104. * for reuse compared to Sun's version.
  105. *
  106. * ftp.x.org/pub/R6.3/xc/programs/xwd
  107. *
  108. * We use these functions since they do the very tough job of capturing
  109. * the screen correctly when it contains multiple visuals. They take into
  110. * account the depth/colormap of each visual and produce a capture as a
  111. * 24-bit RGB image so we don't have to fool around with colormaps etc.
  112. */
  113. GetMultiVisualRegions(
  114. display,
  115. window,
  116. x, y, w, h,
  117. &transparentOverlays,
  118. &numVisuals,
  119. &pVisuals,
  120. &numOverlayVisuals,
  121. &pOverlayVisuals,
  122. &numImageVisuals,
  123. &pImageVisuals,
  124. &vis_regions,
  125. &vis_image_regions,
  126. &allImage );
  127. image = ReadAreaToImage(
  128. display,
  129. window,
  130. x, y, w, h,
  131. numVisuals,
  132. pVisuals,
  133. numOverlayVisuals,
  134. pOverlayVisuals,
  135. numImageVisuals,
  136. pImageVisuals,
  137. vis_regions,
  138. vis_image_regions,
  139. format,
  140. allImage );
  141. /* allow user to do stuff again */
  142. XUngrabServer(display);
  143. /* make sure the grab/ungrab is flushed */
  144. XSync(display, False);
  145. return image;
  146. }
  147. /*********************************************************************************************/
  148. // this should be called from XRobotPeer constructor
  149. JNIEXPORT void JNICALL
  150. Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButtons, jintArray buttonDownMasks)
  151. {
  152. int32_t xtestAvailable;
  153. jint *tmp;
  154. int i;
  155. DTRACE_PRINTLN("RobotPeer: setup()");
  156. num_buttons = numberOfButtons;
  157. tmp = (*env)->GetIntArrayElements(env, buttonDownMasks, JNI_FALSE);
  158. masks = (jint *)malloc(sizeof(jint) * num_buttons);
  159. if (masks == (jint *) NULL) {
  160. JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL);
  161. (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
  162. return;
  163. }
  164. for (i = 0; i < num_buttons; i++) {
  165. masks[i] = tmp[i];
  166. }
  167. (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
  168. AWT_LOCK();
  169. xtestAvailable = isXTestAvailable();
  170. DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
  171. if (!xtestAvailable) {
  172. JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
  173. }
  174. AWT_UNLOCK();
  175. }
  176. JNIEXPORT void JNICALL
  177. Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
  178. jclass cls,
  179. jobject xgc,
  180. jint x,
  181. jint y,
  182. jint width,
  183. jint height,
  184. jintArray pixelArray) {
  185. XImage *image;
  186. jint *ary; /* Array of jints for sending pixel values back
  187. * to parent process.
  188. */
  189. Window rootWindow;
  190. AwtGraphicsConfigDataPtr adata;
  191. DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray);
  192. AWT_LOCK();
  193. /* avoid a lot of work for empty rectangles */
  194. if ((width * height) == 0) {
  195. AWT_UNLOCK();
  196. return;
  197. }
  198. DASSERT(width * height > 0); /* only allow positive size */
  199. adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
  200. DASSERT(adata != NULL);
  201. rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
  202. image = getWindowImage(awt_display, rootWindow, x, y, width, height);
  203. /* Array to use to crunch around the pixel values */
  204. ary = (jint *) malloc(width * height * sizeof (jint));
  205. if (ary == NULL) {
  206. JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
  207. XDestroyImage(image);
  208. AWT_UNLOCK();
  209. return;
  210. }
  211. /* convert to Java ARGB pixels */
  212. for (y = 0; y < height; y++) {
  213. for (x = 0; x < width; x++) {
  214. jint pixel = (jint) XGetPixel(image, x, y); /* Note ignore upper
  215. * 32-bits on 64-bit
  216. * OSes.
  217. */
  218. pixel |= 0xff000000; /* alpha - full opacity */
  219. ary[(y * width) + x] = pixel;
  220. }
  221. }
  222. (*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
  223. free(ary);
  224. XDestroyImage(image);
  225. AWT_UNLOCK();
  226. }
  227. JNIEXPORT void JNICALL
  228. Java_sun_awt_X11_XRobotPeer_keyPressImpl (JNIEnv *env,
  229. jclass cls,
  230. jint keycode) {
  231. AWT_LOCK();
  232. DTRACE_PRINTLN1("RobotPeer: keyPressImpl(%i)", keycode);
  233. XTestFakeKeyEvent(awt_display,
  234. XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
  235. True,
  236. CurrentTime);
  237. XSync(awt_display, False);
  238. AWT_UNLOCK();
  239. }
  240. JNIEXPORT void JNICALL
  241. Java_sun_awt_X11_XRobotPeer_keyReleaseImpl (JNIEnv *env,
  242. jclass cls,
  243. jint keycode) {
  244. AWT_LOCK();
  245. DTRACE_PRINTLN1("RobotPeer: keyReleaseImpl(%i)", keycode);
  246. XTestFakeKeyEvent(awt_display,
  247. XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
  248. False,
  249. CurrentTime);
  250. XSync(awt_display, False);
  251. AWT_UNLOCK();
  252. }
  253. JNIEXPORT void JNICALL
  254. Java_sun_awt_X11_XRobotPeer_mouseMoveImpl (JNIEnv *env,
  255. jclass cls,
  256. jobject xgc,
  257. jint root_x,
  258. jint root_y) {
  259. AwtGraphicsConfigDataPtr adata;
  260. AWT_LOCK();
  261. DTRACE_PRINTLN3("RobotPeer: mouseMoveImpl(%lx, %i, %i)", xgc, root_x, root_y);
  262. adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
  263. DASSERT(adata != NULL);
  264. XWarpPointer(awt_display, None, XRootWindow(awt_display, adata->awt_visInfo.screen), 0, 0, 0, 0, root_x, root_y);
  265. XSync(awt_display, False);
  266. AWT_UNLOCK();
  267. }
  268. /*
  269. * Function joining the code of mousePressImpl and mouseReleaseImpl
  270. */
  271. void mouseAction(JNIEnv *env,
  272. jclass cls,
  273. jint buttonMask,
  274. Bool isMousePress)
  275. {
  276. AWT_LOCK();
  277. DTRACE_PRINTLN1("RobotPeer: mouseAction(%i)", buttonMask);
  278. DTRACE_PRINTLN1("RobotPeer: mouseAction, press = %d", isMousePress);
  279. if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ||
  280. buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK )
  281. {
  282. XTestFakeButtonEvent(awt_display, 1, isMousePress, CurrentTime);
  283. }
  284. if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ||
  285. buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) &&
  286. (num_buttons >= 2)) {
  287. XTestFakeButtonEvent(awt_display, 2, isMousePress, CurrentTime);
  288. }
  289. if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ||
  290. buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) &&
  291. (num_buttons >= 3)) {
  292. XTestFakeButtonEvent(awt_display, 3, isMousePress, CurrentTime);
  293. }
  294. if (num_buttons > 3){
  295. int32_t i;
  296. int32_t button = 0;
  297. for (i = 3; i<num_buttons; i++){
  298. if ((buttonMask & masks[i])) {
  299. // arrays starts from zero index => +1
  300. // users wants to affect 4 or 5 button but they are assigned
  301. // to the wheel so => we have to shift it to the right by 2.
  302. button = i + 3;
  303. XTestFakeButtonEvent(awt_display, button, isMousePress, CurrentTime);
  304. }
  305. }
  306. }
  307. XSync(awt_display, False);
  308. AWT_UNLOCK();
  309. }
  310. JNIEXPORT void JNICALL
  311. Java_sun_awt_X11_XRobotPeer_mousePressImpl (JNIEnv *env,
  312. jclass cls,
  313. jint buttonMask) {
  314. mouseAction(env, cls, buttonMask, True);
  315. }
  316. JNIEXPORT void JNICALL
  317. Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl (JNIEnv *env,
  318. jclass cls,
  319. jint buttonMask) {
  320. mouseAction(env, cls, buttonMask, False);
  321. }
  322. JNIEXPORT void JNICALL
  323. Java_sun_awt_X11_XRobotPeer_mouseWheelImpl (JNIEnv *env,
  324. jclass cls,
  325. jint wheelAmt) {
  326. /* Mouse wheel is implemented as a button press of button 4 and 5, so it */
  327. /* probably could have been hacked into robot_mouseButtonEvent, but it's */
  328. /* cleaner to give it its own command type, in case the implementation */
  329. /* needs to be changed later. -bchristi, 6/20/01 */
  330. int32_t repeat = abs(wheelAmt);
  331. int32_t button = wheelAmt < 0 ? 4 : 5; /* wheel up: button 4 */
  332. /* wheel down: button 5 */
  333. int32_t loopIdx;
  334. AWT_LOCK();
  335. DTRACE_PRINTLN1("RobotPeer: mouseWheelImpl(%i)", wheelAmt);
  336. for (loopIdx = 0; loopIdx < repeat; loopIdx++) { /* do nothing for */
  337. /* wheelAmt == 0 */
  338. XTestFakeButtonEvent(awt_display, button, True, CurrentTime);
  339. XTestFakeButtonEvent(awt_display, button, False, CurrentTime);
  340. }
  341. XSync(awt_display, False);
  342. AWT_UNLOCK();
  343. }