1 /* 2 * Copyright (c) 2003, 2013, 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 26 package sun.awt.X11; 27 28 import java.awt.*; 29 import java.awt.peer.ComponentPeer; 30 import java.lang.ref.WeakReference; 31 import sun.awt.AWTAccessor; 32 33 import sun.awt.GlobalCursorManager; 34 import sun.awt.SunToolkit; 35 36 public final class XGlobalCursorManager extends GlobalCursorManager { 37 38 // cached nativeContainer 39 private WeakReference<Component> nativeContainer; 40 41 42 /** 43 * The XGlobalCursorManager is a singleton. 44 */ 45 private static XGlobalCursorManager manager; 46 47 48 static GlobalCursorManager getCursorManager() { 49 if (manager == null) { 50 manager = new XGlobalCursorManager(); 51 } 52 return manager; 53 } 54 55 /** 56 * Should be called in response to a native mouse enter or native mouse 57 * button released message. Should not be called during a mouse drag. 58 */ 59 static void nativeUpdateCursor(Component heavy) { 60 XGlobalCursorManager.getCursorManager().updateCursorLater(heavy); 61 } 62 63 64 protected void setCursor(Component comp, Cursor cursor, boolean useCache) { 65 if (comp == null) { 66 return; 67 } 68 69 Cursor cur = useCache ? cursor : getCapableCursor(comp); 70 71 Component nc = null; 72 if (useCache) { 73 synchronized (this) { 74 nc = nativeContainer.get(); 75 } 76 } else { 77 nc = SunToolkit.getHeavyweightComponent(comp); 78 } 79 80 if (nc != null) { 81 ComponentPeer nc_peer = AWTAccessor.getComponentAccessor().getPeer(nc); 82 if (nc_peer instanceof XComponentPeer) { 83 synchronized (this) { 84 nativeContainer = new WeakReference<Component>(nc); 85 } 86 87 //6431076. A subcomponents (a XTextArea in particular) 88 //may want to override the cursor over some of their parts. 89 ((XComponentPeer)nc_peer).pSetCursor(cur, false); 90 // in case of grab we do for Swing we need to update keep cursor updated 91 // (we don't need this in case of AWT menus). Window Manager consider 92 // the grabber as a current window and use its cursor. So we need to 93 // change cursor on the grabber too. 94 updateGrabbedCursor(cur); 95 } 96 } 97 } 98 99 /** 100 * Updates cursor on the grabber if it is window peer (i.e. current grab is for 101 * Swing, not for AWT. 102 */ 103 private static void updateGrabbedCursor(Cursor cur) { 104 XBaseWindow target = XAwtState.getGrabWindow(); 105 if (target instanceof XWindowPeer) { 106 XWindowPeer grabber = (XWindowPeer) target; 107 grabber.pSetCursor(cur); 108 } 109 } 110 111 protected void updateCursorOutOfJava() { 112 // in case we have grabbed input for Swing we need to reset cursor 113 // when mouse pointer is out of any java toplevel. 114 // let's use default cursor for this. 115 updateGrabbedCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 116 } 117 118 protected void getCursorPos(Point p) { 119 120 if (!((XToolkit)Toolkit.getDefaultToolkit()).getLastCursorPos(p)) { 121 XToolkit.awtLock(); 122 try { 123 long display = XToolkit.getDisplay(); 124 long root_window = XlibWrapper.RootWindow(display, 125 XlibWrapper.DefaultScreen(display)); 126 127 XlibWrapper.XQueryPointer(display, root_window, 128 XlibWrapper.larg1, 129 XlibWrapper.larg2, 130 XlibWrapper.larg3, 131 XlibWrapper.larg4, 132 XlibWrapper.larg5, 133 XlibWrapper.larg6, 134 XlibWrapper.larg7); 135 136 p.x = (int) XlibWrapper.unsafe.getInt(XlibWrapper.larg3); 137 p.y = (int) XlibWrapper.unsafe.getInt(XlibWrapper.larg4); 138 } finally { 139 XToolkit.awtUnlock(); 140 } 141 } 142 } 143 protected Component findHeavyweightUnderCursor() { 144 return XAwtState.getComponentMouseEntered(); 145 } 146 147 /* 148 * native method to call corresponding methods in Component 149 */ 150 protected Point getLocationOnScreen(Component c) { 151 return c.getLocationOnScreen(); 152 } 153 154 protected Component findHeavyweightUnderCursor(boolean useCache) { 155 return findHeavyweightUnderCursor(); 156 } 157 158 private Cursor getCapableCursor(Component comp) { 159 AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor(); 160 161 Component c = comp; 162 while ((c != null) && !(c instanceof Window) 163 && compAccessor.isEnabled(c) 164 && compAccessor.isVisible(c) 165 && compAccessor.isDisplayable(c)) 166 { 167 c = compAccessor.getParent(c); 168 } 169 if (c instanceof Window) { 170 return (compAccessor.isEnabled(c) 171 && compAccessor.isVisible(c) 172 && compAccessor.isDisplayable(c) 173 && compAccessor.isEnabled(comp)) 174 ? 175 compAccessor.getCursor(comp) 176 : 177 Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); 178 } else if (c == null) { 179 return null; 180 } 181 return getCapableCursor(compAccessor.getParent(c)); 182 } 183 184 /* This methods needs to be called from within XToolkit.awtLock / XToolkit.awtUnlock section. */ 185 186 static long getCursor(Cursor c) { 187 188 long pData = 0; 189 int type = 0; 190 try { 191 pData = AWTAccessor.getCursorAccessor().getPData(c); 192 type = AWTAccessor.getCursorAccessor().getType(c); 193 } 194 catch (Exception e) 195 { 196 e.printStackTrace(); 197 } 198 199 if (pData != 0) return pData; 200 201 int cursorType = 0; 202 switch (type) { 203 case Cursor.DEFAULT_CURSOR: 204 cursorType = XCursorFontConstants.XC_left_ptr; 205 break; 206 case Cursor.CROSSHAIR_CURSOR: 207 cursorType = XCursorFontConstants.XC_crosshair; 208 break; 209 case Cursor.TEXT_CURSOR: 210 cursorType = XCursorFontConstants.XC_xterm; 211 break; 212 case Cursor.WAIT_CURSOR: 213 cursorType = XCursorFontConstants.XC_watch; 214 break; 215 case Cursor.SW_RESIZE_CURSOR: 216 cursorType = XCursorFontConstants.XC_bottom_left_corner; 217 break; 218 case Cursor.NW_RESIZE_CURSOR: 219 cursorType = XCursorFontConstants.XC_top_left_corner; 220 break; 221 case Cursor.SE_RESIZE_CURSOR: 222 cursorType = XCursorFontConstants.XC_bottom_right_corner; 223 break; 224 case Cursor.NE_RESIZE_CURSOR: 225 cursorType = XCursorFontConstants.XC_top_right_corner; 226 break; 227 case Cursor.S_RESIZE_CURSOR: 228 cursorType = XCursorFontConstants.XC_bottom_side; 229 break; 230 case Cursor.N_RESIZE_CURSOR: 231 cursorType = XCursorFontConstants.XC_top_side; 232 break; 233 case Cursor.W_RESIZE_CURSOR: 234 cursorType = XCursorFontConstants.XC_left_side; 235 break; 236 case Cursor.E_RESIZE_CURSOR: 237 cursorType = XCursorFontConstants.XC_right_side; 238 break; 239 case Cursor.HAND_CURSOR: 240 cursorType = XCursorFontConstants.XC_hand2; 241 break; 242 case Cursor.MOVE_CURSOR: 243 cursorType = XCursorFontConstants.XC_fleur; 244 break; 245 } 246 247 XToolkit.awtLock(); 248 try { 249 pData =(long) XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(), cursorType); 250 } 251 finally { 252 XToolkit.awtUnlock(); 253 } 254 255 setPData(c,pData); 256 return pData; 257 } 258 259 260 static void setPData(Cursor c, long pData) { 261 try { 262 AWTAccessor.getCursorAccessor().setPData(c, pData); 263 } 264 catch (Exception e) 265 { 266 e.printStackTrace(); 267 } 268 269 } 270 }