From 58756bbd1d1fd63bb84dbfe2d6419d63de2da7ba Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sun, 5 Jan 2014 18:21:26 +0100
Subject: Bug 935: NEWT PointerIcon/Visibility: Perform OffscreenLayerSurface
 delegation _always_ in common WindowImpl ; Workaround for Windows+Applet
 issue.

Perform OffscreenLayerSurface delegation _always_ in common WindowImpl

Instead of performing OffscreenLayerSurface task on OSX's WindowDriver implementation,
use generic implementation in WindowImpl for all platform exposing same behavior.

ReparentAction takes care of reset/setup of PointerIcon/Visibility states.

+++

This is also a workaround for Windows+Applet issue,
where the PointerIcon gets periodically overridden
by the AWT Component's icon.
---
 src/newt/classes/jogamp/newt/WindowImpl.java       | 162 ++++++++++++++++-----
 .../jogamp/newt/driver/macosx/WindowDriver.java    |  34 +----
 2 files changed, 127 insertions(+), 69 deletions(-)

(limited to 'src/newt/classes')

diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 8d9fb8d7e..50f30f04d 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -34,56 +34,59 @@
 
 package jogamp.newt;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.CapabilitiesChooser;
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.OffscreenLayerSurface;
+import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.nativewindow.SurfaceUpdatedHelper;
 
 import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.IOUtil;
 import com.jogamp.common.util.IntBitfield;
 import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.Display;
 import com.jogamp.newt.Display.PointerIcon;
 import com.jogamp.newt.MonitorDevice;
 import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Display;
 import com.jogamp.newt.Screen;
 import com.jogamp.newt.Window;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
 import com.jogamp.newt.event.DoubleTapScrollGesture;
 import com.jogamp.newt.event.GestureHandler;
 import com.jogamp.newt.event.InputEvent;
 import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.event.KeyListener;
 import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
 import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseEvent.PointerType;
 import com.jogamp.newt.event.MouseListener;
 import com.jogamp.newt.event.NEWTEvent;
 import com.jogamp.newt.event.NEWTEventConsumer;
-import com.jogamp.newt.event.MonitorModeListener;
 import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.event.WindowListener;
 import com.jogamp.newt.event.WindowUpdateEvent;
-import com.jogamp.newt.event.MouseEvent.PointerType;
-
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.CapabilitiesChooser;
-import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindow;
-import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
-import javax.media.nativewindow.SurfaceUpdatedListener;
-import javax.media.nativewindow.WindowClosingProtocol;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.Insets;
-import javax.media.nativewindow.util.InsetsImmutable;
-import javax.media.nativewindow.util.Point;
-import javax.media.nativewindow.util.Rectangle;
-import javax.media.nativewindow.util.RectangleImmutable;
-
-import jogamp.nativewindow.SurfaceUpdatedHelper;
 
 public abstract class WindowImpl implements Window, NEWTEventConsumer
 {
@@ -171,7 +174,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     private String title = "Newt Window";
     private boolean undecorated = false;
     private boolean alwaysOnTop = false;
-    private PointerIcon pointerIcon = null;
+    private PointerIconImpl pointerIcon = null;
     private boolean pointerVisible = true;
     private boolean pointerConfined = false;
     private LifecycleHook lifecycleHook = null;
@@ -438,10 +441,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     createNativeImpl();
                     screen.addMonitorModeListener(monitorModeListenerImpl);
                     setTitleImpl(title);
-                    if( null != pointerIcon ) {
-                        setPointerIconImpl((PointerIconImpl)pointerIcon);
-                    }
-                    setPointerVisibleImpl(pointerVisible);
+                    setPointerIconIntern(pointerIcon);
+                    setPointerVisibleIntern(pointerVisible);
                     confinePointerImpl(pointerConfined);
                     setKeyboardVisible(keyboardVisible);
                     final long remainingV = waitForVisible(true, false);
@@ -1379,6 +1380,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     return;
                 }
 
+                if( null == newParentWindow ) {
+                    // CLIENT -> TOP: Reset Parent's Pointer State
+                    setOffscreenPointerIcon(null);
+                    setOffscreenPointerVisible(true, null);
+                }
+
                 // rearrange window tree
                 if(null!=parentWindow && parentWindow instanceof Window) {
                     ((Window)parentWindow).removeChild(WindowImpl.this);
@@ -1461,6 +1468,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         }
                         destroy( becomesVisible );
                         operation = ReparentOperation.ACTION_NATIVE_CREATION ;
+                    } else {
+                        if( null != parentWindow ) {
+                            // TOP -> CLIENT: Setup Parent's Pointer State
+                            setOffscreenPointerIcon(pointerIcon);
+                            setOffscreenPointerVisible(pointerVisible, pointerIcon);
+                        }
                     }
                 } else {
                     // Case
@@ -1670,32 +1683,109 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return pointerVisible;
     }
     @Override
-    public final void setPointerVisible(boolean pointerVisible) {
+    public final void setPointerVisible(final boolean pointerVisible) {
         if(this.pointerVisible != pointerVisible) {
             boolean setVal = 0 == getWindowHandle();
             if(!setVal) {
-                setVal = setPointerVisibleImpl(pointerVisible);
+                setVal = setPointerVisibleIntern(pointerVisible);
             }
             if(setVal) {
                 this.pointerVisible = pointerVisible;
             }
         }
     }
+    private boolean setPointerVisibleIntern(final boolean pointerVisible) {
+        boolean res = setOffscreenPointerVisible(pointerVisible, pointerIcon);
+        return setPointerVisibleImpl(pointerVisible) || res; // accept onscreen or offscreen positive result!
+    }
+    /**
+     * Helper method to delegate {@link #setPointerVisibleImpl(boolean)} to
+     * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}.
+     * <p>
+     * Note: JAWTWindow is an OffscreenLayerSurface.
+     * </p>
+     * <p>
+     * Performing OffscreenLayerSurface's setCursor(..)/hideCursor(), if available,
+     * gives same behavior on all platforms.
+     * </p>
+     * <p>
+     * If visible, implementation invokes {@link #setOffscreenPointerIcon(OffscreenLayerSurface, PointerIconImpl)} using the
+     * given <code>defaultPointerIcon</code>, otherwise {@link OffscreenLayerSurface#hideCursor()} is invoked.
+     * </p>
+     * @param pointerVisible true for visible, otherwise invisible.
+     * @param defaultPointerIcon default PointerIcon for visibility
+     * @param ols the {@link OffscreenLayerSurface} instance, if null method does nothing.
+     */
+    private boolean setOffscreenPointerVisible(final boolean pointerVisible, final PointerIconImpl defaultPointerIcon) {
+        if( pointerVisible ) {
+            return setOffscreenPointerIcon(defaultPointerIcon);
+        } else {
+            final NativeWindow parent = getParent();
+            if( parent instanceof OffscreenLayerSurface ) {
+                final OffscreenLayerSurface ols = (OffscreenLayerSurface) parent;
+                try {
+                    return ols.hideCursor();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
 
     @Override
     public final PointerIcon getPointerIcon() { return pointerIcon; }
 
     @Override
     public final void setPointerIcon(final PointerIcon pi) {
-        if( this.pointerIcon != pi ) {
+        final PointerIconImpl piImpl = (PointerIconImpl)pi;
+        if( this.pointerIcon != piImpl ) {
             if( isNativeValid() ) {
                 runOnEDTIfAvail(true, new Runnable() {
                     public void run() {
-                        setPointerIconImpl((PointerIconImpl)pi);
+                        setPointerIconIntern(piImpl);
                     } } );
             }
-            this.pointerIcon = pi;
+            this.pointerIcon = piImpl;
+        }
+    }
+    private void setPointerIconIntern(final PointerIconImpl pi) {
+        setOffscreenPointerIcon(pi);
+        setPointerIconImpl(pi);
+    }
+    /**
+     * Helper method to delegate {@link #setPointerIconIntern(PointerIconImpl)} to
+     * {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}.
+     * <p>
+     * Note: JAWTWindow is an OffscreenLayerSurface.
+     * </p>
+     * <p>
+     * Performing OffscreenLayerSurface's setCursor(..), if available,
+     * gives same behavior on all platforms.
+     * </p>
+     * <p>
+     * Workaround for AWT/Windows bug within browser,
+     * where the PointerIcon gets periodically overridden
+     * by the AWT Component's icon.
+     * </p>
+     * @param ols the {@link OffscreenLayerSurface} instance, if null method does nothing.
+     * @param pi the {@link PointerIconImpl} instance, if null PointerIcon gets reset.
+     */
+    private boolean setOffscreenPointerIcon(final PointerIconImpl pi) {
+        final NativeWindow parent = getParent();
+        if( parent instanceof OffscreenLayerSurface ) {
+            final OffscreenLayerSurface ols = (OffscreenLayerSurface) parent;
+            try {
+                if( null != pi ) {
+                    return ols.setCursor(pi.getResource(), pi.getHotspot());
+                } else {
+                    return ols.setCursor(null, null); // default
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
         }
+        return false;
     }
 
     @Override
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
index edeb69f84..e2a57debc 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
@@ -39,8 +39,6 @@ import javax.media.nativewindow.GraphicsConfigurationFactory;
 import javax.media.nativewindow.NativeWindow;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.MutableSurface;
-import javax.media.nativewindow.NativeWindowFactory;
-import javax.media.nativewindow.OffscreenLayerSurface;
 import javax.media.nativewindow.VisualIDHolder;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.Point;
@@ -403,22 +401,6 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                 public void run() {
                     setPointerIcon0(getWindowHandle(), piHandle);
                 } } );
-        } else {
-            final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(this, true);
-            if( null != ols ) {
-                try {
-                    setOLSPointer(ols, pi);
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-    private static void setOLSPointer(final OffscreenLayerSurface ols, final PointerIconImpl pi) throws Exception {
-        if( null != pi ) {
-            ols.setCursor(pi.getResource(), pi.getHotspot());
-        } else {
-            ols.setCursor(null, null); // default
         }
     }
 
@@ -430,21 +412,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                 public void run() {
                     setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
                 } } );
-            return true; // setPointerVisible0 always returns true ..
-        } else {
-            final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(this, true);
-            if( null != ols ) {
-                try {
-                    if( pointerVisible ) {
-                        setOLSPointer(ols, (PointerIconImpl)getPointerIcon());
-                    } else {
-                        ols.hideCursor();
-                    }
-                    return true;
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
+            return true;
         }
         return false;
     }
-- 
cgit v1.2.3