001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Dmitry A. Durnev
019: * @version $Revision$
020: */package org.apache.harmony.awt.wtk.linux;
021:
022: import java.awt.AWTError;
023: import java.awt.Color;
024: import java.awt.Rectangle;
025: import java.awt.event.InputEvent;
026: import java.awt.image.BufferedImage;
027:
028: import org.apache.harmony.awt.gl.linux.XGraphicsConfiguration;
029: import org.apache.harmony.awt.gl.linux.XGraphicsDevice;
030: import org.apache.harmony.awt.gl.linux.XVolatileImage;
031: import org.apache.harmony.awt.internal.nls.Messages;
032: import org.apache.harmony.awt.wtk.NativeRobot;
033:
034: import org.apache.harmony.awt.nativebridge.Int32Pointer;
035: import org.apache.harmony.awt.nativebridge.Int8Pointer;
036: import org.apache.harmony.awt.nativebridge.NativeBridge;
037: import org.apache.harmony.awt.nativebridge.linux.X11;
038: import org.apache.harmony.awt.nativebridge.linux.X11Defs;
039:
040: /**
041: * XTestRobot
042: */
043: public class XTestRobot implements NativeRobot {
044: private static final int[] BTNS = { X11Defs.Button1,
045: X11Defs.Button2, X11Defs.Button3, X11Defs.Button4,
046: X11Defs.Button5, };
047: private final long AllPlanes;
048: private final int screen;
049: private final X11 x11 = X11.getInstance();
050: private final NativeBridge nb = NativeBridge.getInstance();
051: private final long dpy;
052: private final XGraphicsConfiguration gc;
053:
054: public XTestRobot(long display, XGraphicsDevice scrn) {
055: // get screen number
056: // from GraphicsDevice
057: screen = scrn.getScreen();
058: gc = (XGraphicsConfiguration) scrn.getDefaultConfiguration();
059: dpy = display;
060: AllPlanes = x11.XAllPlanes();
061: queryExtension();
062: }
063:
064: /**
065: * @see org.apache.harmony.awt.wtk.NativeRobot#createScreenCapture(java.awt.Rectangle)
066: */
067: public BufferedImage createScreenCapture(Rectangle screenRect) {
068: int w = screenRect.width;
069: int h = screenRect.height;
070: int fmt = X11Defs.ZPixmap;
071: long root = x11.XRootWindow(dpy, screen);
072: X11.XImage ximg = createXImage(w, h);
073: if (ximg == null) {
074: return null;
075: }
076:
077: ximg = x11.XGetSubImage(dpy, root, screenRect.x, screenRect.y,
078: w, h, AllPlanes, fmt, ximg, 0, 0);
079: BufferedImage bufImg = XVolatileImage.biFromXImage(ximg, gc);
080: x11.XDestroyImage(ximg);
081:
082: return bufImg;
083: }
084:
085: /**
086: * @see org.apache.harmony.awt.wtk.NativeRobot#getPixel(int, int)
087: */
088: public Color getPixel(int x, int y) {
089: Rectangle rect = new Rectangle(x, y, 1, 1);
090: X11.XImage ximg = getScreenImage(rect);
091: long pixel = ximg.get_f().get_pixel(ximg, 0, 0);
092: // this only works if window containing (x, y)
093: // point uses default color map:
094: // ideally we should find window at (x,y)
095: // and take its own color map
096: long cmap = x11.XDefaultColormap(dpy, screen);
097: return getColor(cmap, pixel);
098: }
099:
100: /**
101: * @see org.apache.harmony.awt.wtk.NativeRobot#keyEvent(int, boolean)
102: */
103: public void keyEvent(int keycode, boolean press) {
104: int xKeySym = KeyCodeTranslator.VK2XK(keycode);
105: if (xKeySym == X11Defs.NoSymbol) {
106: // awt.11=Invalid key code
107: throw new IllegalArgumentException(Messages
108: .getString("awt.11")); //$NON-NLS-1$
109: }
110: int xKeyCode = x11.XKeysymToKeycode(dpy, xKeySym);
111: x11.XTestFakeKeyEvent(dpy, xKeyCode, getBool(press),
112: X11Defs.CurrentTime);
113: x11.XFlush(dpy);
114:
115: }
116:
117: /**
118: * @see org.apache.harmony.awt.wtk.NativeRobot#mouseButton(int, boolean)
119: */
120: public void mouseButton(int buttons, boolean press) {
121: int isPress = (getBool(press));
122: if ((buttons & InputEvent.BUTTON1_MASK) != 0) {
123: mouseButton(BTNS[0], isPress);
124: }
125: if ((buttons & InputEvent.BUTTON2_MASK) != 0) {
126: mouseButton(BTNS[1], isPress);
127: }
128: if ((buttons & InputEvent.BUTTON3_MASK) != 0) {
129: mouseButton(BTNS[2], isPress);
130: }
131: x11.XFlush(dpy);
132:
133: }
134:
135: /**
136: * @see org.apache.harmony.awt.wtk.NativeRobot#mouseMove(int, int)
137: */
138: public void mouseMove(int x, int y) {
139: x11
140: .XTestFakeMotionEvent(dpy, screen, x, y,
141: X11Defs.CurrentTime);
142: x11.XFlush(dpy);
143:
144: }
145:
146: /**
147: * @see org.apache.harmony.awt.wtk.NativeRobot#mouseWheel(int)
148: */
149: public void mouseWheel(int wheelAmt) {
150: int btn = (BTNS[wheelAmt > 0 ? 4 : 3]);
151: mouseButton(btn, X11Defs.ButtonPress);
152: mouseButton(btn, X11Defs.ButtonRelease);
153: x11.XFlush(dpy);
154:
155: }
156:
157: private void queryExtension() {
158: Int32Pointer dummyPtr = nb.createInt32Pointer(1, false);
159: Int32Pointer majorPtr = nb.createInt32Pointer(1, false);
160: Int32Pointer minorPtr = nb.createInt32Pointer(1, false);
161: int res = 0;
162: res = x11.XTestQueryExtension(dpy, dummyPtr, dummyPtr,
163: majorPtr, minorPtr);
164: if (res != X11Defs.True) {
165: // awt.12=XTest is not supported by your X server\!
166: throw new AWTError(Messages.getString("awt.12")); //$NON-NLS-1$
167: }
168: }
169:
170: private void mouseButton(int btn, int isPress) {
171: int res = x11.XTestFakeButtonEvent(dpy, btn, isPress,
172: X11Defs.CurrentTime);
173: }
174:
175: private X11.XImage getScreenImage(Rectangle r) {
176: long root = x11.XRootWindow(dpy, screen);
177: long ptr = x11.XGetImage(dpy, root, r.x, r.y, r.width,
178: r.height, AllPlanes, X11Defs.ZPixmap);
179: return x11.createXImage(ptr);
180: }
181:
182: private Color getColor(long cmap, long pixel) {
183: X11.XColor xcolor = x11.createXColor(false);
184: xcolor.set_pixel(pixel);
185: x11.XQueryColor(dpy, cmap, xcolor);
186: int r = xcolor.get_red() & 0xFF;
187: int g = xcolor.get_green() & 0xFF;
188: int b = xcolor.get_blue() & 0xFF;
189: return new Color(r, g, b);
190: }
191:
192: private int getBool(boolean b) {
193: return (b ? X11Defs.True : X11Defs.False);
194: }
195:
196: private X11.XImage createXImage(int w, int h) {
197:
198: X11.Visual vis = x11.createVisual(x11.XDefaultVisual(dpy,
199: screen));
200:
201: int size = w * h;
202: int depth = x11.XDefaultDepth(dpy, screen);
203: // MUST use native(not Java!) memory here:
204: Int8Pointer dataPtr = nb.createInt8Pointer(size * 4, true);
205: X11.XImage ximg = x11.XCreateImage(dpy, vis, depth,
206: X11Defs.ZPixmap, 0, dataPtr, w, h, 32, 0);
207:
208: int order = X11Defs.LSBFirst;
209: ximg.set_byte_order(order);
210: return ximg;
211: }
212:
213: }
|