jdk/src/solaris/classes/sun/awt/X11/XGlobalCursorManager.java
changeset 2 90ce3da70b43
child 439 3488710b02f8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XGlobalCursorManager.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.awt.X11;
+
+import java.awt.*;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import sun.awt.ComponentAccessor;
+
+import sun.awt.GlobalCursorManager;
+import sun.awt.SunToolkit;
+
+public final class XGlobalCursorManager extends GlobalCursorManager {
+
+    private static Field  field_pData;
+    private static Field  field_type;
+    private static Class  cursorClass;
+    private static Method method_setPData;
+    static {
+        cursorClass = java.awt.Cursor.class;
+        field_pData = SunToolkit.getField(cursorClass, "pData");
+        field_type  = SunToolkit.getField(cursorClass, "type");
+        method_setPData = SunToolkit.getMethod(cursorClass, "setPData", new Class[] {long.class});
+        if (field_pData == null || field_type == null || method_setPData == null) {
+            System.out.println("Unable to initialize XGlobalCursorManager: ");
+            Thread.dumpStack();
+
+        }
+    }
+
+
+    // cached nativeContainer
+    private WeakReference<Component> nativeContainer;
+
+
+    /**
+     * The XGlobalCursorManager is a singleton.
+     */
+    private static XGlobalCursorManager manager;
+
+
+    static GlobalCursorManager getCursorManager() {
+        if (manager == null) {
+            manager = new XGlobalCursorManager();
+        }
+        return manager;
+    }
+
+    /**
+     * Should be called in response to a native mouse enter or native mouse
+     * button released message. Should not be called during a mouse drag.
+     */
+    static void nativeUpdateCursor(Component heavy) {
+        XGlobalCursorManager.getCursorManager().updateCursorLater(heavy);
+    }
+
+
+    protected void setCursor(Component comp, Cursor cursor, boolean useCache) {
+        if (comp == null) {
+            return;
+        }
+
+        Cursor cur = useCache ? cursor : getCapableCursor(comp);
+
+        Component nc = null;
+        if (useCache) {
+            synchronized (this) {
+                nc = nativeContainer.get();
+            }
+        } else {
+            nc = getNativeContainer(comp);
+        }
+
+        if (nc != null) {
+            ComponentPeer nc_peer = ComponentAccessor.getPeer(nc);
+            if (nc_peer instanceof XComponentPeer) {
+                synchronized (this) {
+                    nativeContainer = new WeakReference<Component>(nc);
+                }
+
+                ((XComponentPeer)nc_peer).pSetCursor(cur);
+                // in case of grab we do for Swing we need to update keep cursor updated
+                // (we don't need this in case of AWT menus).  Window Manager consider
+                // the grabber as a current window and use its cursor.  So we need to
+                // change cursor on the grabber too.
+                updateGrabbedCursor(cur);
+            }
+        }
+    }
+
+    /**
+     * Updates cursor on the grabber if it is window peer (i.e. current grab is for
+     * Swing, not for AWT.
+     */
+    private static void updateGrabbedCursor(Cursor cur) {
+        XBaseWindow target = XAwtState.getGrabWindow();
+        if (target instanceof XWindowPeer) {
+            XWindowPeer grabber = (XWindowPeer) target;
+            grabber.pSetCursor(cur);
+        }
+    }
+
+    protected void updateCursorOutOfJava() {
+        // in case we have grabbed input for Swing we need to reset cursor
+        // when mouse pointer is out of any java toplevel.
+        // let's use default cursor for this.
+        updateGrabbedCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+    }
+
+    private Component getNativeContainer(Component comp) {
+        while (comp != null && ComponentAccessor.getPeer(comp) instanceof LightweightPeer) {
+            comp = ComponentAccessor.getParent_NoClientCode(comp);
+        }
+        return comp;
+    }
+
+    protected void getCursorPos(Point p) {
+
+        if (!((XToolkit)Toolkit.getDefaultToolkit()).getLastCursorPos(p)) {
+            XToolkit.awtLock();
+            try {
+                long display = XToolkit.getDisplay();
+                long root_window = XlibWrapper.RootWindow(display,
+                                                          XlibWrapper.DefaultScreen(display));
+
+                XlibWrapper.XQueryPointer(display, root_window,
+                                          XlibWrapper.larg1,
+                                          XlibWrapper.larg2,
+                                          XlibWrapper.larg3,
+                                          XlibWrapper.larg4,
+                                          XlibWrapper.larg5,
+                                          XlibWrapper.larg6,
+                                          XlibWrapper.larg7);
+
+                p.x = (int) XlibWrapper.unsafe.getInt(XlibWrapper.larg3);
+                p.y = (int) XlibWrapper.unsafe.getInt(XlibWrapper.larg4);
+            } finally {
+                XToolkit.awtUnlock();
+            }
+        }
+    }
+    protected  Component findHeavyweightUnderCursor() {
+        return XAwtState.getComponentMouseEntered();
+    }
+
+    /*
+     * two native methods to call corresponding methods in Container and
+     * Component
+     */
+    protected  Component findComponentAt(Container con, int x, int y) {
+        return con.findComponentAt(x,y);
+    }
+
+    protected  Point getLocationOnScreen(Component c) {
+        return c.getLocationOnScreen();
+    }
+
+    protected Component findHeavyweightUnderCursor(boolean useCache) {
+        return findHeavyweightUnderCursor();
+    }
+
+    private Cursor getCapableCursor(Component comp) {
+        Component c = comp;
+        while ((c != null) && !(c instanceof Window)
+               && ComponentAccessor.isEnabledImpl(c)
+               && ComponentAccessor.getVisible(c)
+               && ComponentAccessor.getPeer(c) != null)
+        {
+            c = ComponentAccessor.getParent_NoClientCode(c);
+        }
+        if (c instanceof Window) {
+            return (ComponentAccessor.isEnabledImpl(c)
+                    && ComponentAccessor.getVisible(c)
+                    && (ComponentAccessor.getPeer(c) != null)
+                    && ComponentAccessor.isEnabledImpl(comp))
+                   ?
+                    ComponentAccessor.getCursor_NoClientCode(comp)
+                   :
+                    Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
+        } else if (c == null) {
+            return null;
+        }
+        return getCapableCursor(ComponentAccessor.getParent_NoClientCode(c));
+    }
+
+    /* This methods needs to be called from within XToolkit.awtLock / XToolkit.awtUnlock section. */
+
+    static long getCursor(Cursor c) {
+
+        long pData = 0;
+        int type = 0;
+        try {
+            pData = field_pData.getLong(c);
+            type = field_type.getInt(c);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+
+        if (pData != 0) return pData;
+
+        int cursorType = 0;
+        switch (type) {
+          case Cursor.DEFAULT_CURSOR:
+              cursorType = XlibWrapper.XC_left_ptr;
+              break;
+          case Cursor.CROSSHAIR_CURSOR:
+              cursorType = XlibWrapper.XC_crosshair;
+              break;
+          case Cursor.TEXT_CURSOR:
+              cursorType = XlibWrapper.XC_xterm;
+              break;
+          case Cursor.WAIT_CURSOR:
+              cursorType = XlibWrapper.XC_watch;
+              break;
+          case Cursor.SW_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_bottom_left_corner;
+              break;
+          case Cursor.NW_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_top_left_corner;
+              break;
+          case Cursor.SE_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_bottom_right_corner;
+              break;
+          case Cursor.NE_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_top_right_corner;
+              break;
+          case Cursor.S_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_bottom_side;
+              break;
+          case Cursor.N_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_top_side;
+              break;
+          case Cursor.W_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_left_side;
+              break;
+          case Cursor.E_RESIZE_CURSOR:
+              cursorType = XlibWrapper.XC_right_side;
+              break;
+          case Cursor.HAND_CURSOR:
+              cursorType = XlibWrapper.XC_hand2;
+              break;
+          case Cursor.MOVE_CURSOR:
+              cursorType = XlibWrapper.XC_fleur;
+              break;
+        }
+
+        XToolkit.awtLock();
+        try {
+            pData =(long) XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(), cursorType);
+        }
+        finally {
+            XToolkit.awtUnlock();
+        }
+
+        setPData(c,pData);
+        return pData;
+    }
+
+
+    static void setPData(Cursor c, long pData) {
+        try {
+            method_setPData.invoke(c, pData);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+
+    }
+}