diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 2afa464..bc83dd1 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -47,6 +47,7 @@ import com.jogamp.nativewindow.CapabilitiesImmutable; import com.jogamp.nativewindow.NativeWindow; import com.jogamp.nativewindow.ScalableSurface; import com.jogamp.nativewindow.WindowClosingProtocol; +import com.jogamp.nativewindow.util.PixelRectangle; import com.jogamp.nativewindow.util.Rectangle; import com.jogamp.nativewindow.util.RectangleImmutable; import com.jogamp.nativewindow.util.SurfaceSize; @@ -399,6 +400,28 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur void setTitle(String title); String getTitle(); + + /** + * Set window icon.
+ * + *

+ * The given icon will replace the default icon for this frame only. + * If the icon is null the default icon will be used instead.
+ * The default application icon can be set using the system properties with + * the key 'newt.window.icons'. More informations on the default application + * icon can be found in the Window class javadoc. + *

+ * + * @param icon frame icon or null for default icon. + */ + void setIcon(PixelRectangle icon); + + /** + * Get window icon.
+ * + * @return window icon, can be null + */ + PixelRectangle getIcon(); /** @see #setPointerVisible(boolean) */ boolean isPointerVisible(); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 3ef017d..5389d14 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -75,6 +75,7 @@ import jogamp.opengl.GLDrawableImpl; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.util.VersionUtil; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.nativewindow.util.PixelRectangle; import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; @@ -527,6 +528,16 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind return window.getLocationOnScreen(storage); } + @Override + public void setIcon(PixelRectangle icon) { + window.setIcon(icon); + } + + @Override + public PixelRectangle getIcon() { + return window.getIcon(); + } + // Hide methods here .. protected class GLLifecycleHook implements WindowImpl.LifecycleHook { diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 8e31d1d..7660d8c 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -182,6 +182,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private boolean nfs_alwaysOnTop; // non fullscreen alwaysOnTop setting private NativeWindow nfs_parent = null; // non fullscreen parent, in case explicit reparenting is performed (offscreen) private String title = "Newt Window"; + private PixelRectangle icon = null; private boolean undecorated = false; private boolean alwaysOnTop = false; private PointerIconImpl pointerIcon = null; @@ -716,6 +717,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected void setTitleImpl(final String title) {} + protected void setIconImpl(final PixelRectangle icon) {} + /** * Translates the given window client-area coordinates with top-left origin * to screen coordinates in window units. @@ -1739,6 +1742,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } @Override + public final PixelRectangle getIcon() { + return icon; + } + @Override + public final void setIcon(PixelRectangle icon) { + if(this.icon==icon) return; + + this.icon = icon; + if(0 != getWindowHandle()) { + if(icon==null){ + //reset default icon + setIconImpl(null); + }else{ + setIconImpl(icon); + } + } + } + + @Override public final boolean isPointerVisible() { return pointerVisible; } diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java index 6cf9727..9985638 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -52,6 +52,8 @@ import com.jogamp.nativewindow.util.Point; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; +import com.jogamp.nativewindow.util.DimensionImmutable; +import com.jogamp.nativewindow.util.PixelRectangle; import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; import com.jogamp.newt.NewtFactory; @@ -276,6 +278,34 @@ public class WindowDriver extends WindowImpl { } }); } + + @Override + protected void setIconImpl(final PixelRectangle icon) { + if(icon!=null){ + final DimensionImmutable size = icon.getSize(); + final int pixelDataSize = size.getWidth() * size.getHeight() * icon.getPixelformat().comp.bytesPerPixel(); + final Buffer pixels = icon.getPixels(); + + runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + @Override + public Object run(final long dpy) { + setWindowIcon0(dpy, getWindowHandle(),pixelDataSize, + pixels,Buffers.getDirectBufferByteOffset(pixels),true /* pixels_is_direct */); + return null; + } + }); + }else if(defaultIconData!=null){ + //set default icon + runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable() { + @Override + public Object run(final long dpy) { + setWindowIcon0(dpy, getWindowHandle(),defaultIconDataSize, + defaultIconData,Buffers.getDirectBufferByteOffset(defaultIconData),true /* pixels_is_direct */); + return null; + } + }); + } + } @Override protected void setPointerIconImpl(final PointerIconImpl pi) { @@ -452,6 +482,8 @@ public class WindowDriver extends WindowImpl { int visualID, long javaObjectAtom, long windowDeleteAtom, int x, int y, int width, int height, boolean autoPosition, int flags, int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct); + private native long setWindowIcon0(long display, long windowHandle, int pixelDataSize, + Object pixels, int pixels_byte_offset, boolean pixels_is_direct); private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/, // XKB disabled for now final int randr_event_base, final int randr_error_base); private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle, diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index e640b0c..e00d323 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -692,6 +692,39 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 /* * Class: jogamp_newt_driver_x11_WindowDriver + * Method: SetWindowIcon + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setWindowIcon0 + (JNIEnv *env, jobject obj, jlong display, jlong windowHandle, jint pixelDataSize, jobject pixels, + jint pixels_byte_offset, jboolean pixels_is_direct) +{ + Display * dpy = (Display *)(intptr_t)display; + Window window = (Window)windowHandle; + + const unsigned char * pixelPtr = NULL; + + // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly! + DBG_PRINT("X11: CreateWindow icon: size %d, pixels %p, offset %d, direct %d\n", pixelDataSize, (void*)pixels, pixels_byte_offset, pixels_is_direct); + if( 0 < pixelDataSize && NULL != pixels ) { + pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ? + (*env)->GetDirectBufferAddress(env, pixels) : + (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); + DBG_PRINT("X11: CreateWindow icon: NIO %p\n", pixelPtr); + NewtWindows_setIcon(dpy, window, (int)pixelDataSize, pixelPtr+pixels_byte_offset); + } + + XMapWindow(dpy, window); + //XUnmapWindow(dpy, w); + XSync(dpy, False); + + if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) { + (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); + } + +} + +/* + * Class: jogamp_newt_driver_x11_WindowDriver * Method: CloseWindow * Signature: (JJ)V */