diff --git a/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/src/macosx/classes/sun/lwawt/LWComponentPeer.java index 0f81d75472bc40155607704badc407726c498b6b..86f1f84b131f1a35eb3e0db590b25ece97648a36 100644 --- a/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -616,6 +616,17 @@ public abstract class LWComponentPeer windowLocation.y + locationInWindow.y); } + /** + * Returns the cursor of the peer, which is cursor of the target by default, + * but peer can override this behavior. + * + * @param p Point relative to the peer. + * @return Cursor of the peer or null if default cursor should be used. + */ + protected Cursor getCursor(final Point p) { + return getTarget().getCursor(); + } + @Override public void setBackground(final Color c) { final Color oldBg = getBackground(); diff --git a/src/macosx/classes/sun/lwawt/LWCursorManager.java b/src/macosx/classes/sun/lwawt/LWCursorManager.java index 62de104be01635ad745b4d6b234aafcd1dc613c7..1c34353c7b9f136392a324c804419a006887f963 100644 --- a/src/macosx/classes/sun/lwawt/LWCursorManager.java +++ b/src/macosx/classes/sun/lwawt/LWCursorManager.java @@ -36,32 +36,34 @@ import sun.awt.SunToolkit; public abstract class LWCursorManager { - // A flag to indicate if the update is scheduled, so we don't - // process it twice - private AtomicBoolean updatePending = new AtomicBoolean(false); + /** + * A flag to indicate if the update is scheduled, so we don't process it + * twice. + */ + private final AtomicBoolean updatePending = new AtomicBoolean(false); protected LWCursorManager() { } - /* + /** * Sets the cursor to correspond the component currently under mouse. * * This method should not be executed on the toolkit thread as it * calls to user code (e.g. Container.findComponentAt). */ - public void updateCursor() { + public final void updateCursor() { updatePending.set(false); updateCursorImpl(); } - /* + /** * Schedules updating the cursor on the corresponding event dispatch * thread for the given window. * * This method is called on the toolkit thread as a result of a * native update cursor request (e.g. WM_SETCURSOR on Windows). */ - public void updateCursorLater(LWWindowPeer window) { + public final void updateCursorLater(final LWWindowPeer window) { if (updatePending.compareAndSet(false, true)) { Runnable r = new Runnable() { @Override @@ -74,45 +76,58 @@ public abstract class LWCursorManager { } private void updateCursorImpl() { - LWWindowPeer windowUnderCursor = LWWindowPeer.getWindowUnderCursor(); - Point cursorPos = getCursorPosition(); - LWComponentPeer componentUnderCursor = null; - // TODO: it's possible to get the component under cursor directly as - // it's stored in LWWindowPee anyway (lastMouseEventPeer) - if (windowUnderCursor != null) { - componentUnderCursor = windowUnderCursor.findPeerAt(cursorPos.x, cursorPos.y); + final Point cursorPos = getCursorPosition(); + final Component c = findComponent(cursorPos); + final Cursor cursor; + final Object peer = LWToolkit.targetToPeer(c); + if (peer instanceof LWComponentPeer) { + final LWComponentPeer lwpeer = (LWComponentPeer) peer; + final Point p = lwpeer.getLocationOnScreen(); + cursor = lwpeer.getCursor(new Point(cursorPos.x - p.x, + cursorPos.y - p.y)); + } else { + cursor = (c != null) ? c.getCursor() : null; } - Cursor cursor = null; - if (componentUnderCursor != null) { - Component c = componentUnderCursor.getTarget(); + // TODO: default cursor for modal blocked windows + setCursor(cursor); + } + + /** + * Returns the first visible, enabled and showing component under cursor. + * + * @param cursorPos Current cursor position. + * @return Component + */ + private static final Component findComponent(final Point cursorPos) { + final LWComponentPeer peer = LWWindowPeer.getPeerUnderCursor(); + Component c = null; + if (peer != null) { + c = peer.getTarget(); if (c instanceof Container) { - Point p = componentUnderCursor.getLocationOnScreen(); - c = ((Container)c).findComponentAt(cursorPos.x - p.x, cursorPos.y - p.y); + final Point p = peer.getLocationOnScreen(); + c = ((Container) c).findComponentAt(cursorPos.x - p.x, + cursorPos.y - p.y); } - // Traverse up to the first visible, enabled and showing component while (c != null) { if (c.isVisible() && c.isEnabled() && (c.getPeer() != null)) { break; } c = c.getParent(); } - if (c != null) { - cursor = c.getCursor(); - } } - // TODO: default cursor for modal blocked windows - setCursor(windowUnderCursor, cursor); + return c; } - /* + /** * Returns the current cursor position. */ // TODO: make it public to reuse for MouseInfo protected abstract Point getCursorPosition(); - /* - * Sets a cursor. The cursor can be null if the mouse is not over a Java window. + /** + * Sets a cursor. The cursor can be null if the mouse is not over a Java + * window. + * @param cursor the new {@code Cursor}. */ - protected abstract void setCursor(LWWindowPeer windowUnderCursor, Cursor cursor); - + protected abstract void setCursor(Cursor cursor); } diff --git a/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java b/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java index a7a214f522d7fe77ae985a80f9e6bc008feed42e..e71ee173c508745b3c9d657966cfe46d011080c2 100644 --- a/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java +++ b/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java @@ -27,6 +27,7 @@ package sun.lwawt; import java.awt.Component; +import java.awt.Cursor; import java.awt.Dimension; import java.awt.Point; import java.awt.TextArea; @@ -71,6 +72,15 @@ final class LWTextAreaPeer return getDelegate().getView(); } + @Override + protected Cursor getCursor(final Point p) { + final boolean isContains; + synchronized (getDelegateLock()) { + isContains = getDelegate().getViewport().getBounds().contains(p); + } + return isContains ? super.getCursor(p) : null; + } + @Override protected Component getDelegateFocusOwner() { return getTextComponent(); diff --git a/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 3b9ee106e758a3997ff9673a5ddb70b7cc1a41c4..535a89be9c2d447333f5213b9396898b1d54ebc6 100644 --- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -784,9 +784,8 @@ public class LWWindowPeer } mouseClickButtons &= ~eventButtonMask; } - - notifyUpdateCursor(); } + notifyUpdateCursor(); } public void dispatchMouseWheelEvent(long when, int x, int y, int modifiers, @@ -1057,6 +1056,10 @@ public class LWWindowPeer return lastMouseEventPeer != null ? lastMouseEventPeer.getWindowPeerOrSelf() : null; } + public static LWComponentPeer getPeerUnderCursor() { + return lastMouseEventPeer; + } + public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { if (focusLog.isLoggable(PlatformLogger.FINE)) { focusLog.fine("requesting native focus to " + this); diff --git a/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java b/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java index cc4cd355d94a3ec15222efafad7c44a68576d3d5..b17618452ace759dc641af73e427b191cb399e20 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java +++ b/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java @@ -25,24 +25,26 @@ package sun.lwawt.macosx; -import java.awt.*; +import sun.lwawt.LWCursorManager; + +import java.awt.Cursor; +import java.awt.Point; import java.awt.geom.Point2D; -import sun.lwawt.*; +final class CCursorManager extends LWCursorManager { -public class CCursorManager extends LWCursorManager { private static native Point2D nativeGetCursorPosition(); private static native void nativeSetBuiltInCursor(final int type, final String name); private static native void nativeSetCustomCursor(final long imgPtr, final double x, final double y); private static final int NAMED_CURSOR = -1; - private final static CCursorManager theInstance = new CCursorManager(); + private static final CCursorManager theInstance = new CCursorManager(); public static CCursorManager getInstance() { return theInstance; } - Cursor currentCursor; + private volatile Cursor currentCursor; private CCursorManager() { } @@ -62,8 +64,11 @@ public class CCursorManager extends LWCursorManager { } @Override - protected void setCursor(final LWWindowPeer windowUnderCursor, final Cursor cursor) { - if (cursor == currentCursor) return; + protected void setCursor(final Cursor cursor) { + if (cursor == currentCursor) { + return; + } + currentCursor = cursor; if (cursor == null) { nativeSetBuiltInCursor(Cursor.DEFAULT_CURSOR, null); @@ -71,10 +76,12 @@ public class CCursorManager extends LWCursorManager { } if (cursor instanceof CCustomCursor) { - final CCustomCursor customCursor = ((CCustomCursor)cursor); + final CCustomCursor customCursor = (CCustomCursor) cursor; final long imagePtr = customCursor.getImageData(); - final Point hotSpot = customCursor.getHotSpot(); - if(imagePtr != 0L) nativeSetCustomCursor(imagePtr, hotSpot.x, hotSpot.y); + if (imagePtr != 0L) { + final Point hotSpot = customCursor.getHotSpot(); + nativeSetCustomCursor(imagePtr, hotSpot.x, hotSpot.y); + } return; } @@ -94,13 +101,6 @@ public class CCursorManager extends LWCursorManager { throw new RuntimeException("Unimplemented"); } - static long getNativeWindow(final LWWindowPeer window) { - if (window == null) return 0; - final CPlatformWindow platformWindow = (CPlatformWindow)window.getPlatformWindow(); - if (platformWindow == null) return 0; - return platformWindow.getNSWindowPtr(); - } - // package private methods to handle cursor change during drag-and-drop private boolean isDragging = false; private Point dragPos = null; @@ -109,9 +109,7 @@ public class CCursorManager extends LWCursorManager { if (isDragging) { throw new RuntimeException("Invalid Drag state in CCursorManager!"); } - isDragging = true; - dragPos = new Point(x, y); }