1 /*
2  * Copyright (c) 2003, 2014, 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 
getCursorManager()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      */
nativeUpdateCursor(Component heavy)59     static void nativeUpdateCursor(Component heavy) {
60         XGlobalCursorManager.getCursorManager().updateCursorLater(heavy);
61     }
62 
63 
setCursor(Component comp, Cursor cursor, boolean useCache)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      */
updateGrabbedCursor(Cursor cur)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 
updateCursorOutOfJava()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 
getCursorPos(Point p)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 = XlibWrapper.unsafe.getInt(XlibWrapper.larg3);
137                 p.y = XlibWrapper.unsafe.getInt(XlibWrapper.larg4);
138             } finally {
139                 XToolkit.awtUnlock();
140             }
141         }
142     }
findHeavyweightUnderCursor()143     protected  Component findHeavyweightUnderCursor() {
144         return XAwtState.getComponentMouseEntered();
145     }
146 
147     /*
148      * native method to call corresponding methods in Component
149      */
getLocationOnScreen(Component c)150     protected  Point getLocationOnScreen(Component c) {
151         return c.getLocationOnScreen();
152     }
153 
findHeavyweightUnderCursor(boolean useCache)154     protected Component findHeavyweightUnderCursor(boolean useCache) {
155         return findHeavyweightUnderCursor();
156     }
157 
getCapableCursor(Component comp)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 
getCursor(Cursor c)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 
setPData(Cursor c, long pData)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 }
271