001: /*
002: * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.X11;
027:
028: import java.awt.*;
029: import java.awt.peer.ComponentPeer;
030: import java.awt.peer.LightweightPeer;
031: import java.lang.ref.WeakReference;
032: import java.lang.reflect.Field;
033: import java.lang.reflect.Method;
034: import sun.awt.ComponentAccessor;
035:
036: import sun.awt.GlobalCursorManager;
037: import sun.awt.SunToolkit;
038:
039: public final class XGlobalCursorManager extends GlobalCursorManager {
040:
041: private static Field field_pData;
042: private static Field field_type;
043: private static Class cursorClass;
044: private static Method method_setPData;
045: static {
046: cursorClass = java.awt.Cursor.class;
047: field_pData = SunToolkit.getField(cursorClass, "pData");
048: field_type = SunToolkit.getField(cursorClass, "type");
049: method_setPData = SunToolkit.getMethod(cursorClass, "setPData",
050: new Class[] { long.class });
051: if (field_pData == null || field_type == null
052: || method_setPData == null) {
053: System.out
054: .println("Unable to initialize XGlobalCursorManager: ");
055: Thread.dumpStack();
056:
057: }
058: }
059:
060: // cached nativeContainer
061: private WeakReference<Component> nativeContainer;
062:
063: /**
064: * The XGlobalCursorManager is a singleton.
065: */
066: private static XGlobalCursorManager manager;
067:
068: static GlobalCursorManager getCursorManager() {
069: if (manager == null) {
070: manager = new XGlobalCursorManager();
071: }
072: return manager;
073: }
074:
075: /**
076: * Should be called in response to a native mouse enter or native mouse
077: * button released message. Should not be called during a mouse drag.
078: */
079: static void nativeUpdateCursor(Component heavy) {
080: XGlobalCursorManager.getCursorManager()
081: .updateCursorLater(heavy);
082: }
083:
084: protected void setCursor(Component comp, Cursor cursor,
085: boolean useCache) {
086: if (comp == null) {
087: return;
088: }
089:
090: Cursor cur = useCache ? cursor : getCapableCursor(comp);
091:
092: Component nc = null;
093: if (useCache) {
094: synchronized (this ) {
095: nc = nativeContainer.get();
096: }
097: } else {
098: nc = getNativeContainer(comp);
099: }
100:
101: if (nc != null) {
102: ComponentPeer nc_peer = ComponentAccessor.getPeer(nc);
103: if (nc_peer instanceof XComponentPeer) {
104: synchronized (this ) {
105: nativeContainer = new WeakReference<Component>(nc);
106: }
107:
108: ((XComponentPeer) nc_peer).pSetCursor(cur);
109: // in case of grab we do for Swing we need to update keep cursor updated
110: // (we don't need this in case of AWT menus). Window Manager consider
111: // the grabber as a current window and use its cursor. So we need to
112: // change cursor on the grabber too.
113: updateGrabbedCursor(cur);
114: }
115: }
116: }
117:
118: /**
119: * Updates cursor on the grabber if it is window peer (i.e. current grab is for
120: * Swing, not for AWT.
121: */
122: private static void updateGrabbedCursor(Cursor cur) {
123: XBaseWindow target = XAwtState.getGrabWindow();
124: if (target instanceof XWindowPeer) {
125: XWindowPeer grabber = (XWindowPeer) target;
126: grabber.pSetCursor(cur);
127: }
128: }
129:
130: protected void updateCursorOutOfJava() {
131: // in case we have grabbed input for Swing we need to reset cursor
132: // when mouse pointer is out of any java toplevel.
133: // let's use default cursor for this.
134: updateGrabbedCursor(Cursor
135: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
136: }
137:
138: private Component getNativeContainer(Component comp) {
139: while (comp != null
140: && ComponentAccessor.getPeer(comp) instanceof LightweightPeer) {
141: comp = ComponentAccessor.getParent_NoClientCode(comp);
142: }
143: return comp;
144: }
145:
146: protected void getCursorPos(Point p) {
147:
148: if (!((XToolkit) Toolkit.getDefaultToolkit())
149: .getLastCursorPos(p)) {
150: XToolkit.awtLock();
151: try {
152: long display = XToolkit.getDisplay();
153: long root_window = XlibWrapper.RootWindow(display,
154: XlibWrapper.DefaultScreen(display));
155:
156: XlibWrapper.XQueryPointer(display, root_window,
157: XlibWrapper.larg1, XlibWrapper.larg2,
158: XlibWrapper.larg3, XlibWrapper.larg4,
159: XlibWrapper.larg5, XlibWrapper.larg6,
160: XlibWrapper.larg7);
161:
162: p.x = (int) XlibWrapper.unsafe
163: .getInt(XlibWrapper.larg3);
164: p.y = (int) XlibWrapper.unsafe
165: .getInt(XlibWrapper.larg4);
166: } finally {
167: XToolkit.awtUnlock();
168: }
169: }
170: }
171:
172: protected Component findHeavyweightUnderCursor() {
173: return XAwtState.getComponentMouseEntered();
174: }
175:
176: /*
177: * two native methods to call corresponding methods in Container and
178: * Component
179: */
180: protected Component findComponentAt(Container con, int x, int y) {
181: return con.findComponentAt(x, y);
182: }
183:
184: protected Point getLocationOnScreen(Component c) {
185: return c.getLocationOnScreen();
186: }
187:
188: protected Component findHeavyweightUnderCursor(boolean useCache) {
189: return findHeavyweightUnderCursor();
190: }
191:
192: private Cursor getCapableCursor(Component comp) {
193: Component c = comp;
194: while ((c != null) && !(c instanceof Window)
195: && ComponentAccessor.isEnabledImpl(c)
196: && ComponentAccessor.getVisible(c)
197: && ComponentAccessor.getPeer(c) != null) {
198: c = ComponentAccessor.getParent_NoClientCode(c);
199: }
200: if (c instanceof Window) {
201: return (ComponentAccessor.isEnabledImpl(c)
202: && ComponentAccessor.getVisible(c)
203: && (ComponentAccessor.getPeer(c) != null) && ComponentAccessor
204: .isEnabledImpl(comp)) ? ComponentAccessor
205: .getCursor_NoClientCode(comp) : Cursor
206: .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
207: } else if (c == null) {
208: return null;
209: }
210: return getCapableCursor(ComponentAccessor
211: .getParent_NoClientCode(c));
212: }
213:
214: /* This methods needs to be called from within XToolkit.awtLock / XToolkit.awtUnlock section. */
215:
216: static long getCursor(Cursor c) {
217:
218: long pData = 0;
219: int type = 0;
220: try {
221: pData = field_pData.getLong(c);
222: type = field_type.getInt(c);
223: } catch (Exception e) {
224: e.printStackTrace();
225: }
226:
227: if (pData != 0)
228: return pData;
229:
230: int cursorType = 0;
231: switch (type) {
232: case Cursor.DEFAULT_CURSOR:
233: cursorType = XlibWrapper.XC_left_ptr;
234: break;
235: case Cursor.CROSSHAIR_CURSOR:
236: cursorType = XlibWrapper.XC_crosshair;
237: break;
238: case Cursor.TEXT_CURSOR:
239: cursorType = XlibWrapper.XC_xterm;
240: break;
241: case Cursor.WAIT_CURSOR:
242: cursorType = XlibWrapper.XC_watch;
243: break;
244: case Cursor.SW_RESIZE_CURSOR:
245: cursorType = XlibWrapper.XC_bottom_left_corner;
246: break;
247: case Cursor.NW_RESIZE_CURSOR:
248: cursorType = XlibWrapper.XC_top_left_corner;
249: break;
250: case Cursor.SE_RESIZE_CURSOR:
251: cursorType = XlibWrapper.XC_bottom_right_corner;
252: break;
253: case Cursor.NE_RESIZE_CURSOR:
254: cursorType = XlibWrapper.XC_top_right_corner;
255: break;
256: case Cursor.S_RESIZE_CURSOR:
257: cursorType = XlibWrapper.XC_bottom_side;
258: break;
259: case Cursor.N_RESIZE_CURSOR:
260: cursorType = XlibWrapper.XC_top_side;
261: break;
262: case Cursor.W_RESIZE_CURSOR:
263: cursorType = XlibWrapper.XC_left_side;
264: break;
265: case Cursor.E_RESIZE_CURSOR:
266: cursorType = XlibWrapper.XC_right_side;
267: break;
268: case Cursor.HAND_CURSOR:
269: cursorType = XlibWrapper.XC_hand2;
270: break;
271: case Cursor.MOVE_CURSOR:
272: cursorType = XlibWrapper.XC_fleur;
273: break;
274: }
275:
276: XToolkit.awtLock();
277: try {
278: pData = (long) XlibWrapper.XCreateFontCursor(XToolkit
279: .getDisplay(), cursorType);
280: } finally {
281: XToolkit.awtUnlock();
282: }
283:
284: setPData(c, pData);
285: return pData;
286: }
287:
288: static void setPData(Cursor c, long pData) {
289: try {
290: method_setPData.invoke(c, pData);
291: } catch (Exception e) {
292: e.printStackTrace();
293: }
294:
295: }
296: }
|