summaryrefslogtreecommitdiffstats
path: root/src/newt/classes/jogamp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-12-31 08:14:21 +0100
committerSven Gothel <[email protected]>2013-12-31 08:14:21 +0100
commite7ffa68bce9bb707005be72530b207c732f62c31 (patch)
treedb1d2e73c89da355c8ff319febcf3c2cc2637a16 /src/newt/classes/jogamp
parente7032ae9ca4b754bd9737f86d9496211e9155db4 (diff)
Bug 934, Bug 935: NEWT: Add support for custom Application/Window and Pointer Icons
- Utilizing JOGL's PNG decoder for all icons, if available. - Application/window icons: - Providing default application/window icons in 16x16 and 32x32 size - NewtFactory.setWindowIcons(..) or property 'newt.window.icons' maybe used to override default icons. - Using icons at application/window instantiation - Display.PointerIcons: - NativeWindow Win32 WindowClass no more references a default cursor in favor of fine grained cursor control [in NEWT] - Display provides create/destroy methods, where display destruction also releases open PointerIcon references. - Window.setPointerIcon(..) sets custom PointerIcon - Implemented Platforms - X11 - Windows - OSX - Manual Test: TestGearsES2NEWT (Press 'c')
Diffstat (limited to 'src/newt/classes/jogamp')
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java68
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java22
-rw-r--r--src/newt/classes/jogamp/newt/driver/PNGIcon.java102
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java51
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java11
-rw-r--r--src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java139
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java38
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java56
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java46
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java51
10 files changed, 571 insertions, 13 deletions
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index 0c29d772a..4e9b8b441 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -34,14 +34,18 @@
package jogamp.newt;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.newt.Display;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.event.NEWTEvent;
import com.jogamp.newt.event.NEWTEventConsumer;
import jogamp.newt.event.NEWTEventTask;
+
import com.jogamp.newt.util.EDTUtil;
+import java.io.IOException;
+import java.net.MalformedURLException;
import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -62,6 +66,67 @@ public abstract class DisplayImpl extends Display {
});
}
+ public static class PointerIconImpl implements PointerIcon {
+ public final long handle;
+ public PointerIconImpl(long handle) {
+ this.handle=handle;
+ }
+ }
+
+ private void addPointerIconToList(final PointerIcon pi) {
+ synchronized(pointerIconList) {
+ pointerIconList.add(pi);
+ }
+ }
+ private void delPointerIconFromList(final PointerIcon pi) {
+ synchronized(pointerIconList) {
+ pointerIconList.remove(pi);
+ }
+ }
+ private final ArrayList<PointerIcon> pointerIconList = new ArrayList<PointerIcon>();
+
+ /** Executed from EDT! */
+ private void destroyAllPointerIconFromList(final long dpy) {
+ synchronized(pointerIconList) {
+ for( int i=0; i < pointerIconList.size(); i++ ) {
+ final PointerIcon item = pointerIconList.get(i);
+ if( null != item ) {
+ // destroy!
+ destroyPointerIconImpl(dpy, item);
+ }
+ }
+ pointerIconList.clear();
+ }
+ }
+
+ @Override
+ public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
+ final PointerIcon res = createPointerIconImpl(pngResource, hotX, hotY);
+ addPointerIconToList(res);
+ return res;
+ }
+ protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
+ return null;
+ }
+
+ @Override
+ public final void destroyPointerIcon(final PointerIcon pi) {
+ delPointerIconFromList(pi);
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ try {
+ destroyPointerIconImpl(dpy, pi);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ });
+ }
+ /** Executed from EDT! */
+ protected void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) { }
+
/** Ensure static init has been run. */
/* pp */static void initSingleton() { }
@@ -283,6 +348,7 @@ public abstract class DisplayImpl extends Display {
@Override
public void run() {
if ( null != f_aDevice ) {
+ f_dpy.destroyAllPointerIconFromList(f_aDevice.getHandle());
f_dpy.closeNativeImpl(f_aDevice);
}
}
@@ -453,7 +519,7 @@ public abstract class DisplayImpl extends Display {
/** Dispatch native Toolkit messageges */
protected abstract void dispatchMessagesNative();
- private Object eventsLock = new Object();
+ private final Object eventsLock = new Object();
private ArrayList<NEWTEventTask> events = new ArrayList<NEWTEventTask>();
private volatile boolean haveEvents = false;
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 7a7e69e48..d078caa3b 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -42,6 +42,7 @@ import java.lang.reflect.Method;
import com.jogamp.common.util.ArrayHashSet;
import com.jogamp.common.util.IntBitfield;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Display;
@@ -83,6 +84,7 @@ import javax.media.nativewindow.util.Rectangle;
import javax.media.nativewindow.util.RectangleImmutable;
import jogamp.nativewindow.SurfaceUpdatedHelper;
+import jogamp.newt.DisplayImpl.PointerIconImpl;
public abstract class WindowImpl implements Window, NEWTEventConsumer
{
@@ -170,6 +172,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 boolean pointerVisible = true;
private boolean pointerConfined = false;
private LifecycleHook lifecycleHook = null;
@@ -436,6 +439,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
createNativeImpl();
screen.addMonitorModeListener(monitorModeListenerImpl);
setTitleImpl(title);
+ if( null != pointerIcon ) {
+ setPointerIcon(pointerIcon);
+ }
setPointerVisibleImpl(pointerVisible);
confinePointerImpl(pointerConfined);
setKeyboardVisible(keyboardVisible);
@@ -725,6 +731,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected boolean setPointerVisibleImpl(boolean pointerVisible) { return false; }
protected boolean confinePointerImpl(boolean confine) { return false; }
protected void warpPointerImpl(int x, int y) { }
+ protected void setPointerIconImpl(final PointerIconImpl pi) { }
//----------------------------------------------------------------------
// NativeSurface
@@ -1675,6 +1682,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
+
+ @Override
+ public final PointerIcon getPointerIcon() { return pointerIcon; }
+
+ @Override
+ public final void setPointerIcon(final PointerIcon pi) {
+ if( this.pointerIcon != pi ) {
+ setPointerIcon(pointerIcon);
+ if( isNativeValid() ) {
+ setPointerIconImpl((PointerIconImpl)pi);
+ }
+ this.pointerIcon = pi;
+ }
+ }
+
@Override
public final boolean isPointerConfined() {
return pointerConfined;
diff --git a/src/newt/classes/jogamp/newt/driver/PNGIcon.java b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
new file mode 100644
index 000000000..c958f6ec2
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.ByteBuffer;
+
+import jogamp.newt.Debug;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.ReflectionUtil;
+
+public class PNGIcon {
+ private static final String err0 = "PNG decoder not implemented.";
+
+ private static final boolean avail;
+
+ static {
+ Debug.initSingleton();
+
+ final ClassLoader cl = PNGIcon.class.getClassLoader();
+ avail = ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl) &&
+ ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.texture.spi.PNGImage", cl);
+ }
+
+ /** Returns true if PNG decoder is available. */
+ public static boolean isAvailable() {
+ return avail;
+ }
+
+ /**
+ * Implemented for X11.
+ * @param resources
+ * @param data_size
+ * @param elem_bytesize
+ *
+ * @return BGRA8888 bytes with origin at upper-left corner where component B is located on the lowest 8-bit and component A is located on the highest 8-bit.
+ *
+ * @throws UnsupportedOperationException if not implemented
+ * @throws InterruptedException
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
+ if( avail ) {
+ return jogamp.newt.driver.opengl.JoglUtilPNGIcon.arrayToX11BGRAImages(resources, data_size, elem_bytesize);
+ }
+ throw new UnsupportedOperationException(err0);
+ }
+
+ /**
+ * Implemented for Windows.
+ * @param resources
+ * @param toBGRA if true, arranges stores in BGRA888 order, otherwise RGBA888
+ * @param width
+ * @param height
+ * @param data_size
+ * @param elem_bytesize
+ * @param resourcesIdx
+ * @return pixels with origin at upper-left corner.
+ * If storing RGBA8888, component R is located on the lowest 8-bit.
+ * If storing BGRA8888, component B is located on the lowest 8-bit.
+ * Component A is located on the highest 8-bit.
+ *
+ * @throws UnsupportedOperationException if not implemented
+ * @throws InterruptedException
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
+ if( avail ) {
+ return jogamp.newt.driver.opengl.JoglUtilPNGIcon.singleToRGBAImage(resources, resourceIdx, toBGRA, width, height, data_size, elem_bytesize);
+ }
+ throw new UnsupportedOperationException(err0);
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
index c44685dc8..86c8464a8 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
@@ -34,15 +34,26 @@
package jogamp.newt.driver.macosx;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
+import com.jogamp.newt.NewtFactory;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
+import jogamp.newt.driver.PNGIcon;
public class DisplayDriver extends DisplayImpl {
+ private static final int defaultIconWidth, defaultIconHeight;
+ private static final Buffer defaultIconData;
+
static {
NEWTJNILibLoader.loadNEWT();
@@ -52,6 +63,25 @@ public class DisplayDriver extends DisplayImpl {
if(!WindowDriver.initIDs0()) {
throw new NativeWindowException("Failed to initialize jmethodIDs");
}
+ {
+ final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 };
+ Buffer data=null;
+ if( PNGIcon.isAvailable() ) {
+ try {
+ final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
+ data = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, false /* toBGRA */, width, height, data_size, elem_bytesize);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconWidth = width[0];
+ defaultIconHeight = height[0];
+ defaultIconData = data;
+ if( null != defaultIconData ) {
+ DisplayDriver.setAppIcon0(defaultIconData, defaultIconWidth, defaultIconHeight);
+ }
+ }
+
if(DEBUG) {
System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName());
}
@@ -79,6 +109,23 @@ public class DisplayDriver extends DisplayImpl {
aDevice.close();
}
+ @Override
+ protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
+ if( PNGIcon.isAvailable() ) {
+ final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 };
+ if( null != pngResource && 0 < pngResource.resourceCount() ) {
+ final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size, elem_bytesize);
+ return new PointerIconImpl( createPointerIcon0(data, width[0], height[0], hotX, hotY) );
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) {
+ destroyPointerIcon0(((PointerIconImpl)pi).handle);
+ }
+
public static void runNSApplication() {
runNSApplication0();
}
@@ -89,5 +136,9 @@ public class DisplayDriver extends DisplayImpl {
private static native boolean initNSApplication0();
private static native void runNSApplication0();
private static native void stopNSApplication0();
+ /* pp */ static native void setAppIcon0(Object iconData, int iconWidth, int iconHeight);
+ private static native long createPointerIcon0(Object iconData, int iconWidth, int iconHeight, int hotX, int hotY);
+ private static native long destroyPointerIcon0(long handle);
+
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
index 641d7437c..a55fa915a 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
@@ -46,6 +46,7 @@ import javax.media.nativewindow.util.PointImmutable;
import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.newt.WindowImpl;
+import jogamp.newt.DisplayImpl.PointerIconImpl;
import jogamp.newt.driver.DriverClearFocus;
import jogamp.newt.driver.DriverUpdatePosition;
@@ -392,6 +393,15 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
}
@Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ setPointerIcon0(getWindowHandle(), null != pi ? pi.handle : 0);
+ } } );
+ }
+
+ @Override
protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
if( !isOffscreenInstance ) {
return setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
@@ -568,6 +578,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
private static native boolean confinePointer0(long windowHandle, boolean confine);
private static native void warpPointer0(long windowHandle, int x, int y);
+ private static native void setPointerIcon0(long windowHandle, long handle);
// Window styles
private static final int NSBorderlessWindowMask = 0;
diff --git a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
new file mode 100644
index 000000000..ea9029006
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
@@ -0,0 +1,139 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver.opengl;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.texture.spi.PNGImage;
+
+public class JoglUtilPNGIcon {
+
+ public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
+ final PNGImage[] images = new PNGImage[resources.resourceCount()];
+ data_size[0] = 0;
+ for(int i=0; i<resources.resourceCount(); i++) {
+ final URLConnection urlConn = resources.resolve(i);
+ final PNGImage image = PNGImage.read(urlConn.getInputStream());
+ data_size[0] += 2 + image.getWidth() * image.getHeight();
+ images[i] = image;
+ }
+ final boolean is64Bit = Platform.is64Bit();
+ elem_bytesize[0] = is64Bit ? Buffers.SIZEOF_LONG : Buffers.SIZEOF_INT;
+ final ByteBuffer buffer = Buffers.newDirectByteBuffer( data_size[0] * elem_bytesize[0] );
+
+ for(int i=0; i<images.length; i++) {
+ final PNGImage image1 = images[i];
+ if( is64Bit ) {
+ buffer.putLong(image1.getWidth());
+ buffer.putLong(image1.getHeight());
+ } else {
+ buffer.putInt(image1.getWidth());
+ buffer.putInt(image1.getHeight());
+ }
+ final ByteBuffer bb = image1.getData();
+ final int bpp = image1.getBytesPerPixel();
+ final int stride = image1.getWidth() * bpp;
+ for(int y=0; y<image1.getHeight(); y++) {
+ int bbOff = image1.isGLOriented() ? ( image1.getHeight() - 1 - y ) * stride : y * stride;
+ for(int x=0; x<image1.getWidth(); x++) {
+ // Source: R G B A
+ // Dest: B G R A
+ long pixel;
+ pixel = ( 0xffL & bb.get(bbOff++) ) << 16; // R
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 8; // G
+ pixel |= ( 0xffL & bb.get(bbOff++) ); // B
+ if( 4 == bpp ) {
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 24;
+ } else {
+ pixel |= 0x00000000ff000000L;
+ }
+ if( is64Bit ) {
+ buffer.putLong(pixel);
+ } else {
+ buffer.putInt((int)pixel);
+ }
+ }
+ }
+ }
+ buffer.rewind();
+ return buffer;
+ }
+
+ public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
+ width[0] = 0;
+ height[0] = 0;
+ data_size[0] = 0;
+ final URLConnection urlConn = resources.resolve(resourceIdx);
+ final PNGImage image = PNGImage.read(urlConn.getInputStream());
+ width[0] = image.getWidth();
+ height[0] = image.getHeight();
+ data_size[0] = image.getWidth() * image.getHeight();
+
+ elem_bytesize[0] = 4; // BGRA
+ final ByteBuffer buffer = Buffers.newDirectByteBuffer( data_size[0] * elem_bytesize[0] );
+
+ final ByteBuffer bb = image.getData();
+ final int bpp = image.getBytesPerPixel();
+ final int stride = image.getWidth() * bpp;
+ for(int y=0; y<image.getHeight(); y++) {
+ int bbOff = image.isGLOriented() ? ( image.getHeight() - 1 - y ) * stride : y * stride;
+ for(int x=0; x<image.getWidth(); x++) {
+ // Source: R G B A
+ final byte r, g, b, a;
+ r = bb.get(bbOff++); // R
+ g = bb.get(bbOff++); // G
+ b = bb.get(bbOff++); // B
+ if( 4 == bpp ) {
+ a = bb.get(bbOff++); // A
+ } else {
+ a = (byte)0xff; // A
+ }
+ if( toBGRA ) {
+ // Dest: B G R A
+ buffer.put(b);
+ buffer.put(g);
+ buffer.put(r);
+ } else {
+ // Dest: R G B A
+ buffer.put(r);
+ buffer.put(g);
+ buffer.put(b);
+ }
+ buffer.put(a);
+ }
+ }
+ buffer.rewind();
+ return buffer;
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
index c4cfd98b3..8d4d8972b 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
@@ -34,13 +34,22 @@
package jogamp.newt.driver.windows;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import jogamp.nativewindow.windows.RegisteredClass;
import jogamp.nativewindow.windows.RegisteredClassFactory;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
+import jogamp.newt.driver.PNGIcon;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
public class DisplayDriver extends DisplayImpl {
@@ -92,9 +101,38 @@ public class DisplayDriver extends DisplayImpl {
return sharedClass.getName();
}
+ @Override
+ protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
+ if( PNGIcon.isAvailable() ) {
+ final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 };
+ if( null != pngResource && 0 < pngResource.resourceCount() ) {
+ final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size, elem_bytesize);
+ return new PointerIconImpl( createBGRA8888Icon0(data, width[0], height[0], true, hotX, hotY) );
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) {
+ destroyIcon0(((PointerIconImpl)pi).handle);
+ }
+
//----------------------------------------------------------------------
// Internals only
//
private static native void DispatchMessages0();
+
+ static long createBGRA8888Icon0(Buffer data, int width, int height, boolean isCursor, int hotX, int hotY) {
+ if( null == data ) {
+ throw new IllegalArgumentException("data buffer/size");
+ }
+ if( !Buffers.isDirect(data) ) {
+ throw new IllegalArgumentException("data buffer is not direct "+data);
+ }
+ return createBGRA8888Icon0(data, Buffers.getDirectBufferByteOffset(data), width, height, isCursor, hotX, hotY);
+ }
+ private static native long createBGRA8888Icon0(Object data, int data_offset, int width, int height, boolean isCursor, int hotX, int hotY);
+ private static native void destroyIcon0(long handle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index 6e8ac3efa..3239aab5b 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -34,9 +34,13 @@
package jogamp.newt.driver.windows;
+import java.nio.ByteBuffer;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIUtil;
import jogamp.newt.WindowImpl;
+import jogamp.newt.DisplayImpl.PointerIconImpl;
+import jogamp.newt.driver.PNGIcon;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
@@ -47,23 +51,46 @@ import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseEvent.PointerType;
public class WindowDriver extends WindowImpl {
+ private static final long[] defaultIconHandles;
+
+ static {
+ DisplayDriver.initSingleton();
+ {
+ long[] _defaultIconHandle = { 0, 0 };
+ if( PNGIcon.isAvailable() ) {
+ try {
+ final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 };
+ final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
+ {
+ final ByteBuffer icon_data_small = PNGIcon.singleToRGBAImage(iconRes, 0, true /* toBGRA */, width, height, data_size, elem_bytesize);
+ _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(icon_data_small, width[0], height[0], false, 0, 0);
+ }
+ {
+ final ByteBuffer icon_data_big = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, true /* toBGRA */, width, height, data_size, elem_bytesize);
+ _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(icon_data_big, width[0], height[0], false, 0, 0);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconHandles = _defaultIconHandle;
+ }
+ }
private long hmon;
private long hdc;
private long hdc_old;
private long windowHandleClose;
- static {
- DisplayDriver.initSingleton();
- }
-
public WindowDriver() {
}
@@ -142,7 +169,8 @@ public class WindowDriver extends WindowImpl {
( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
final long _windowHandle = CreateWindow0(DisplayDriver.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
winVer.getMajor(), winVer.getMinor(),
- getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags);
+ getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags,
+ defaultIconHandles[0], defaultIconHandles[1]);
if ( 0 == _windowHandle ) {
throw new NativeWindowException("Error creating window");
}
@@ -159,8 +187,8 @@ public class WindowDriver extends WindowImpl {
@Override
protected void closeNativeImpl() {
- if(windowHandleClose != 0) {
- if (hdc != 0) {
+ if( 0 != windowHandleClose ) {
+ if ( 0 != hdc ) {
try {
GDI.ReleaseDC(windowHandleClose, hdc);
} catch (Throwable t) {
@@ -177,10 +205,9 @@ public class WindowDriver extends WindowImpl {
Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
e.printStackTrace();
}
- } finally {
- windowHandleClose = 0;
}
}
+ windowHandleClose = 0;
hdc = 0;
hdc_old = 0;
}
@@ -224,6 +251,11 @@ public class WindowDriver extends WindowImpl {
}
@Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ setPointerIcon0(getWindowHandle(), null != pi ? pi.handle : 0);
+ }
+
+ @Override
protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
final boolean[] res = new boolean[] { false };
@@ -361,7 +393,8 @@ public class WindowDriver extends WindowImpl {
protected static native boolean initIDs0(long hInstance);
private native long CreateWindow0(long hInstance, String wndClassName, String wndName, int winMajor, int winMinor,
- long parentWindowHandle, int x, int y, int width, int height, boolean autoPosition, int flags);
+ long parentWindowHandle, int x, int y, int width, int height, boolean autoPosition, int flags,
+ long iconSmallHandle, long iconBigHandle);
private native long MonitorFromWindow0(long windowHandle);
private native void reconfigureWindow0(long parentWindowHandle, long windowHandle,
int x, int y, int width, int height, int flags);
@@ -371,4 +404,7 @@ public class WindowDriver extends WindowImpl {
private static native boolean setPointerVisible0(long windowHandle, boolean visible);
private static native boolean confinePointer0(long windowHandle, boolean grab, int l, int t, int r, int b);
private static native void warpPointer0(long windowHandle, int x, int y);
+ private static native ByteBuffer newDirectByteBuffer(long addr, long capacity);
+
+ private static native void setPointerIcon0(long windowHandle, long iconHandle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index 504839797..8170c2e3d 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -34,14 +34,22 @@
package jogamp.newt.driver.x11;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
+import jogamp.newt.driver.PNGIcon;
public class DisplayDriver extends DisplayImpl {
@@ -120,6 +128,35 @@ public class DisplayDriver extends DisplayImpl {
/** Returns <code>null</code> if !{@link #isNativeValid()}, otherwise the Boolean value of {@link X11GraphicsDevice#isXineramaEnabled()}. */
protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; }
+ @Override
+ protected PointerIcon createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
+ if( PNGIcon.isAvailable() ) {
+ final int[] width = { 0 }, height = { 0 }, data_size = { 0 }, elem_bytesize = { 0 };
+ if( null != pngResource && 0 < pngResource.resourceCount() ) {
+ final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, false /* toBGRA */, width, height, data_size, elem_bytesize);
+ final long handle = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Long>() {
+ @Override
+ public Long run(long dpy) {
+ long h = 0;
+ try {
+ h = createPointerIcon0(dpy, data, width[0], height[0], hotX, hotY);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return Long.valueOf(h);
+ }
+ }).longValue();
+ return new PointerIconImpl(handle);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, final PointerIcon pi) {
+ destroyPointerIcon0(displayHandle, ((PointerIconImpl)pi).handle);
+ }
+
//----------------------------------------------------------------------
// Internals only
//
@@ -137,6 +174,15 @@ public class DisplayDriver extends DisplayImpl {
private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now
+ static long createPointerIcon0(long display, Buffer data, int width, int height, int hotX, int hotY) {
+ if( !Buffers.isDirect(data) ) {
+ throw new IllegalArgumentException("data buffer is not direct "+data);
+ }
+ return createPointerIcon0(display, data, Buffers.getDirectBufferByteOffset(data), width, height, hotX, hotY);
+ }
+ private static native long createPointerIcon0(long display, Object data, int data_offset, int width, int height, int hotX, int hotY);
+ static native void destroyPointerIcon0(long display, long handle);
+
/** X11 Window delete atom marker used on EDT */
private long windowDeleteAtom;
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index f2a27b0c9..0ea2c5358 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -34,11 +34,16 @@
package jogamp.newt.driver.x11;
+import java.nio.Buffer;
+
import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.DisplayImpl;
import jogamp.newt.DisplayImpl.DisplayRunnable;
+import jogamp.newt.DisplayImpl.PointerIconImpl;
import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.PNGIcon;
+
import javax.media.nativewindow.*;
import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.util.Insets;
@@ -47,6 +52,7 @@ import javax.media.nativewindow.util.Point;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.MouseEvent;
@@ -58,8 +64,29 @@ public class WindowDriver extends WindowImpl {
private static final int X11_WHEEL_TWO_UP_BUTTON = 6;
private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7;
+ private static final int defaultIconDataSize;
+ private static final Buffer defaultIconData;
+
static {
ScreenDriver.initSingleton();
+
+ int _icon_data_size=0, _icon_elem_bytesize=0;
+ Buffer _icon_data=null;
+ if( PNGIcon.isAvailable() ) {
+ try {
+ final int[] data_size = { 0 }, elem_bytesize = { 0 };
+ _icon_data = PNGIcon.arrayToX11BGRAImages(NewtFactory.getWindowIcons(), data_size, elem_bytesize);
+ _icon_data_size = data_size[0];
+ _icon_elem_bytesize = elem_bytesize[0];
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconDataSize = _icon_data_size;
+ defaultIconData = _icon_data;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Def. Icon: data_size "+defaultIconDataSize+" * elem_size "+_icon_elem_bytesize+" = data "+defaultIconData);
+ }
}
public WindowDriver() {
@@ -100,7 +127,8 @@ public class WindowDriver extends WindowImpl {
setWindowHandle(CreateWindow0(getParentWindowHandle(),
edtDevice.getHandle(), screen.getIndex(), visualID,
display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
- getX(), getY(), getWidth(), getHeight(), autoPosition(), flags));
+ getX(), getY(), getWidth(), getHeight(), autoPosition(), flags,
+ defaultIconDataSize, defaultIconData));
} finally {
edtDevice.unlock();
}
@@ -246,6 +274,21 @@ public class WindowDriver extends WindowImpl {
}
@Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ try {
+ setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.handle : 0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ });
+ }
+
+ @Override
protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Boolean>() {
@Override
@@ -381,13 +424,17 @@ public class WindowDriver extends WindowImpl {
private native long CreateWindow0(long parentWindowHandle, long display, int screen_index,
int visualID, long javaObjectAtom, long windowDeleteAtom,
- int x, int y, int width, int height, boolean autoPosition, int flags);
+ int x, int y, int width, int height, boolean autoPosition, int flags,
+ int iconDataSize, Object iconData);
private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/ ); // XKB disabled for now
private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
long windowDeleteAtom, int x, int y, int width, int height, int flags);
private native void requestFocus0(long display, long windowHandle, boolean force);
private static native void setTitle0(long display, long windowHandle, String title);
+
+ private static native void setPointerIcon0(long display, long windowHandle, long handle);
+
private static native long getParentWindow0(long display, long windowHandle);
private static native boolean setPointerVisible0(long display, long windowHandle, boolean visible);
private static native boolean confinePointer0(long display, long windowHandle, boolean grab);